<script setup lang="ts">
/**
 * 作品表单：封面/图集/技术栈/外链/演示视频。
 */
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 { useAdminGuard } from '../../composables/useAdminGuard'
import { adminCreate, adminGet, adminUpdate, type Work, type WorkTechGroup } from '@/api'
import { resolveMediaUrl } from '@/utils/request'
import { uploadAttachment } 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 form = reactive({
  title: '',
  category: '',
  year: '',
  heroImg: '',
  heroVideo: '',
  desc: '',
  live: '',
  github: '',
  demo: '',
})
const techStack = ref<WorkTechGroup[]>([{ category: 'Frontend', items: [] }])
const gallery = ref<string[]>([])
const techInput = ref('')

const pageTitle = computed(() => (mode.value === 'create' ? '新建作品' : '编辑作品'))

async function load() {
  if (!guardAdmin()) return
  if (mode.value !== 'edit' || !id.value) return
  loading.value = true
  try {
    const data = await adminGet('works', id.value) as Work
    form.title = String(data.title || '')
    form.category = String(data.category || '')
    form.year = String(data.year || '')
    form.heroImg = String(data.heroImg || '')
    form.heroVideo = String(data.heroVideo || data.videoUrl || '')
    form.desc = String(data.desc || data.description || '')
    const links = typeof data.links === 'string'
      ? (() => { try { return JSON.parse(data.links) } catch { return {} } })()
      : (data.links || {})
    form.live = String((links as Record<string, string>).live || '')
    form.github = String((links as Record<string, string>).github || '')
    form.demo = String((links as Record<string, string>).demo || '')
    techStack.value = Array.isArray(data.techStack) && data.techStack.length
      ? data.techStack
      : [{ category: 'Frontend', items: [] }]
    gallery.value = Array.isArray(data.gallery) ? [...data.gallery] : []
  }
  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 addTechTag() {
  const t = techInput.value.trim()
  if (!t) return
  if (!techStack.value[0]) techStack.value = [{ category: 'Frontend', items: [] }]
  techStack.value[0].items = [...(techStack.value[0].items || []), t]
  techInput.value = ''
}

function removeTech(i: number) {
  techStack.value[0]?.items?.splice(i, 1)
}

async function addGallery() {
  if (gallery.value.length >= 20) {
    toast.show('最多 20 张')
    return
  }
  try {
    const res = await uni.chooseImage({ count: Math.min(9, 20 - gallery.value.length), sizeType: ['compressed'] })
    for (const path of res.tempFilePaths || []) {
      const up = await uploadAttachment(path)
      const url = up.fileUrl || up.url
      if (url) gallery.value.push(url)
    }
  }
  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 onSubmit() {
  if (!form.title.trim()) {
    toast.show('请填写标题')
    return
  }
  submitting.value = true
  try {
    const payload = {
      title: form.title,
      category: form.category,
      year: form.year,
      heroImg: form.heroImg,
      heroVideo: form.heroVideo,
      desc: form.desc,
      techStack: techStack.value,
      gallery: gallery.value,
      links: { live: form.live, github: form.github, demo: form.demo },
    }
    if (mode.value === 'edit' && id.value) await adminUpdate('works', id.value, payload)
    else await adminCreate('works', payload)
    toast.success('已保存')
    setTimeout(() => uni.navigateBack(), 400)
  }
  catch (e: unknown) {
    toast.error(e instanceof Error ? e.message : '保存失败')
  }
  finally {
    submitting.value = false
  }
}
</script>

<template>
  <AppPageShell admin>
    <AppNavbar :title="pageTitle" show-back />
    <view class="page-pad">
      <view class="admin-card form-card">
        <wd-input v-model="form.title" label="标题" clearable />
        <wd-input v-model="form.category" label="分类" clearable />
        <wd-input v-model="form.year" label="年份" clearable />
        <AdminMediaPicker v-model="form.heroImg" label="封面图" />
        <AdminMediaPicker v-model="form.heroVideo" label="演示视频" media-type="video" />
        <wd-textarea v-model="form.desc" label="描述" />
        <view class="section">
          <text class="label text-art-muted">技术栈</text>
          <view class="tag-wrap">
            <view v-for="(t, i) in techStack[0]?.items || []" :key="i" class="tag" @click="removeTech(i)">{{ t }} ×</view>
          </view>
          <view class="row-input">
            <wd-input v-model="techInput" placeholder="添加技术标签" clearable />
            <wd-button size="small" @click="addTechTag">添加</wd-button>
          </view>
        </view>
        <view class="section">
          <text class="label text-art-muted">图集 ({{ gallery.length }}/20)</text>
          <view class="gallery">
            <image v-for="(g, i) in gallery" :key="i" class="g-img" :src="resolveMediaUrl(g)" mode="aspectFill" @click="gallery.splice(i, 1)" />
            <view class="g-add" @click="addGallery">+</view>
          </view>
        </view>
        <wd-input v-model="form.live" label="线上地址" clearable />
        <wd-input v-model="form.github" label="GitHub" clearable />
        <wd-input v-model="form.demo" label="Demo" clearable />
        <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>
  </AppPageShell>
</template>

<style scoped lang="scss">
.page-pad { padding: 24rpx 32rpx 80rpx; }
.form-card { padding: 24rpx; }
.section { margin: 20rpx 0; }
.label { font-size: 24rpx; }
.tag-wrap { display: flex; flex-wrap: wrap; gap: 10rpx; margin: 12rpx 0; }
.tag {
  padding: 6rpx 14rpx;
  border-radius: 8rpx;
  background: rgba(212, 179, 131, 0.2);
  color: rgb(var(--art-accent));
  font-size: 22rpx;
}
.row-input { display: flex; gap: 12rpx; align-items: center; }
.gallery { display: flex; flex-wrap: wrap; gap: 12rpx; margin-top: 12rpx; }
.g-img, .g-add {
  width: 140rpx; height: 140rpx; border-radius: 12rpx;
  background: rgba(255, 255, 255, 0.06);
}
.g-add {
  display: flex; align-items: center; justify-content: center;
  font-size: 48rpx; color: rgba(255, 255, 255, 0.4);
  border: 1px dashed rgba(255, 255, 255, 0.15);
}
</style>
