<script setup lang="ts">
/**
 * 文章编辑表单：结构化字段 + 简易 Markdown 工具条（插图走附件上传）。
 * 分类/专栏用 wd-picker，空列时塞占位项，避免 wot 内部 map 读 value of undefined。
 * 版本历史/访问日志共用一个 page-container（小程序同页只能有一个）。
 */
import { computed, reactive, ref } from 'vue'
import { onLoad, onShow } from '@dcloudio/uni-app'
import { useToast } from '@wot-ui/ui'
import AppNavbar from '@/components/layout/AppNavbar.vue'
import AppPageShell from '@/components/layout/AppPageShell.vue'
import AdminMediaPicker from '../../components/AdminMediaPicker.vue'
import AdminDetailDrawer from '../../components/AdminDetailDrawer.vue'
import AdminFormField from '../../components/AdminFormField.vue'
import { useAdminGuard } from '../../composables/useAdminGuard'
import {
  adminCreate,
  adminGetPost,
  adminList,
  adminUpdate,
  getPostAccessLogs,
  getPostHistory,
  normalizeAdminList,
  restorePostVersion,
  uploadAttachment,
  type Post,
} from '@/api'

const toast = useToast()
const { guardAdmin } = useAdminGuard()

const mode = ref<'create' | 'edit'>('create')
const id = ref('')
const loading = ref(false)
const submitting = ref(false)
const categories = ref<{ id: number, name: string }[]>([])
/** 专栏列表；勿命名 columns，避免与 wd-picker 的 columns 属性混淆 */
const columnList = ref<{ id: number, name?: string, title?: string }[]>([])
const tags = ref<{ id: number, name: string }[]>([])
const selectedTagIds = ref<number[]>([])

const form = reactive({
  title: '',
  excerpt: '',
  content: '',
  cover: '',
  categoryId: '' as string | number,
  columnId: '' as string | number,
  date: '',
  isPublished: 1,
})

/** 单一抽屉：history | access，避免双 page-container */
const drawerShow = ref(false)
const drawerMode = ref<'history' | 'access'>('history')
const historyRows = ref<{ label: string, value: string }[]>([])
const historyVersions = ref<{ version?: number | string, createdAt?: string }[]>([])
const accessRows = ref<{ label: string, value: string }[]>([])

const pageTitle = computed(() => (mode.value === 'create' ? '新建文章' : '编辑文章'))
const drawerTitle = computed(() => (drawerMode.value === 'history' ? '版本历史' : '访问日志'))
const drawerRows = computed(() =>
  drawerMode.value === 'history' ? historyRows.value : accessRows.value,
)

/**
 * wd-picker 列数据：空数组会触发内部 selectWithValue 崩溃，故至少给一项占位。
 */
const categoryColumns = computed(() => {
  const list = categories.value.map(c => ({ label: c.name, value: c.id }))
  return [list.length ? list : [{ label: '暂无分类', value: '' }]]
})
const columnColumns = computed(() => {
  const list = columnList.value.map(c => ({
    label: c.name || c.title || String(c.id),
    value: c.id,
  }))
  return [list.length ? list : [{ label: '暂无专栏', value: '' }]]
})

function insertMd(prefix: string, suffix = '') {
  form.content = `${form.content}${prefix}${suffix}`
}

async function insertImage() {
  try {
    const res = await uni.chooseImage({ count: 1, sizeType: ['compressed'] })
    const path = res.tempFilePaths?.[0]
    if (!path) return
    const uploaded = await uploadAttachment(path)
    const url = uploaded.fileUrl || uploaded.url || ''
    if (url) insertMd(`\n![](${url})\n`)
  }
  catch (e: unknown) {
    if (e && typeof e === 'object' && 'errMsg' in e && String((e as { errMsg: string }).errMsg).includes('cancel')) return
    toast.error(e instanceof Error ? e.message : '插图失败')
  }
}

async function loadMeta() {
  const [cats, cols, tgs] = await Promise.all([
    adminList('categories').catch(() => []),
    adminList('columns').catch(() => []),
    adminList('tags').catch(() => []),
  ])
  categories.value = normalizeAdminList(cats) as { id: number, name: string }[]
  columnList.value = normalizeAdminList(cols) as { id: number, name?: string, title?: string }[]
  tags.value = normalizeAdminList(tgs) as { id: number, name: string }[]
}

async function load() {
  if (!guardAdmin()) return
  loading.value = true
  try {
    await loadMeta()
    if (mode.value === 'edit' && id.value) {
      // 走后台详情接口（含未发布），勿用公开 getPost / 已删除的 adminGet posts
      const data = await adminGetPost(id.value)
      form.title = String(data.title || '')
      form.excerpt = String(data.excerpt || data.summary || '')
      form.content = String(data.content || '')
      form.cover = String(data.cover || '')
      form.categoryId = (data.categoryId as number) || ''
      form.columnId = (data.columnId as number) || ''
      form.date = String(data.date || '')
      form.isPublished = data.isPublished === 0 || data.isPublished === false ? 0 : 1
      selectedTagIds.value = (data.tags || []).map(t => Number(t.id))
    }
  }
  catch (e: unknown) {
    toast.error(e instanceof Error ? e.message : '加载失败')
  }
  finally {
    loading.value = false
  }
}

onLoad((q) => {
  mode.value = q?.mode === 'edit' ? 'edit' : 'create'
  id.value = String(q?.id || '')
})
onShow(load)

function toggleTag(tid: number) {
  const i = selectedTagIds.value.indexOf(tid)
  if (i >= 0) selectedTagIds.value.splice(i, 1)
  else selectedTagIds.value.push(tid)
}

function onCatConfirm(payload: { value?: unknown[] }) {
  const v = payload?.value?.[0]
  const raw = (v && typeof v === 'object' && 'value' in v)
    ? (v as { value: unknown }).value
    : v
  form.categoryId = (raw as number) || ''
}

function onColConfirm(payload: { value?: unknown[] }) {
  const v = payload?.value?.[0]
  const raw = (v && typeof v === 'object' && 'value' in v)
    ? (v as { value: unknown }).value
    : v
  form.columnId = (raw as number) || ''
}

async function onSubmit() {
  if (!form.title.trim()) {
    toast.show('请填写标题')
    return
  }
  submitting.value = true
  try {
    const payload = {
      title: form.title,
      excerpt: form.excerpt,
      content: form.content,
      cover: form.cover,
      categoryId: form.categoryId ? Number(form.categoryId) : undefined,
      columnId: form.columnId ? Number(form.columnId) : undefined,
      date: form.date || undefined,
      isPublished: form.isPublished,
      tagIds: selectedTagIds.value,
    }
    if (mode.value === 'edit' && id.value) await adminUpdate('posts', id.value, payload)
    else await adminCreate('posts', payload)
    toast.success('已保存')
    setTimeout(() => uni.navigateBack(), 400)
  }
  catch (e: unknown) {
    toast.error(e instanceof Error ? e.message : '保存失败')
  }
  finally {
    submitting.value = false
  }
}

async function openHistory() {
  if (!id.value) return
  try {
    const list = await getPostHistory(id.value)
    historyVersions.value = (Array.isArray(list) ? list : []) as typeof historyVersions.value
    historyRows.value = historyVersions.value.map((v, i) => ({
      label: `版本 ${v.version ?? i + 1}`,
      value: String(v.createdAt || ''),
    }))
    drawerMode.value = 'history'
    drawerShow.value = true
  }
  catch (e: unknown) {
    toast.error(e instanceof Error ? e.message : '加载历史失败')
  }
}

async function restore(version: string | number) {
  try {
    await restorePostVersion(id.value, version)
    toast.success('已恢复')
    drawerShow.value = false
    load()
  }
  catch (e: unknown) {
    toast.error(e instanceof Error ? e.message : '恢复失败')
  }
}

async function openAccess() {
  if (!id.value) return
  try {
    const data = await getPostAccessLogs(id.value, { page: 1, pageSize: 20 })
    const list = Array.isArray(data) ? data : data.list || []
    accessRows.value = list.map((row: unknown, i: number) => {
      const r = row as Record<string, unknown>
      return {
        label: `#${i + 1} ${r.path || r.ip || ''}`,
        value: String(r.createdAt || r.region || ''),
      }
    })
    drawerMode.value = 'access'
    drawerShow.value = true
  }
  catch (e: unknown) {
    toast.error(e instanceof Error ? e.message : '加载访问日志失败')
  }
}

function catLabel() {
  return categories.value.find(c => String(c.id) === String(form.categoryId))?.name || '选择分类'
}
function colLabel() {
  const c = columnList.value.find(c => String(c.id) === String(form.columnId))
  return c?.name || c?.title || '选择专栏（可选）'
}
</script>

<template>
  <AppPageShell admin>
    <AppNavbar :title="pageTitle" show-back />
    <view class="page-pad">
      <view class="admin-card form-card">
        <AdminFormField label="标题" required>
          <wd-input v-model="form.title" placeholder="请输入标题" clearable />
        </AdminFormField>
        <AdminFormField label="摘要">
          <wd-textarea v-model="form.excerpt" placeholder="文章摘要" />
        </AdminFormField>
        <AdminMediaPicker v-model="form.cover" label="封面" />
        <wd-picker :columns="categoryColumns" @confirm="onCatConfirm">
          <view class="picker-row"><text>分类</text><text class="val">{{ catLabel() }}</text></view>
        </wd-picker>
        <wd-picker :columns="columnColumns" @confirm="onColConfirm">
          <view class="picker-row"><text>专栏</text><text class="val">{{ colLabel() }}</text></view>
        </wd-picker>
        <AdminFormField label="日期">
          <wd-input v-model="form.date" placeholder="YYYY-MM-DD" clearable />
        </AdminFormField>
        <view class="switch-row">
          <text>发布</text>
          <wd-switch :model-value="!!form.isPublished" @change="(v: boolean) => form.isPublished = v ? 1 : 0" />
        </view>
        <view class="tags">
          <text class="label text-art-muted">标签</text>
          <view class="tag-wrap">
            <view
              v-for="t in tags"
              :key="t.id"
              class="tag"
              :class="{ on: selectedTagIds.includes(t.id) }"
              @click="toggleTag(t.id)"
            >
              {{ t.name }}
            </view>
          </view>
        </view>
        <view class="md-tools">
          <wd-button size="small" plain @click="insertMd('**', '**')">加粗</wd-button>
          <wd-button size="small" plain @click="insertMd('[链接](', ')')">链接</wd-button>
          <wd-button size="small" plain @click="insertImage">插图</wd-button>
        </view>
        <AdminFormField label="正文 Markdown" required>
          <wd-textarea v-model="form.content" placeholder="支持 Markdown" :rows="12" />
        </AdminFormField>
        <view v-if="mode === 'edit'" class="extra">
          <wd-button size="small" plain @click="openHistory">版本历史</wd-button>
          <wd-button size="small" plain @click="openAccess">访问日志</wd-button>
        </view>
        <wd-button
          block
          type="primary"
          :loading="submitting"
          custom-style="margin-top:24rpx;background:#d4b383;border-color:#d4b383;"
          @click="onSubmit"
        >
          保存
        </wd-button>
      </view>
      <wd-loading v-if="loading" />
    </view>

    <AdminDetailDrawer v-model:show="drawerShow" :title="drawerTitle" :rows="drawerRows">
      <template v-if="drawerMode === 'history'">
        <view v-for="(v, i) in historyVersions" :key="i" class="hist-row">
          <wd-button size="small" @click="restore(v.version ?? i + 1)">恢复此版本</wd-button>
        </view>
      </template>
    </AdminDetailDrawer>
  </AppPageShell>
</template>

<style scoped lang="scss">
.page-pad { padding: 24rpx 32rpx 80rpx; }
.picker-row, .switch-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 20rpx 0;
  color: rgb(var(--art-text));
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.val { color: rgba(255, 255, 255, 0.6); font-size: 26rpx; }
.tags { margin: 16rpx 0; }
.label { font-size: 24rpx; }
.tag-wrap { display: flex; flex-wrap: wrap; gap: 12rpx; margin-top: 12rpx; }
.tag {
  padding: 8rpx 18rpx;
  border-radius: 8rpx;
  font-size: 24rpx;
  background: rgba(255, 255, 255, 0.06);
  color: rgba(255, 255, 255, 0.65);
}
.tag.on { background: rgba(212, 179, 131, 0.25); color: rgb(var(--art-accent)); }
.md-tools { display: flex; gap: 12rpx; margin: 16rpx 0; flex-wrap: wrap; }
.extra { display: flex; gap: 12rpx; margin-top: 16rpx; }
.hist-row { margin: 8rpx 0; }
</style>
