'use client'

import { useEffect, useState } from 'react'
import { useRouter } from 'next/navigation'
import { Upload } from 'lucide-react'
import { AdminShell } from '@/components/admin/AdminShell'
import { apiBase, backend } from '@/lib/backend'
import type { CourseAccessState } from '@/types'

const emptyCourse = {
  slug: '',
  title: '',
  summary: '',
  priceAmount: 0,
  instructor: '',
  courseType: 'paid',
  memberLevelRequired: 0,
  lessonCount: 6,
  startsAt: '',
  location: '线上',
  courseStatus: 'anytime',
  direction: '数据治理',
  courseFormat: '线上课程',
  accessPolicy: 'paid_all',
  registeredAccess: 'paid' as CourseAccessState,
  juniorAccess: 'paid' as CourseAccessState,
  seniorAccess: 'paid' as CourseAccessState,
  registeredPriceAmount: 0,
  juniorPriceAmount: 0,
  seniorPriceAmount: 0,
  coverUrl: '',
  liveUrl: '',
  replayUrl: '',
  coverLabel: '',
  capacity: 0,
  checkinRequired: false,
  recommended: false,
  audience: '',
  outcomes: '',
  lessonModules: [{ title: '', description: '', videoUrl: '', materialUrl: '', durationMinutes: 0, sortOrder: 10, status: 'published' }],
  accessNote: '',
  sortOrder: 10,
  status: 'draft',
  productStatus: 'draft',
}

type LessonModule = (typeof emptyCourse.lessonModules)[number]

function toInputDateTime(value: string | null) {
  if (!value) return ''
  const date = new Date(value)
  const offset = date.getTimezoneOffset()
  const local = new Date(date.getTime() - offset * 60 * 1000)
  return local.toISOString().slice(0, 16)
}

function toSafeNumber(value: unknown) {
  const num = Number(value)
  if (!Number.isFinite(num)) return 0
  return Math.max(0, Math.round(num))
}

function displayYuan(value: unknown) {
  return (toSafeNumber(value) / 100).toFixed(2).replace(/\.00$/, '')
}

function yuanToCents(value: unknown) {
  const num = Number(value)
  if (!Number.isFinite(num)) return 0
  return Math.max(0, Math.round(num * 100))
}

function FieldHelp({ children }: { children: string }) {
  return <span className="mt-1 block text-xs font-bold text-soft">{children}</span>
}

const accessStateOptions: { value: CourseAccessState; label: string }[] = [
  { value: 'closed', label: '不可购买' },
  { value: 'free', label: '免费' },
  { value: 'paid', label: '收费' },
]

const accessRows: { key: 'registered' | 'junior' | 'senior'; label: string; accessKey: 'registeredAccess' | 'juniorAccess' | 'seniorAccess'; priceKey: 'registeredPriceAmount' | 'juniorPriceAmount' | 'seniorPriceAmount' }[] = [
  { key: 'registered', label: '注册用户', accessKey: 'registeredAccess', priceKey: 'registeredPriceAmount' },
  { key: 'junior', label: '初级会员', accessKey: 'juniorAccess', priceKey: 'juniorPriceAmount' },
  { key: 'senior', label: '高级会员', accessKey: 'seniorAccess', priceKey: 'seniorPriceAmount' },
]

function courseTypeFromMatrix(form: typeof emptyCourse) {
  if (form.registeredAccess === 'free') return 'free'
  if (form.registeredAccess === 'closed' && form.juniorAccess === 'closed') return 'senior'
  if (form.registeredAccess === 'closed') return 'junior'
  return 'paid'
}

function memberLevelFromMatrix(form: typeof emptyCourse) {
  if (form.registeredAccess !== 'closed') return 0
  if (form.juniorAccess !== 'closed') return 1
  return 2
}

function absoluteApiUrl(path: string) {
  if (/^https?:\/\//.test(path) || path.startsWith('data:')) return path
  return `${apiBase.replace(/\/api$/, '')}${path}`
}

function isSupportedCoverImage(file: File) {
  return ['image/jpeg', 'image/png', 'image/webp'].includes(file.type)
}

function modulePatch(modules: LessonModule[], index: number, patch: Partial<LessonModule>) {
  return modules.map((item, moduleIndex) => moduleIndex === index ? { ...item, ...patch } : item)
}

function buildCoursePayload(form: typeof emptyCourse) {
  return {
    ...form,
    coverLabel: '',
    courseType: courseTypeFromMatrix(form),
    priceAmount: toSafeNumber(form.priceAmount),
    registeredPriceAmount: toSafeNumber(form.registeredPriceAmount),
    juniorPriceAmount: toSafeNumber(form.juniorPriceAmount),
    seniorPriceAmount: toSafeNumber(form.seniorPriceAmount),
    memberLevelRequired: memberLevelFromMatrix(form),
    lessonCount: Number(form.lessonCount),
    capacity: toSafeNumber(form.capacity),
    checkinRequired: form.courseFormat === '线下培训' || Boolean(form.checkinRequired),
    sortOrder: toSafeNumber(form.sortOrder),
    startsAt: form.startsAt ? new Date(form.startsAt).toISOString() : null,
    outcomes: form.outcomes.split('\n').map((item) => item.trim()).filter(Boolean),
    lessonModules: form.lessonModules
      .map((item, index) => ({
        ...item,
        sortOrder: Number(item.sortOrder || (index + 1) * 10),
        durationMinutes: Number(item.durationMinutes || 0),
      }))
      .filter((item) => item.title.trim()),
  }
}

function validateCourseForm(form: typeof emptyCourse) {
  for (const row of accessRows) {
    if (form[row.accessKey] === 'paid' && toSafeNumber(form[row.priceKey]) <= 0) {
      return `${row.label}选择收费时，价格必须大于 0。`
    }
  }
  return ''
}

export function CourseProductForm({ productId }: { productId?: string }) {
  const router = useRouter()
  const [form, setForm] = useState(emptyCourse)
  const [error, setError] = useState('')
  const [coverUploadStatus, setCoverUploadStatus] = useState('')
  const [videoUploadStatus, setVideoUploadStatus] = useState<Record<number, string>>({})

  useEffect(() => {
    if (!productId) return
    void backend.adminCourseProducts().then((result) => {
      const item = result.items.find((current) => current.id === productId)
      if (!item) return
      setForm({
        slug: item.slug,
        title: item.title,
        summary: item.summary,
        priceAmount: toSafeNumber(item.priceAmount),
        instructor: item.instructor || '',
        courseType: item.courseType || 'paid',
        memberLevelRequired: item.memberLevelRequired || 0,
        lessonCount: item.lessonCount || 0,
        startsAt: toInputDateTime(item.startsAt),
        location: item.location || '',
        courseStatus: item.courseStatus || 'anytime',
        direction: item.direction || '',
        courseFormat: item.courseFormat || '',
        accessPolicy: item.accessPolicy || 'paid_all',
        registeredAccess: item.registeredAccess || 'paid',
        juniorAccess: item.juniorAccess || 'paid',
        seniorAccess: item.seniorAccess || 'paid',
        registeredPriceAmount: toSafeNumber(item.registeredPriceAmount ?? item.priceAmount),
        juniorPriceAmount: toSafeNumber(item.juniorPriceAmount ?? item.priceAmount),
        seniorPriceAmount: toSafeNumber(item.seniorPriceAmount ?? item.priceAmount),
        coverUrl: item.coverUrl || '',
        liveUrl: item.liveUrl || '',
        replayUrl: item.replayUrl || '',
        coverLabel: item.coverLabel || '',
        capacity: toSafeNumber(item.capacity),
        checkinRequired: Boolean(item.checkinRequired),
        recommended: Boolean(item.recommended),
        audience: item.audience || '',
        outcomes: (item.outcomes || []).join('\n'),
        lessonModules: item.lessonModules?.length
          ? item.lessonModules.map((module) => ({
            title: module.title,
            description: module.description || '',
            videoUrl: module.videoUrl || '',
            materialUrl: module.materialUrl || '',
            durationMinutes: module.durationMinutes || 0,
            sortOrder: module.sortOrder || 10,
            status: module.status || 'published',
          }))
          : (item.modules || []).map((title, index) => ({ title, description: '', videoUrl: '', materialUrl: '', durationMinutes: 0, sortOrder: (index + 1) * 10, status: 'published' })),
        accessNote: item.accessNote || '',
        sortOrder: toSafeNumber(item.sortOrder),
        status: item.status || 'draft',
        productStatus: item.productStatus || item.status || 'draft',
      })
    }).catch((err) => setError(err instanceof Error ? err.message : '课程商品加载失败'))
  }, [productId])

  return (
    <AdminShell title={productId ? '编辑课程商品' : '新增课程商品'} description="按录播、直播、线下培训分别维护字段，保存后用户端课程页、详情页、我的课程同步读取。">
      <form
        className="border border-line bg-white"
        onSubmit={async (event) => {
          event.preventDefault()
          try {
            const validationError = validateCourseForm(form)
            if (validationError) {
              setError(validationError)
              return
            }
            await backend.saveAdminCourseProduct(productId || null, buildCoursePayload(form))
            router.push('/admin/products/courses')
          } catch (err) {
            setError(err instanceof Error ? err.message : '保存失败')
          }
        }}
      >
        <div className="grid gap-4 border-b border-line px-5 py-4 lg:grid-cols-[1fr_auto] lg:items-center">
          <div>
            <div className="text-base font-extrabold text-ink">{form.title || '课程商品'}</div>
            <div className="mt-1 text-xs font-bold text-muted">字段会同步影响课程列表、课程详情、购买结算和我的课程学习入口。</div>
          </div>
          <button className="h-9 rounded-[4px] bg-brand px-5 text-sm font-extrabold text-white hover:bg-brand-dark">保存课程</button>
        </div>
        {error && <div className="mx-5 mt-4 border border-red-100 bg-red-50 px-3 py-2 text-sm font-bold text-red-700">{error}</div>}

        <div className="grid gap-0 lg:grid-cols-[minmax(0,1fr)_340px]">
          <section className="space-y-5 px-5 py-5">
            <div>
              <div className="mb-3 text-sm font-extrabold text-ink">基础展示</div>
              <div className="grid gap-4 md:grid-cols-2">
                <label className="block">
                  <span className="mb-2 block text-sm font-bold text-ink">课程标题</span>
                  <input value={form.title} onChange={(event) => setForm((current) => ({ ...current, title: event.target.value }))} required className="h-10 w-full rounded-[4px] border border-line px-3 text-sm" />
                  <FieldHelp>显示在课程列表、详情页、订单和我的课程里。</FieldHelp>
                </label>
                <label className="block">
                  <span className="mb-2 block text-sm font-bold text-ink">Slug</span>
                  <input value={form.slug} onChange={(event) => setForm((current) => ({ ...current, slug: event.target.value }))} required className="h-10 w-full rounded-[4px] border border-line px-3 text-sm" />
                  <FieldHelp>用于用户端详情页地址，例如 /courses/data-governance-fundamentals。</FieldHelp>
                </label>
              </div>
            </div>

            <label className="block">
              <span className="mb-2 block text-sm font-bold text-ink">列表摘要</span>
              <textarea value={form.summary} onChange={(event) => setForm((current) => ({ ...current, summary: event.target.value }))} required rows={3} className="w-full rounded-[4px] border border-line p-3 text-sm" />
              <FieldHelp>用户在课程目录和详情页标题下看到的课程简介。</FieldHelp>
            </label>

            <label className="block">
              <span className="mb-2 block text-sm font-bold text-ink">上传封面图片</span>
              <label className="inline-flex h-10 cursor-pointer items-center gap-2 rounded-[4px] border border-line bg-white px-4 text-sm font-extrabold text-ink hover:border-brand hover:text-brand">
                <Upload className="h-4 w-4" />
                {coverUploadStatus || (form.coverUrl ? '重新上传封面' : '上传封面')}
                <input
                  type="file"
                  accept="image/jpeg,image/png,image/webp"
                  className="sr-only"
                  onChange={async (event) => {
                    const file = event.target.files?.[0]
                    if (!file) return
                    if (!isSupportedCoverImage(file)) {
                      setError('封面只支持 JPG、PNG 或 WebP。请不要上传 HEIC/HEIF，用户端可能无法显示。')
                      event.target.value = ''
                      return
                    }
                    setCoverUploadStatus('上传中...')
                    try {
                      const uploaded = await backend.uploadAdminFile(file)
                      setForm((current) => ({ ...current, coverUrl: absoluteApiUrl(uploaded.url) }))
                      setCoverUploadStatus(`已上传：${uploaded.fileName}`)
                    } catch (err) {
                      setError(err instanceof Error ? err.message : '封面上传失败')
                      setCoverUploadStatus('')
                    } finally {
                      event.target.value = ''
                    }
                  }}
                />
              </label>
              <FieldHelp>{form.coverUrl ? '已上传真实封面图片，用户端会直接展示。' : '未上传时用户端只显示朴素空态，不生成模拟图片。'}</FieldHelp>
            </label>

            {form.courseFormat === '直播课' && (
              <label className="block">
                <span className="mb-2 block text-sm font-bold text-ink">直播入口 URL</span>
                <input value={form.liveUrl} onChange={(event) => setForm((current) => ({ ...current, liveUrl: event.target.value }))} className="h-10 w-full rounded-[4px] border border-line px-3 text-sm" />
                <FieldHelp>直播课可以使用外部直播地址；课程结束后不设置回放，用户端显示“直播已结束”。</FieldHelp>
              </label>
            )}

            <div>
              <div className="mb-3 text-sm font-extrabold text-ink">课程类型与准入</div>
              <div className="grid gap-4 md:grid-cols-2">
                <label className="block">
                  <span className="mb-2 block text-sm font-bold text-ink">课程形式</span>
                  <select
                    value={form.courseFormat}
                    onChange={(event) => {
                      const courseFormat = event.target.value
                      setForm((current) => ({
                        ...current,
                        courseFormat,
                        courseStatus: courseFormat === '线上课程' ? 'anytime' : current.courseStatus,
                        checkinRequired: courseFormat === '线下培训',
                        capacity: courseFormat === '线下培训' ? current.capacity : 0,
                      }))
                    }}
                    className="h-10 w-full rounded-[4px] border border-line px-3 text-sm"
                  >
                    <option value="线上课程">线上课程（录播）</option>
                    <option value="直播课">直播课</option>
                    <option value="线下培训">线下培训</option>
                  </select>
                  <FieldHelp>决定用户端课程展示口径和我的课程入口。</FieldHelp>
                </label>
                <label className="block">
                  <span className="mb-2 block text-sm font-bold text-ink">课程方向</span>
                  <input value={form.direction} onChange={(event) => setForm((current) => ({ ...current, direction: event.target.value }))} placeholder="例如：数据治理、AI应用、企业数字化" className="h-10 w-full rounded-[4px] border border-line px-3 text-sm" />
                  <FieldHelp>后台可自由填写课程方向，用于详情展示和运营识别。</FieldHelp>
                </label>
              </div>
            </div>

            <div className="border border-line bg-bg/40 p-4">
              <div className="mb-3 flex items-start justify-between gap-4">
                <div>
                  <div className="text-sm font-extrabold text-ink">访问权限矩阵</div>
                  <div className="mt-1 text-xs font-bold leading-5 text-soft">每个身份单独设置：不可购买会在后端结算拒绝；免费结算为 0；收费使用该身份价格。</div>
                </div>
              </div>
              <div className="divide-y divide-line border border-line bg-white">
                {accessRows.map((row) => {
                  const state = form[row.accessKey]
                  return (
                    <div key={row.key} className="grid gap-3 p-3 md:grid-cols-[120px_180px_1fr] md:items-center">
                      <div className="text-sm font-extrabold text-ink">{row.label}</div>
                      <select
                        value={state}
                        onChange={(event) => setForm((current) => ({ ...current, [row.accessKey]: event.target.value as CourseAccessState }))}
                        className="h-10 w-full rounded-[4px] border border-line px-3 text-sm font-bold"
                      >
                        {accessStateOptions.map((item) => <option key={item.value} value={item.value}>{item.label}</option>)}
                      </select>
                      <label className="block">
                        <span className="sr-only">{row.label}价格</span>
                        <input
                          value={displayYuan(form[row.priceKey])}
                          onChange={(event) => setForm((current) => {
                            const amount = yuanToCents(event.target.value)
                            return { ...current, [row.priceKey]: amount, priceAmount: row.key === 'registered' ? amount : current.priceAmount }
                          })}
                          type="number"
                          min={state === 'paid' ? '0.01' : '0'}
                          step="0.01"
                          disabled={state !== 'paid'}
                          placeholder={state === 'paid' ? '价格（元）' : state === 'free' ? '免费，无需价格' : '不可购买，无需价格'}
                          className="h-10 w-full rounded-[4px] border border-line px-3 text-sm disabled:bg-bg disabled:text-soft"
                        />
                        <FieldHelp>{state === 'paid' ? `${row.label}需要支付这个价格后才能学习。` : state === 'free' ? `${row.label}可直接加入学习，结算金额为 0。` : `${row.label}不能购买或加入，结算接口会直接拒绝。`}</FieldHelp>
                      </label>
                    </div>
                  )
                })}
              </div>
            </div>

            <div className="grid gap-4 md:grid-cols-3">
              <label className="block">
                <span className="mb-2 block text-sm font-bold text-ink">课时数</span>
                <input value={form.lessonCount} onChange={(event) => setForm((current) => ({ ...current, lessonCount: Number(event.target.value || 0) }))} type="number" min="0" className="h-10 w-full rounded-[4px] border border-line px-3 text-sm" />
              </label>
              <label className="block">
                <span className="mb-2 block text-sm font-bold text-ink">讲师</span>
                <input value={form.instructor} onChange={(event) => setForm((current) => ({ ...current, instructor: event.target.value }))} className="h-10 w-full rounded-[4px] border border-line px-3 text-sm" />
              </label>
              <label className="block">
                <span className="mb-2 block text-sm font-bold text-ink">课程状态</span>
                <select value={form.courseStatus} onChange={(event) => setForm((current) => ({ ...current, courseStatus: event.target.value }))} className="h-10 w-full rounded-[4px] border border-line px-3 text-sm">
                  <option value="anytime">随时学习</option>
                  <option value="upcoming">待开课</option>
                  <option value="ongoing">进行中</option>
                  <option value="completed">已完课</option>
                </select>
              </label>
            </div>

            <div className="grid gap-4 md:grid-cols-2">
              <label className="block">
                <span className="mb-2 block text-sm font-bold text-ink">开课时间</span>
                <input value={form.startsAt} onChange={(event) => setForm((current) => ({ ...current, startsAt: event.target.value }))} type="datetime-local" className="h-10 w-full rounded-[4px] border border-line px-3 text-sm" />
                <FieldHelp>录播课可以留空；直播和线下培训建议填写。</FieldHelp>
              </label>
              <label className="block">
                <span className="mb-2 block text-sm font-bold text-ink">地点/学习入口说明</span>
                <input value={form.location} onChange={(event) => setForm((current) => ({ ...current, location: event.target.value }))} className="h-10 w-full rounded-[4px] border border-line px-3 text-sm" />
                <FieldHelp>线上填“线上”；线下填具体地址或集合地点。</FieldHelp>
              </label>
            </div>

            {form.courseFormat === '线下培训' && (
              <div className="border border-line bg-bg/40 p-4">
                <div className="mb-3 text-sm font-extrabold text-ink">线下培训报名与核销</div>
                <label className="block">
                  <span className="mb-2 block text-sm font-bold text-ink">名额上限</span>
                  <input
                    value={form.capacity}
                    onChange={(event) => setForm((current) => ({ ...current, capacity: Number(event.target.value || 0), checkinRequired: true }))}
                    type="number"
                    min="0"
                    className="h-10 w-full rounded-[4px] border border-line px-3 text-sm"
                  />
                  <FieldHelp>0 表示不限名额；达到上限后用户端显示名额已满，结算接口也会拒绝新报名。线下培训默认生成报名码并进入课程核销名单。</FieldHelp>
                </label>
              </div>
            )}

            <label className="block">
              <span className="mb-2 block text-sm font-bold text-ink">适合人群</span>
              <textarea value={form.audience} onChange={(event) => setForm((current) => ({ ...current, audience: event.target.value }))} rows={3} className="w-full rounded-[4px] border border-line p-3 text-sm" />
              <FieldHelp>详情页“适合人群”和推荐课程卡片会读取这里。</FieldHelp>
            </label>

            <label className="block">
              <span className="mb-2 block text-sm font-bold text-ink">学习收获（每行一条）</span>
              <textarea value={form.outcomes} onChange={(event) => setForm((current) => ({ ...current, outcomes: event.target.value }))} rows={5} className="w-full rounded-[4px] border border-line p-3 text-sm" />
              <FieldHelp>对应详情页“你将学到”。</FieldHelp>
            </label>

            <div>
              <div className="mb-3 flex items-center justify-between gap-4">
                <div>
                  <div className="text-sm font-extrabold text-ink">{form.courseFormat === '线上课程' ? '录播课模块' : '课程模块'}</div>
                  <div className="mt-1 text-xs font-bold text-soft">
                    {form.courseFormat === '线上课程' ? '录播课每个模块都可以上传一个视频文件，用户在我的课程里切换观看。' : '直播和线下课程只维护模块标题与说明，不显示视频上传。'}
                  </div>
                </div>
                <button
                  type="button"
                  onClick={() => setForm((current) => ({
                    ...current,
                    lessonModules: [...current.lessonModules, { title: '', description: '', videoUrl: '', materialUrl: '', durationMinutes: 0, sortOrder: (current.lessonModules.length + 1) * 10, status: 'published' }],
                  }))}
                  className="h-8 rounded-[4px] border border-line bg-white px-3 text-xs font-extrabold text-ink hover:border-brand hover:text-brand"
                >
                  添加模块
                </button>
              </div>
              <div className="space-y-3">
                {form.lessonModules.map((module, index) => (
                  <div key={index} className="border border-line bg-white p-3">
                    <div className="mb-3 flex items-center justify-between">
                      <div className="text-xs font-extrabold text-soft">模块 {index + 1}</div>
                      <button
                        type="button"
                        onClick={() => setForm((current) => ({ ...current, lessonModules: current.lessonModules.filter((_, moduleIndex) => moduleIndex !== index) }))}
                        className="text-xs font-extrabold text-red-600"
                      >
                        删除模块
                      </button>
                    </div>
                    <div className="grid gap-3 md:grid-cols-[1fr_130px_120px]">
                      <label className="block">
                        <span className="mb-1 block text-xs font-bold text-soft">模块标题</span>
                        <input value={module.title} onChange={(event) => setForm((current) => ({ ...current, lessonModules: modulePatch(current.lessonModules, index, { title: event.target.value }) }))} placeholder="模块标题" className="h-10 w-full rounded-[4px] border border-line px-3 text-sm" />
                      </label>
                      <label className="block">
                        <span className="mb-1 block text-xs font-bold text-soft">视频时长（分钟）</span>
                        <input value={module.durationMinutes} onChange={(event) => setForm((current) => ({ ...current, lessonModules: modulePatch(current.lessonModules, index, { durationMinutes: Number(event.target.value || 0) }) }))} type="number" min="0" className="h-10 w-full rounded-[4px] border border-line px-3 text-sm" />
                      </label>
                      <label className="block">
                        <span className="mb-1 block text-xs font-bold text-soft">显示排序</span>
                        <input value={module.sortOrder} onChange={(event) => setForm((current) => ({ ...current, lessonModules: modulePatch(current.lessonModules, index, { sortOrder: Number(event.target.value || 0) }) }))} type="number" className="h-10 w-full rounded-[4px] border border-line px-3 text-sm" />
                      </label>
                    </div>
                    <textarea value={module.description} onChange={(event) => setForm((current) => ({ ...current, lessonModules: modulePatch(current.lessonModules, index, { description: event.target.value }) }))} rows={2} placeholder="模块说明" className="mt-3 w-full rounded-[4px] border border-line p-3 text-sm" />
                    {form.courseFormat === '线上课程' && (
                      <label className="mt-3 block">
                        <span className="mb-1 block text-xs font-bold text-soft">上传录播视频</span>
                        <input
                          type="file"
                          accept="video/*"
                          onChange={async (event) => {
                            const file = event.target.files?.[0]
                            if (!file) return
                            setVideoUploadStatus((current) => ({ ...current, [index]: '正在上传录播视频...' }))
                            try {
                              const uploaded = await backend.uploadAdminFile(file)
                              const videoUrl = absoluteApiUrl(uploaded.url)
                              const nextForm = { ...form, lessonModules: modulePatch(form.lessonModules, index, { videoUrl }) }
                              setForm(nextForm)
                              if (productId) {
                                await backend.saveAdminCourseProduct(productId, buildCoursePayload(nextForm))
                                setVideoUploadStatus((current) => ({ ...current, [index]: `已上传并保存：${uploaded.fileName}` }))
                              } else {
                                setVideoUploadStatus((current) => ({ ...current, [index]: `已上传：${uploaded.fileName}，保存课程后生效` }))
                              }
                            } catch (err) {
                              setVideoUploadStatus((current) => ({ ...current, [index]: '' }))
                              setError(err instanceof Error ? err.message : '录播视频上传失败')
                            }
                          }}
                          className="block w-full rounded-[4px] border border-line bg-white px-3 py-2 text-sm"
                        />
                        <FieldHelp>视频文件进入统一 bucket，数据库只保存下载/播放地址；当前模块已有视频时保存会覆盖。</FieldHelp>
                        {module.videoUrl && <div className="mt-2 truncate text-xs font-bold text-muted">当前视频：{module.videoUrl}</div>}
                        {videoUploadStatus[index] && <div className="mt-2 text-xs font-extrabold text-brand">{videoUploadStatus[index]}</div>}
                      </label>
                    )}
                  </div>
                ))}
              </div>
            </div>

            <label className="block">
              <span className="mb-2 block text-sm font-bold text-ink">学习权益说明</span>
              <textarea value={form.accessNote} onChange={(event) => setForm((current) => ({ ...current, accessNote: event.target.value }))} rows={3} className="w-full rounded-[4px] border border-line p-3 text-sm" />
              <FieldHelp>说明购买/加入后能看到什么资料、入口、回放或线下安排。</FieldHelp>
            </label>
          </section>

          <aside className="border-t border-line bg-bg/60 px-5 py-5 lg:border-l lg:border-t-0">
            <div className="mb-3 text-sm font-extrabold text-ink">发布控制</div>
            <div className="space-y-4">
              <label className="block">
                <span className="mb-2 block text-sm font-bold text-ink">排序</span>
                <input value={form.sortOrder} onChange={(event) => setForm((current) => ({ ...current, sortOrder: Number(event.target.value || 0) }))} type="number" className="h-10 w-full rounded-[4px] border border-line px-3 text-sm" />
                <FieldHelp>保存后会占用这个排序号，已有同号和后续商品自动后移。</FieldHelp>
              </label>
              <label className="block">
                <span className="mb-2 block text-sm font-bold text-ink">发布状态</span>
                <select value={form.status} onChange={(event) => setForm((current) => ({ ...current, status: event.target.value, productStatus: event.target.value }))} className="h-10 w-full rounded-[4px] border border-line px-3 text-sm">
                  <option value="draft">草稿</option>
                  <option value="published">已发布</option>
                  <option value="offline">已下架</option>
                </select>
                <FieldHelp>只有已发布课程会在用户端展示并允许购买。</FieldHelp>
              </label>
              <label className="flex items-start gap-2 text-sm font-bold text-ink">
                <input
                  type="checkbox"
                  checked={form.recommended}
                  onChange={(event) => setForm((current) => ({ ...current, recommended: event.target.checked }))}
                  className="mt-1"
                />
                <span>
                  推荐展示
                  <FieldHelp>勾选后进入课程页推荐轮播和首页近期课程。</FieldHelp>
                </span>
              </label>
            </div>
          </aside>
        </div>
      </form>
    </AdminShell>
  )
}
