import { useState, useRef } from 'react'
import { usePageSize } from '../hooks/usePageSize'
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import { Plus, Search, Paperclip, Trash2, X, FileText, Download, AlertTriangle } from 'lucide-react'
import { toast } from 'sonner'
import { rosterApi, employeeApi, attachmentApi } from '../lib/api-services'
import api from '../lib/api'
import Card from '../components/ui/Card'
import Button from '../components/ui/Button'
import { Input, Label, Select } from '../components/ui/Input'
import Modal from '../components/ui/Modal'
import EmptyState from '../components/ui/EmptyState'
import Pagination from '../components/ui/Pagination'

interface EmployeeItem {
  id: string
  name: string
  department: string
  hireDate: string
  status: string
  contractStatus: string
  contractStatusText: string
  riskLevel: 'high' | 'medium' | 'low' | 'safe'
  isPregnant: boolean
  isInMedicalPeriod: boolean
  isWorkInjured: boolean
}

interface EmployeeListResponse {
  items: EmployeeItem[]
  total: number
  page: number
  pageSize: number
  totalPages: number
}

export default function Contracts() {
  const queryClient = useQueryClient()
  const [search, setSearch] = useState('')
  const [filterDepartment, setFilterDepartment] = useState('')
  const [filterContractStatus, setFilterContractStatus] = useState('')
  const pageSize = usePageSize()
  const [page, setPage] = useState(1)
  const [showAddModal, setShowAddModal] = useState(false)
  const [selectedEmpId, setSelectedEmpId] = useState<string | null>(null)

  const { data, isLoading } = useQuery<EmployeeListResponse>({
    queryKey: ['employees', search, filterDepartment, filterContractStatus, page, pageSize],
    queryFn: async () => {
      const params: any = { search, page, pageSize }
      if (filterDepartment) params.department = filterDepartment
      if (filterContractStatus) params.contractStatus = filterContractStatus
      const res = await rosterApi.list({ search, page, pageSize, department: filterDepartment || undefined, contractStatus: filterContractStatus || undefined } as any) as any
      return res
    },
  })

  const addMutation = useMutation({
    mutationFn: (data: any) => employeeApi.create(data),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['employees'] })
      queryClient.invalidateQueries({ queryKey: ['roster'] })
      queryClient.invalidateQueries({ queryKey: ['dashboard'] })
      queryClient.invalidateQueries({ queryKey: ['roster-profile'] })
      localStorage.removeItem('add-employee-draft')
      setShowAddModal(false)
    },
  })

  const { data: departmentList } = useQuery<string[]>({
    queryKey: ['roster-departments'],
    queryFn: () => rosterApi.departments(),
  })

  return (
    <div className="space-y-4">
      <div className="flex items-center justify-between">
        <div className="flex items-center gap-2">
          <FileText className="h-5 w-5 text-primary" />
          <div>
            <h1 className="text-base font-semibold">合同管理</h1>
            <p className="mt-1 text-sm text-gray-500">集中管理用工关系（劳动合同/劳务协议/实习协议）、签署状态及到期风险</p>
          </div>
        </div>
        <Button onClick={() => setShowAddModal(true)}>
          <Plus className="w-4 h-4 mr-1" /> 添加员工
        </Button>
      </div>

      {/* 搜索栏 */}
      <div className="flex gap-2 flex-wrap">
        <div className="relative flex-1 min-w-[200px]">
          <Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-400" />
          <Input
            placeholder="搜索员工姓名或手机号"
            value={search}
            onChange={(e) => { setSearch(e.target.value); setPage(1) }}
            className="pl-9"
          />
        </div>
        <select
          value={filterDepartment}
          onChange={(e) => { setFilterDepartment(e.target.value); setPage(1) }}
          className="h-9 rounded-md border border-gray-200 bg-white px-3 text-sm text-gray-700 shadow-sm outline-none transition focus:border-primary focus:ring-2 focus:ring-primary/10"
        >
          <option value="">全部部门</option>
          {departmentList?.map((d: string) => <option key={d} value={d}>{d}</option>)}
        </select>
        <select
          value={filterContractStatus}
          onChange={(e) => { setFilterContractStatus(e.target.value); setPage(1) }}
          className="h-9 rounded-md border border-gray-200 bg-white px-3 text-sm text-gray-700 shadow-sm outline-none transition focus:border-primary focus:ring-2 focus:ring-primary/10"
        >
          <option value="">全部合同</option>
          <option value="active">正常</option>
          <option value="expiring">即将到期</option>
          <option value="expired">已到期</option>
          <option value="unsigned">未签合同</option>
          <option value="unsigned_over_30">未签合同(超30天)</option>
          <option value="unsigned_over_year">未签合同(已满一年)</option>
        </select>
        {(search || filterDepartment || filterContractStatus) && (
          <button onClick={() => { setSearch(''); setFilterDepartment(''); setFilterContractStatus(''); setPage(1) }} className="text-xs text-gray-500 hover:text-primary">清除筛选</button>
        )}
      </div>

      {/* 员工列表 */}
      <Card>
        {isLoading ? (
          <div className="text-center py-8 text-gray-400">加载中...</div>
        ) : !data || data.items.length === 0 ? (
          <EmptyState
            title="暂无员工"
            description="点击「添加员工」开始管理合同"
            actionLabel="添加员工"
            onAction={() => setShowAddModal(true)}
          />
        ) : (
          <>
            <div className="overflow-x-auto">
              <table className="w-full text-sm">
                <thead>
                  <tr className="border-b text-left text-xs text-gray-500">
                    <th className="py-2 px-3 font-medium">姓名</th>
                    <th className="py-2 px-3 font-medium">部门</th>
                    <th className="py-2 px-3 font-medium">入职日期</th>
                    <th className="py-2 px-3 font-medium">合同状态</th>
                    <th className="py-2 px-3 font-medium">特殊状态</th>
                  </tr>
                </thead>
                <tbody>
                  {data.items.map((emp) => (
                    <tr key={emp.id} className="border-b last:border-0 hover:bg-gray-50 cursor-pointer" onClick={() => setSelectedEmpId(emp.id)}>
                      <td className="py-3 px-3 font-medium">{emp.name}</td>
                      <td className="py-3 px-3 text-gray-600">{emp.department}</td>
                      <td className="py-3 px-3 text-gray-600">{emp.hireDate}</td>
                      <td className="py-3 px-3">
                        {(() => {
                          const tagStyles: Record<string, string> = {
                            expired: 'bg-red-50 text-danger',
                            unsigned_over_year: 'bg-red-50 text-danger',
                            unsigned_over_30: 'bg-red-50 text-danger',
                            unsigned: 'bg-yellow-50 text-yellow-700',
                            expiring: 'bg-yellow-50 text-yellow-700',
                            active: 'bg-green-50 text-safe',
                            unfixed: 'bg-blue-50 text-blue-700',
                          }
                          const style = tagStyles[emp.contractStatus] || 'bg-gray-100 text-gray-600'
                          return <span className={`px-2 py-0.5 rounded text-xs ${style}`}>{emp.contractStatusText}</span>
                        })()}
                      </td>
                      <td className="py-3 px-3">
                        <div className="flex gap-1">
                          {emp.isPregnant && <span className="text-xs px-1.5 py-0.5 rounded bg-pink-50 text-pink-600">孕期</span>}
                          {emp.isInMedicalPeriod && <span className="text-xs px-1.5 py-0.5 rounded bg-orange-50 text-orange-600">医疗期</span>}
                          {emp.isWorkInjured && <span className="text-xs px-1.5 py-0.5 rounded bg-red-50 text-red-600">工伤</span>}
                        </div>
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>

            {/* 分页 */}
            <Pagination
              page={page}
              pageSize={pageSize}
              total={data.total}
              onPageChange={setPage}
              onPageSizeChange={() => setPage(1)}
            />
          </>
        )}
      </Card>

      {/* 添加员工 Modal */}
      <AddEmployeeModal
        open={showAddModal}
        onClose={() => setShowAddModal(false)}
        onSubmit={(data) => addMutation.mutate(data)}
        loading={addMutation.isPending}
        error={addMutation.error as any}
      />

      {/* 员工详情抽屉 */}
      {selectedEmpId && (
        <EmployeeDetailDrawer employeeId={selectedEmpId} onClose={() => setSelectedEmpId(null)} />
      )}
    </div>
  )
}

function AddEmployeeModal({ open, onClose, onSubmit, loading, error }: {
  open: boolean
  onClose: () => void
  onSubmit: (data: any) => void
  loading: boolean
  error: any
}) {
  // 拉取组织架构部门列表，用于部门下拉选择
  const { data: departments = [] } = useQuery({
    queryKey: ['departments'],
    queryFn: () => api.get('/departments').then(r => r.data),
  })
  // 构建部门树形下拉选项（带层级缩进）
  const deptOptions: { id: string; label: string; level: number }[] = []
  const buildDeptOptions = (items: any[], parentId: string | null, level: number) => {
    items.filter(d => d.parentId === parentId).sort((a, b) => a.sortOrder - b.sortOrder).forEach(d => {
      deptOptions.push({ id: d.id, label: d.name, level })
      buildDeptOptions(items, d.id, level + 1)
    })
  }
  buildDeptOptions(departments, null, 0)
  // 手机号查重
  const [phoneDuplicate, setPhoneDuplicate] = useState<{ exists: boolean; employee?: any } | null>(null)
  const [form, setForm] = useState({
    name: '',
    department: '',
    position: '',
    hireDate: '',
    monthlySalary: '',
    gender: '男' as '男' | '女',
    phone: '',
    isPregnant: false,
    isInMedicalPeriod: false,
    isWorkInjured: false,
    contractType: 'FIXED' as 'FIXED' | 'UNFIXED' | 'UNSIGNED',
    signDate: '',
    startDate: '',
    endDate: '',
    contractYears: 3,
    probationMonths: 0,
    probationSalary: 0,
  })

  const handleSubmit = () => {
    const data: any = {
      name: form.name,
      department: form.department,
      position: form.position || undefined,
      hireDate: new Date(form.hireDate).toISOString(),
      monthlySalary: form.monthlySalary,
      gender: form.gender,
      phone: form.phone || undefined,
      isPregnant: form.isPregnant,
      isInMedicalPeriod: form.isInMedicalPeriod,
      isWorkInjured: form.isWorkInjured,
    }
    if (form.contractType !== 'UNSIGNED' && form.startDate) {
      data.contract = {
        signDate: form.signDate ? new Date(form.signDate).toISOString() : null,
        startDate: new Date(form.startDate).toISOString(),
        endDate: form.endDate ? new Date(form.endDate).toISOString() : null,
        contractType: form.contractType,
        contractYears: form.contractYears,
        probationMonths: form.probationMonths,
        probationSalary: form.probationSalary,
      }
    }
    onSubmit(data)
  }

  return (
    <Modal open={open} onClose={onClose} title="添加员工">
      <div className="space-y-4">
        {error && (
          <div className="px-3 py-2 rounded-md bg-red-50 text-red-700 text-xs">
            {error.response?.data?.error?.message || '操作失败'}
          </div>
        )}

        <div className="grid grid-cols-2 gap-3">
          <div>
            <Label>姓名 *</Label>
            <Input value={form.name} onChange={(e) => setForm({ ...form, name: e.target.value })} placeholder="员工姓名" />
          </div>
          <div>
            <Label>部门 *</Label>
            <Select value={form.department} onChange={(e) => setForm({ ...form, department: e.target.value })}>
              <option value="">请选择部门</option>
              {deptOptions.map(d => (
                <option key={d.id} value={d.label}>{'　'.repeat(d.level)}{d.label}</option>
              ))}
            </Select>
          </div>
        </div>

        <div className="grid grid-cols-2 gap-3">
          <div>
            <Label>职务/岗位</Label>
            <Input value={form.position} onChange={(e) => setForm({ ...form, position: e.target.value })} placeholder="如：前端工程师" />
          </div>
          <div>
            <Label>入职日期 *</Label>
            <Input type="date" value={form.hireDate} onChange={(e) => setForm({ ...form, hireDate: e.target.value })} />
          </div>
        </div>

        <div>
          <Label>月工资 *</Label>
          <Input type="number" value={form.monthlySalary} onChange={(e) => setForm({ ...form, monthlySalary: e.target.value })} placeholder="元" />
        </div>

        <div className="grid grid-cols-2 gap-3">
          <div>
            <Label>性别</Label>
            <Select value={form.gender} onChange={(e) => setForm({ ...form, gender: e.target.value as '男' | '女' })}>
              <option value="男">男</option>
              <option value="女">女</option>
            </Select>
          </div>
          <div>
            <Label>手机号</Label>
            <Input value={form.phone} onChange={(e) => {
              const phone = e.target.value.replace(/\D/g, '').slice(0, 11)
              setForm({ ...form, phone })
              setPhoneDuplicate(null)
              if (phone.length === 11) {
                employeeApi.checkPhone(phone).then((data: { exists: boolean; employee?: any }) => {
                  setPhoneDuplicate(data)
                }).catch(() => {})
              }
            }} placeholder="选填" maxLength={11} />
          </div>
        </div>
        {phoneDuplicate?.exists && (
          <div className="px-3 py-2 rounded-md bg-amber-50 text-amber-700 text-xs flex items-center gap-2">
            <AlertTriangle className="w-4 h-4 shrink-0" />
            <span>该手机号已存在：{phoneDuplicate.employee?.name}（{phoneDuplicate.employee?.department}），请确认是否重复录入</span>
          </div>
        )}

        {/* 特殊状态 */}
        <div className="flex gap-4">
          <label className="flex items-center gap-1.5 text-xs">
            <input type="checkbox" checked={form.isPregnant} onChange={(e) => setForm({ ...form, isPregnant: e.target.checked })} />
            孕期/哺乳期
          </label>
          <label className="flex items-center gap-1.5 text-xs">
            <input type="checkbox" checked={form.isInMedicalPeriod} onChange={(e) => setForm({ ...form, isInMedicalPeriod: e.target.checked })} />
            医疗期
          </label>
          <label className="flex items-center gap-1.5 text-xs">
            <input type="checkbox" checked={form.isWorkInjured} onChange={(e) => setForm({ ...form, isWorkInjured: e.target.checked })} />
            工伤
          </label>
        </div>

        {/* 合同信息 */}
        <div className="border-t pt-3">
          <Label>合同类型</Label>
          <Select value={form.contractType} onChange={(e) => setForm({ ...form, contractType: e.target.value as any })}>
            <option value="FIXED">固定期限</option>
            <option value="UNFIXED">无固定期限</option>
            <option value="UNSIGNED">未签合同</option>
          </Select>
        </div>

        {form.contractType !== 'UNSIGNED' && (
          <div className="space-y-3">
            <div className="grid grid-cols-2 gap-3">
              <div>
                <Label>签订日期</Label>
                <Input type="date" value={form.signDate} onChange={(e) => setForm({ ...form, signDate: e.target.value })} />
              </div>
              <div>
                <Label>合同开始日期 *</Label>
                <Input type="date" value={form.startDate} onChange={(e) => setForm({ ...form, startDate: e.target.value })} />
              </div>
            </div>

            {form.contractType === 'FIXED' && (
              <div className="grid grid-cols-1 sm:grid-cols-3 gap-3">
                <div>
                  <Label>合同结束日期</Label>
                  <Input type="date" value={form.endDate} onChange={(e) => setForm({ ...form, endDate: e.target.value })} />
                </div>
                <div>
                  <Label>试用期(月)</Label>
                  <Input type="number" value={form.probationMonths} onChange={(e) => setForm({ ...form, probationMonths: parseInt(e.target.value) || 0 })} min={0} max={6} />
                </div>
                <div>
                  <Label>试用期工资</Label>
                  <Input type="number" value={form.probationSalary} onChange={(e) => setForm({ ...form, probationSalary: parseInt(e.target.value) || 0 })} />
                </div>
              </div>
            )}
          </div>
        )}

        <div className="flex justify-end gap-2 pt-2">
          <Button variant="secondary" onClick={onClose}>取消</Button>
          <Button onClick={handleSubmit} disabled={loading || !form.name || !form.department || !form.hireDate || !form.monthlySalary}>
            {loading ? '保存中...' : '保存'}
          </Button>
        </div>
      </div>
    </Modal>
  )
}

function EmployeeDetailDrawer({ employeeId, onClose }: { employeeId: string; onClose: () => void }) {
  const queryClient = useQueryClient()
  const fileInputRef = useRef<HTMLInputElement>(null)
  const [fileType, setFileType] = useState<'ID_CARD' | 'BANK_CARD' | 'CONTRACT_SCAN' | 'EDUCATION' | 'TERMINATION_DOC' | 'RETIREMENT_DOC' | 'INJURY_CERT' | 'MEDICAL_CERT' | 'PREGNANCY_CERT' | 'OTHER'>('ID_CARD')
  const [previewUrl, setPreviewUrl] = useState<string | null>(null)

  const { data: employee } = useQuery<any>({
    queryKey: ['employee-detail', employeeId],
    queryFn: async () => {
      return await employeeApi.detail(employeeId)
    },
  })

  const { data: attachments } = useQuery<any[]>({
    queryKey: ['employee-attachments', employeeId],
    queryFn: async () => {
      return await attachmentApi.list(employeeId)
    },
  })

  const addAttachmentMutation = useMutation({
    mutationFn: (data: any) => attachmentApi.add(data),
    onSuccess: () => queryClient.invalidateQueries({ queryKey: ['employee-attachments', employeeId] }),
  })

  const deleteAttachmentMutation = useMutation({
    mutationFn: (id: string) => attachmentApi.remove(id),
    onSuccess: () => queryClient.invalidateQueries({ queryKey: ['employee-attachments', employeeId] }),
  })

  const handleFileUpload = (e: React.ChangeEvent<HTMLInputElement>) => {
    const files = e.target.files
    if (!files || files.length === 0) return

    const allowedExts = ['.pdf', '.jpg', '.jpeg', '.png', '.heic', '.gif', '.bmp', '.webp', '.doc', '.docx', '.xls', '.xlsx', '.tiff', '.tif']
    const maxSize = 10 * 1024 * 1024

    for (const file of Array.from(files)) {
      const ext = file.name.toLowerCase().substring(file.name.lastIndexOf('.'))
      if (!allowedExts.includes(ext)) {
        toast.error(`不支持的文件格式: ${file.name}`)
        continue
      }
      if (file.size > maxSize) {
        toast.error(`文件过大: ${file.name}（最大 10MB）`)
        continue
      }
      const reader = new FileReader()
      reader.onload = (event) => {
        const fileUrl = event.target?.result as string
        addAttachmentMutation.mutate({
          employeeId,
          fileName: file.name,
          fileType,
          fileUrl,
          fileSize: file.size,
        })
      }
      reader.readAsDataURL(file)
    }
    e.target.value = ''
  }

  const fileTypeLabels: Record<string, string> = {
    ID_CARD: '身份证',
    BANK_CARD: '银行卡',
    CONTRACT_SCAN: '合同附件',
    EDUCATION: '学历证书',
    TERMINATION_DOC: '解除文件',
    RETIREMENT_DOC: '退休档案',
    INJURY_CERT: '工伤认定',
    MEDICAL_CERT: '医疗期证明',
    PREGNANCY_CERT: '三期证明',
    OTHER: '其他',
  }

  const emp = employee?.data || employee

  return (
    <div className="fixed inset-0 z-50 flex justify-end">
      <button className="fixed inset-0 bg-black/40 cursor-default" onClick={onClose} aria-label="关闭" />
      <div className="relative w-full max-w-2xl bg-white h-full overflow-y-auto shadow-xl">
        <div className="flex items-center justify-between px-5 py-3 border-b border-gray-200 sticky top-0 bg-white z-10">
          <h3 className="font-medium text-gray-900">员工详情</h3>
          <button onClick={onClose} className="text-gray-500 hover:text-gray-700" aria-label="关闭">
            <X className="w-5 h-5" />
          </button>
        </div>

        <div className="p-5 space-y-4">
          {emp && (
            <>
              <div className="space-y-2">
                <div className="flex items-center gap-2">
                  <h2 className="text-sm font-medium">{emp.name}</h2>
                  <span className="text-xs text-gray-500">{emp.department}</span>
                </div>
                <div className="grid grid-cols-2 gap-2 text-xs">
                  <div><span className="text-gray-400">入职日期：</span>{emp.hireDate?.slice(0, 10)}</div>
                  <div><span className="text-gray-400">性别：</span>{emp.gender || '-'}</div>
                  <div><span className="text-gray-400">手机：</span>{emp.phone || '-'}</div>
                  <div><span className="text-gray-400">状态：</span>{emp.status === 'ACTIVE' ? '在职' : '离职'}</div>
                </div>
                {(emp.isPregnant || emp.isInMedicalPeriod || emp.isWorkInjured) && (
                  <div className="flex gap-1">
                    {emp.isPregnant && <span className="text-xs px-1.5 py-0.5 rounded bg-pink-50 text-pink-600">孕期</span>}
                    {emp.isInMedicalPeriod && <span className="text-xs px-1.5 py-0.5 rounded bg-orange-50 text-orange-600">医疗期</span>}
                    {emp.isWorkInjured && <span className="text-xs px-1.5 py-0.5 rounded bg-red-50 text-red-600">工伤</span>}
                  </div>
                )}
              </div>

              {emp.contracts && emp.contracts.length > 0 && (
                <div className="border-t pt-3">
                  <h3 className="font-medium text-xs mb-2">合同信息</h3>
                  <div className="space-y-2 text-xs">
                    {emp.contracts.map((c: any) => (
                      <div key={c.id} className="bg-gray-50 rounded p-2">
                        <div className="flex items-center gap-2">
                          {(() => {
                            const typeLabel = c.contractType === 'FIXED' ? '固定期限' : c.contractType === 'UNFIXED' ? '无固定期限' : '未签'
                            const typeStyle = c.contractType === 'UNSIGNED' ? 'bg-red-50 text-danger' : 'bg-blue-50 text-blue-700'
                            return <span className={`px-2 py-0.5 rounded text-xs ${typeStyle}`}>{typeLabel}</span>
                          })()}
                        </div>
                        <div className="text-gray-500 text-xs mt-1">
                          {c.startDate?.slice(0, 10)} ~ {c.endDate?.slice(0, 10) || '无固定期限'}
                        </div>
                      </div>
                    ))}
                  </div>
                </div>
              )}
            </>
          )}

          <div className="border-t pt-3">
            <div className="flex items-center justify-between mb-3">
              <h3 className="font-medium text-xs flex items-center gap-1">
                <Paperclip className="w-4 h-4" /> 附件管理
              </h3>
            </div>

            <div className="flex gap-2 mb-3">
              <Select value={fileType} onChange={(e) => setFileType(e.target.value as any)} className="text-xs">
                <option value="ID_CARD">身份证</option>
                <option value="BANK_CARD">银行卡</option>
                <option value="CONTRACT_SCAN">合同附件</option>
                <option value="EDUCATION">学历证书</option>
                <option value="TERMINATION_DOC">解除文件</option>
                <option value="RETIREMENT_DOC">退休档案</option>
                <option value="INJURY_CERT">工伤认定</option>
                <option value="MEDICAL_CERT">医疗期证明</option>
                <option value="PREGNANCY_CERT">三期证明</option>
                <option value="OTHER">其他</option>
              </Select>
              <input
                ref={fileInputRef}
                type="file"
                multiple
                className="hidden"
                onChange={handleFileUpload}
              />
              <Button
                size="sm"
                variant="secondary"
                onClick={() => fileInputRef.current?.click()}
                disabled={addAttachmentMutation.isPending}
              >
                {addAttachmentMutation.isPending ? '上传中...' : '上传附件'}
              </Button>
            </div>
            <p className="text-xs text-gray-400 mb-2">支持 PDF、图片、Word、Excel 等格式，每个文件最大 10MB</p>

            {attachments && attachments.length > 0 ? (
              <div className="space-y-2">
                {attachments.map((att: any) => (
                  <div key={att.id} className="flex items-center justify-between bg-gray-50 rounded p-2 text-xs">
                    <div className="flex items-center gap-2 min-w-0">
                      <Paperclip className="w-4 h-4 text-gray-400 shrink-0" />
                      <div className="min-w-0">
                        <button onClick={() => setPreviewUrl(att.fileUrl)} className="text-primary hover:underline truncate text-left">
                          {att.fileName}
                        </button>
                        <div className="text-xs text-gray-400">
                          {fileTypeLabels[att.fileType] || att.fileType} · {new Date(att.createdAt).toLocaleDateString('zh-CN')}
                        </div>
                      </div>
                    </div>
                    <div className="flex items-center gap-1 shrink-0 ml-2">
                      <a href={att.fileUrl} download={att.fileName} className="text-gray-400 hover:text-primary p-1" title="下载">
                        <Download className="w-4 h-4" />
                      </a>
                      <button
                        onClick={() => deleteAttachmentMutation.mutate(att.id)}
                        className="text-gray-400 hover:text-danger p-1"
                        title="删除"
                      >
                        <Trash2 className="w-4 h-4" />
                      </button>
                    </div>
                  </div>
                ))}
              </div>
            ) : (
              <div className="text-gray-400 text-xs text-center py-4">暂无附件</div>
            )}
          </div>
        </div>
      </div>

      {/* 附件预览弹窗 */}
      {previewUrl && (() => {
        const dataToBlobUrl = (dataUrl: string) => {
          try {
            const arr = dataUrl.split(',')
            const mime = arr[0].match(/:(.*?);/)?.[1] || 'application/octet-stream'
            const bstr = atob(arr[1])
            const u8 = new Uint8Array(bstr.length)
            for (let i = 0; i < bstr.length; i++) u8[i] = bstr.charCodeAt(i)
            return URL.createObjectURL(new Blob([u8], { type: mime }))
          } catch { return dataUrl }
        }
        const blobUrl = previewUrl.startsWith('data:') ? dataToBlobUrl(previewUrl) : previewUrl
        const mime = previewUrl.startsWith('data:') ? previewUrl.match(/data:(.*?);/)?.[1] || '' : ''
        const isImage = mime.startsWith('image/')
        const isPdf = mime === 'application/pdf'

        return (
        <div className="fixed inset-0 z-[60] flex items-center justify-center bg-black/50" onClick={() => { if (blobUrl !== previewUrl) URL.revokeObjectURL(blobUrl); setPreviewUrl(null) }}>
          <div className="bg-white rounded-lg shadow-xl max-w-4xl w-full h-[90vh] flex flex-col" onClick={e => e.stopPropagation()}>
            <div className="flex items-center justify-between px-4 py-2 border-b">
              <span className="text-sm font-medium">附件预览</span>
              <div className="flex items-center gap-2">
                <a href={blobUrl} download="附件" className="text-xs text-primary hover:underline flex items-center gap-1">
                  <Download className="w-3 h-3" />下载
                </a>
                <button onClick={() => { if (blobUrl !== previewUrl) URL.revokeObjectURL(blobUrl); setPreviewUrl(null) }} className="text-gray-400 hover:text-gray-600">
                  <X className="w-4 h-4" />
                </button>
              </div>
            </div>
            <div className="flex-1 overflow-auto flex items-center justify-center p-4">
              {isImage ? (
                <img src={blobUrl} alt="附件预览" className="max-w-full max-h-full object-contain" />
              ) : isPdf ? (
                <embed src={blobUrl} type="application/pdf" className="w-full h-full" />
              ) : (
                <div className="text-center space-y-3">
                  <FileText className="w-12 h-12 text-gray-300 mx-auto" />
                  <p className="text-sm text-gray-500">此文件格式不支持在线预览</p>
                  <a href={blobUrl} download="附件" className="inline-flex items-center gap-1 text-sm text-primary hover:underline">
                    <Download className="w-4 h-4" />点击下载查看
                  </a>
                </div>
              )}
            </div>
          </div>
        </div>
        )
      })()}
    </div>
  )
}
