/**
 * 待签合同 / 电子签署管理页面
 * - Tab1 待签合同：按员工聚合展示所有未签署文件，支持催办（生成二维码/链接）
 * - Tab2 签署记录：全部签署记录列表（状态/场景/签署方式筛选）
 * - 发起电子签署（场景选择 + 模板自动渲染 + 组织开关校验）
 * - 线下手签登记（上传扫描件 + 签署信息 + 证据链）
 * - 签署详情（含证据链查看）
 * - 取消签署
 */
import { useState, useRef, useEffect, Fragment } from 'react'
import { useSearchParams } from 'react-router-dom'
import { toast } from 'sonner'
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import { QRCodeSVG } from 'qrcode.react'
import { PenTool, Plus, RefreshCw, ExternalLink, FileText, AlertCircle, Shield, ChevronLeft, Clock, CheckCircle2, XCircle, Eye, Upload, FileCheck, Bell, Copy, Check, ChevronDown, ChevronRight, User } from 'lucide-react'
import { esignApi, employeeApi } from '../lib/api-services'
import PageGuide from '../components/ui/PageGuide'
import Card from '../components/ui/Card'
import Button from '../components/ui/Button'
import { Input, Label, Select } from '../components/ui/Input'
import { InlineAlert } from '../components/ui/InlineAlert'
import Modal from '../components/ui/Modal'

const STATUS_CONFIG: Record<string, { label: string; color: string; icon: React.ReactNode }> = {
  PENDING: { label: '待签署', color: 'bg-yellow-50 text-yellow-700', icon: <Clock className="w-3 h-3" /> },
  SIGNING: { label: '签署中', color: 'bg-blue-50 text-blue-700', icon: <Clock className="w-3 h-3" /> },
  COMPLETED: { label: '已完成', color: 'bg-green-50 text-safe', icon: <CheckCircle2 className="w-3 h-3" /> },
  REJECTED: { label: '已拒绝', color: 'bg-red-50 text-danger', icon: <XCircle className="w-3 h-3" /> },
  EXPIRED: { label: '已过期', color: 'bg-gray-100 text-gray-500', icon: <XCircle className="w-3 h-3" /> },
  CANCELLED: { label: '已取消', color: 'bg-gray-100 text-gray-500', icon: <XCircle className="w-3 h-3" /> },
}

const SCENE_CONFIG: Record<string, { label: string; color: string }> = {
  CONTRACT: { label: '劳动合同', color: 'bg-blue-50 text-blue-600 border border-blue-200' },
  RESIGNATION: { label: '离职协议', color: 'bg-orange-50 text-orange-600 border border-orange-200' },
  POLICY: { label: '规章制度', color: 'bg-amber-50 text-amber-600 border border-amber-200' },
  PAYSLIP: { label: '工资条', color: 'bg-emerald-50 text-emerald-600 border border-emerald-200' },
  ONBOARDING: { label: '入职文件', color: 'bg-purple-50 text-purple-600 border border-purple-200' },
}

const SIGN_METHOD_CONFIG: Record<string, { label: string; color: string }> = {
  ELECTRONIC: { label: '电子签', color: 'bg-blue-50 text-blue-600' },
  PAPER: { label: '线下手签', color: 'bg-orange-50 text-orange-600' },
}

export default function ESign() {
  const queryClient = useQueryClient()
  const [activeTab, setActiveTab] = useState<'pending' | 'records'>('pending')
  const [filterStatus, setFilterStatus] = useState('')
  const [filterScene, setFilterScene] = useState('')
  const [showCreate, setShowCreate] = useState(false)
  const [showPaperSign, setShowPaperSign] = useState(false)
  const [detailId, setDetailId] = useState<string | null>(null)
  const [searchParams] = useSearchParams()
  const [formData, setFormData] = useState({
    employeeId: '',
    scene: 'CONTRACT',
    documentTitle: '',
    remark: '',
  })

  // 从 URL 参数读取，自动打开线下手签登记
  useEffect(() => {
    const action = searchParams.get('action')
    if (action === 'paper-sign') {
      setShowPaperSign(true)
      // 预填表单
      const employeeId = searchParams.get('employeeId')
      const scene = searchParams.get('scene') as string
      const documentTitle = searchParams.get('documentTitle') as string
      if (employeeId || scene || documentTitle) {
        setFormData({
          employeeId: employeeId || '',
          scene: scene || 'CONTRACT',
          documentTitle: documentTitle || '',
          remark: '花名册操作跳转登记',
        })
      }
    }
  }, [searchParams])

  const { data: records = [], isLoading } = useQuery<any[]>({
    queryKey: ['esign-records', filterStatus, filterScene],
    queryFn: async () => {
      return await esignApi.list({ status: filterStatus || undefined, scene: filterScene || undefined })
    },
  })

  /** 待签合同列表（按员工聚合） */
  const { data: pendingList = [], isLoading: pendingLoading } = useQuery<any[]>({
    queryKey: ['esign-pending'],
    queryFn: async () => {
      return await esignApi.pending()
    },
  })

  /** 催办（生成自动登录链接） */
  const remindMutation = useMutation({
    mutationFn: (employeeId: string) => esignApi.remind(employeeId) as any,
    onSuccess: (data: any) => {
      queryClient.invalidateQueries({ queryKey: ['esign-pending'] })
      toast.success(`催办链接已生成，可复制或展示二维码给员工`, {
        description: data?.phone ? `员工手机：${data.phone}` : '',
      })
    },
    onError: (err: any) => toast.error(err?.response?.data?.error?.message || '催办失败'),
  })

  const { data: rosterData = [] } = useQuery<any[]>({
    queryKey: ['employees-for-esign'],
    queryFn: async () => {
      return await employeeApi.allLite({ status: 'ACTIVE' })
    },
    enabled: showCreate,
  })

  const createMutation = useMutation({
    mutationFn: async (data: { employeeId: string; scene: string; documentTitle: string; remark?: string }) =>
      esignApi.create(data) as any,
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['esign-records'] })
      setShowCreate(false)
      setFormData({ employeeId: '', scene: 'CONTRACT', documentTitle: '', remark: '' })
      toast.success('签署记录已创建，员工可在员工端查看并签署')
    },
    onError: (err: any) => {
      toast.error(err?.response?.data?.error?.message || '创建失败')
    },
  })

  const cancelMutation = useMutation({
    mutationFn: (id: string) => esignApi.cancel(id),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['esign-records'] })
      toast.success('已取消签署')
    },
  })

  const refreshStatusMutation = useMutation({
    mutationFn: (id: string) => esignApi.status(id),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['esign-records'] })
      toast.success('状态已刷新')
    },
  })

  const handleCreate = () => {
    if (!formData.employeeId) { toast.error('请选择员工'); return }
    if (!formData.documentTitle.trim()) { toast.error('请填写文件标题'); return }
    createMutation.mutate(formData)
  }

  // ===== 签署详情视图 =====
  if (detailId) {
    return <ESignDetail id={detailId} onBack={() => setDetailId(null)} />
  }

  return (
    <div className="space-y-4">
      <PageGuide>
        管理员工合同、协议、规章等文件的签署。未签署的按员工聚合在「待签合同」中催办；已签署的记录在「签署记录」中查看。
      </PageGuide>
      <div className="flex items-center gap-2">
        <PenTool 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>

      {/* Tab 切换 */}
      <div className="flex items-center justify-between">
        <div className="flex gap-1 border-b">
          <button
            onClick={() => setActiveTab('pending')}
            className={`px-4 py-2 text-sm font-medium border-b-2 transition-colors ${activeTab === 'pending' ? 'border-primary text-primary' : 'border-transparent text-gray-500 hover:text-gray-700'}`}
          >
            待签合同
            {pendingList.length > 0 && <span className="ml-1.5 px-1.5 py-0.5 rounded-full text-xs bg-yellow-100 text-yellow-700">{pendingList.length}</span>}
          </button>
          <button
            onClick={() => setActiveTab('records')}
            className={`px-4 py-2 text-sm font-medium border-b-2 transition-colors ${activeTab === 'records' ? 'border-primary text-primary' : 'border-transparent text-gray-500 hover:text-gray-700'}`}
          >
            签署记录
            {records.length > 0 && <span className="ml-1.5 px-1.5 py-0.5 rounded-full text-xs bg-blue-100 text-blue-700">{records.length}</span>}
          </button>
        </div>
        <div className="flex gap-2">
          <Button size="sm" onClick={() => setShowCreate(true)}>
            <Plus className="w-4 h-4 mr-1" />发起电子签署
          </Button>
          <Button size="sm" variant="secondary" onClick={() => setShowPaperSign(true)}>
            <FileCheck className="w-4 h-4 mr-1" />线下手签登记
          </Button>
        </div>
      </div>

      {/* ===== Tab1: 待签合同（按员工聚合） ===== */}
      {activeTab === 'pending' && (
        <PendingTab pendingList={pendingList} loading={pendingLoading} onRemind={(empId) => remindMutation.mutate(empId)} remindLoading={remindMutation.isPending} remindData={remindMutation.data} onDetail={(id) => setDetailId(id)} />
      )}

      {/* ===== Tab2: 签署记录 ===== */}
      {activeTab === 'records' && (
        <>
      <div className="flex items-center justify-between">
        <div className="flex gap-2">
          <select
            value={filterStatus}
            onChange={(e) => setFilterStatus(e.target.value)}
            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>
            {Object.entries(STATUS_CONFIG).map(([k, v]) => <option key={k} value={k}>{v.label}</option>)}
          </select>
          <select
            value={filterScene}
            onChange={(e) => setFilterScene(e.target.value)}
            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>
            {Object.entries(SCENE_CONFIG).map(([k, v]) => <option key={k} value={k}>{v.label}</option>)}
          </select>
        </div>
      </div>

      {/* 签署记录列表 */}
      <Card>
        {isLoading ? (
          <div className="text-center py-8 text-gray-400">加载中...</div>
        ) : records.length === 0 ? (
          <div className="text-center py-8 text-gray-400 text-sm">暂无签署记录，点击「发起签署」创建</div>
        ) : (
          <div className="overflow-x-auto">
            <table className="w-full text-sm">
              <thead>
                <tr className="border-b text-xs text-gray-500">
                  <th className="py-2 px-3 text-left">文件标题</th>
                  <th className="py-2 px-3 text-left">签署人</th>
                  <th className="py-2 px-3 text-left">部门</th>
                  <th className="py-2 px-3 text-left">签署方式</th>
                  <th className="py-2 px-3 text-left">状态</th>
                  <th className="py-2 px-3 text-left">发起时间</th>
                  <th className="py-2 px-3 text-left">完成时间</th>
                  <th className="py-2 px-3 text-right">操作</th>
                </tr>
              </thead>
              <tbody>
                {records.map((r: any) => {
                  const statusCfg = STATUS_CONFIG[r.status] || STATUS_CONFIG.PENDING
                  return (
                    <tr key={r.id} className="border-b last:border-0 hover:bg-gray-50">
                      <td className="py-2 px-3">
                        <div className="flex items-center gap-1.5">
                          <FileText className="w-3.5 h-3.5 text-gray-400 shrink-0" />
                          <button className="font-medium truncate max-w-[200px] text-left hover:text-primary" onClick={() => setDetailId(r.id)}>
                            {r.documentTitle}
                          </button>
                          {r.scene && SCENE_CONFIG[r.scene] && (
                            <span className={`px-1.5 py-0.5 rounded text-xs shrink-0 ${SCENE_CONFIG[r.scene].color}`}>{SCENE_CONFIG[r.scene].label}</span>
                          )}
                        </div>
                        {r.remark && <div className="text-xs text-gray-400 mt-0.5">{r.remark}</div>}
                      </td>
                      <td className="py-2 px-3">
                        <div className="flex flex-col gap-0.5">
                          <span>{r.employee?.name || '—'}</span>
                          {r.employee?.idCardNumber && <span className="text-gray-400 text-[11px] font-mono">{r.employee.idCardNumber}</span>}
                        </div>
                      </td>
                      <td className="py-2 px-3 text-gray-500">{r.employee?.department || '—'}</td>
                      <td className="py-2 px-3">
                        <span className={`px-1.5 py-0.5 rounded text-xs ${(SIGN_METHOD_CONFIG[r.signMethod] || SIGN_METHOD_CONFIG.ELECTRONIC).color}`}>
                          {(SIGN_METHOD_CONFIG[r.signMethod] || SIGN_METHOD_CONFIG.ELECTRONIC).label}
                        </span>
                      </td>
                      <td className="py-2 px-3">
                        <span className={`inline-flex items-center gap-1 px-2 py-0.5 rounded text-xs ${statusCfg.color}`}>
                          {statusCfg.icon}{statusCfg.label}
                        </span>
                      </td>
                      <td className="py-2 px-3 text-gray-500 text-xs">{new Date(r.createdAt).toLocaleString('zh-CN')}</td>
                      <td className="py-2 px-3 text-gray-500 text-xs">{r.completedAt ? new Date(r.completedAt).toLocaleString('zh-CN') : '—'}</td>
                      <td className="py-2 px-3 text-right">
                        <div className="flex items-center justify-end gap-1">
                          <button className="text-xs text-gray-400 hover:text-primary" onClick={() => setDetailId(r.id)} title="查看详情">
                            <Eye className="w-3.5 h-3.5" />
                          </button>
                          {r.status === 'COMPLETED' && r.signedPdfUrl && (
                            <a href={r.signedPdfUrl} target="_blank" rel="noopener noreferrer"
                              className="text-xs text-primary hover:underline flex items-center gap-0.5">
                              <ExternalLink className="w-3 h-3" />PDF
                            </a>
                          )}
                          {r.status === 'COMPLETED' && r.signMethod === 'PAPER' && (r as any).scanFileUrls && (
                            <a href={(r as any).scanFileUrls[0]?.url} target="_blank" rel="noopener noreferrer"
                              className="text-xs text-primary hover:underline flex items-center gap-0.5">
                              <ExternalLink className="w-3 h-3" />扫描件
                            </a>
                          )}
                          {(r.status === 'PENDING' || r.status === 'SIGNING') && (
                            <>
                              <button className="text-xs text-gray-400 hover:text-primary" onClick={() => refreshStatusMutation.mutate(r.id)}
                                title="刷新状态">
                                <RefreshCw className={`w-3.5 h-3.5 ${refreshStatusMutation.isPending ? 'animate-spin' : ''}`} />
                              </button>
                              <button className="text-xs text-gray-400 hover:text-danger" onClick={() => {
                                if (confirm('确定取消此签署任务吗？')) cancelMutation.mutate(r.id)
                              }}>取消</button>
                            </>
                          )}
                        </div>
                      </td>
                    </tr>
                  )
                })}
              </tbody>
            </table>
          </div>
        )}
      </Card>
        </>
      )}

      {/* 发起签署 Modal */}
      {showCreate && (
        <Modal open={true} onClose={() => setShowCreate(false)} title="发起电子签署" size="md">
          <div className="space-y-3">
            <InlineAlert type="info">
              选择员工和签署场景，系统将自动从模板渲染文件内容，创建签署记录并发起证据链。员工可在员工端查看文件并通过验证码签署。
            </InlineAlert>
            <div>
              <Label>签署员工 *</Label>
              <select
                className="h-9 w-full 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"
                value={formData.employeeId}
                onChange={(e) => setFormData({ ...formData, employeeId: e.target.value })}
              >
                <option value="">请选择员工</option>
                {rosterData.map((emp: any) => (
                  <option key={emp.id} value={emp.id}>{emp.name}{emp.idCardNumber ? `（${emp.idCardNumber}）` : ''} - {emp.department}</option>
                ))}
              </select>
            </div>
            <div>
              <Label>签署场景 *</Label>
              <select
                className="h-9 w-full 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"
                value={formData.scene}
                onChange={(e) => {
                  const scene = e.target.value
                  const defaultTitle: Record<string, string> = {
                    CONTRACT: '劳动合同书',
                    RESIGNATION: '协商解除劳动合同协议书',
                    POLICY: '规章制度签收确认书',
                    PAYSLIP: '工资条确认书',
                    ONBOARDING: '入职文件签署',
                  }
                  setFormData({ ...formData, scene, documentTitle: defaultTitle[scene] || '' })
                }}
              >
                {Object.entries(SCENE_CONFIG).map(([k, v]) => <option key={k} value={k}>{v.label}</option>)}
              </select>
            </div>
            <div>
              <Label>文件标题 *</Label>
              <Input value={formData.documentTitle} onChange={(e) => setFormData({ ...formData, documentTitle: e.target.value })}
                placeholder="如：2024年度劳动合同" />
            </div>
            <div>
              <Label>备注</Label>
              <Input value={formData.remark} onChange={(e) => setFormData({ ...formData, remark: e.target.value })}
                placeholder="可选" />
            </div>
            <div className="text-xs text-gray-400 bg-gray-50 rounded p-2">
              <div className="font-medium text-gray-500 mb-1">签署流程说明</div>
              <div>1. 创建后员工在员工端「我的电子签署」中看到待签文件</div>
              <div>2. 员工点击「签署」→ 获取手机验证码 → 输入验证码确认</div>
              <div>3. 签署完成自动记录证据链（IP/时间戳/验证码），可在此详情页查看</div>
              {formData.scene === 'CONTRACT' && <div>4. 关联合同的签署完成后自动回写合同签署方式为「电子签署」</div>}
            </div>
            <div className="flex justify-end gap-2 pt-2">
              <Button variant="secondary" size="sm" onClick={() => setShowCreate(false)}>取消</Button>
              <Button size="sm" onClick={handleCreate} disabled={createMutation.isPending}>
                {createMutation.isPending ? '创建中...' : '发起签署'}
              </Button>
            </div>
          </div>
        </Modal>
      )}

      {/* 线下手签登记 Modal */}
      {showPaperSign && (
        <PaperSignModal
          initialEmployeeId={formData.employeeId}
          initialScene={formData.scene as any}
          initialDocumentTitle={formData.documentTitle}
          initialRemark={formData.remark}
          onClose={() => { setShowPaperSign(false); setFormData({ employeeId: '', scene: 'CONTRACT', documentTitle: '', remark: '' }) }}
          onSuccess={() => {
            queryClient.invalidateQueries({ queryKey: ['esign-records'] })
            setShowPaperSign(false)
            setFormData({ employeeId: '', scene: 'CONTRACT', documentTitle: '', remark: '' })
          }}
        />
      )}
    </div>
  )
}

// ===== 线下手签登记 Modal =====
function PaperSignModal({ onClose, onSuccess, initialEmployeeId, initialScene, initialDocumentTitle, initialRemark }: {
  onClose: () => void
  onSuccess: () => void
  initialEmployeeId?: string
  initialScene?: string
  initialDocumentTitle?: string
  initialRemark?: string
}) {
  const fileInputRef = useRef<HTMLInputElement>(null)
  const [form, setForm] = useState({
    employeeId: initialEmployeeId || '',
    scene: initialScene || 'CONTRACT',
    documentTitle: initialDocumentTitle || '',
    signedAt: new Date().toISOString().slice(0, 10),
    signedLocation: '',
    witnessName: '',
    witnessPhone: '',
    remark: initialRemark || '',
  })
  const [scanFiles, setScanFiles] = useState<Array<{ name: string; url: string }>>([])
  const [uploading, setUploading] = useState(false)

  const { data: rosterData = [] } = useQuery<any[]>({
    queryKey: ['employees-for-paper-sign'],
    queryFn: () => employeeApi.allLite({ status: 'ACTIVE' }),
  })

  const paperSignMutation = useMutation({
    mutationFn: (data: any) => esignApi.paperSign(data),
    onSuccess: () => {
      toast.success('线下手签登记成功，证据链已记录')
      onSuccess()
    },
    onError: (err: any) => toast.error(err?.response?.data?.error?.message || '登记失败'),
  })

  const handleFileUpload = async (e: React.ChangeEvent<HTMLInputElement>) => {
    const files = e.target.files
    if (!files || files.length === 0) return
    const allowedExts = ['.jpg', '.jpeg', '.png', '.pdf', '.bmp', '.webp', '.tiff', '.tif']
    const validFiles: File[] = []
    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 > 10 * 1024 * 1024) {
        toast.error(`文件过大: ${file.name}（最大10MB）`)
        continue
      }
      validFiles.push(file)
    }
    if (validFiles.length === 0) return

    setUploading(true)
    try {
      const res = await esignApi.uploadPaperSign(validFiles)
      setScanFiles(prev => [...prev, ...res])
      toast.success(`已上传 ${res.length} 个文件`)
    } catch (err: any) {
      toast.error(err?.response?.data?.error?.message || '上传失败')
    } finally {
      setUploading(false)
    }
    e.target.value = ''
  }

  const handleSubmit = () => {
    if (!form.employeeId) { toast.error('请选择员工'); return }
    if (!form.documentTitle.trim()) { toast.error('请填写文件标题'); return }
    if (!form.signedAt) { toast.error('请选择签署日期'); return }
    if (scanFiles.length === 0) { toast.error('请至少上传一份签署扫描件'); return }
    paperSignMutation.mutate({ ...form, scanFileUrls: scanFiles })
  }

  return (
    <Modal open={true} onClose={onClose} title="线下手签登记" size="md">
      <div className="space-y-3">
        <InlineAlert type="info">
          登记员工线下手签的合同/协议，上传签署后的纸质文件扫描件。系统自动记录证据链（签署日期、地点、见证人、扫描件），与电子签署具有同等证据效力。
        </InlineAlert>
        <div>
          <Label>签署员工 *</Label>
          <select
            className="h-9 w-full 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"
            value={form.employeeId}
            onChange={(e) => setForm({ ...form, employeeId: e.target.value })}
          >
            <option value="">请选择员工</option>
            {rosterData.map((emp: any) => (
              <option key={emp.id} value={emp.id}>{emp.name}{emp.idCardNumber ? `（${emp.idCardNumber}）` : ''} - {emp.department}</option>
            ))}
          </select>
        </div>
        <div>
          <Label>文件类型 *</Label>
          <select
            className="h-9 w-full 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"
            value={form.scene}
            onChange={(e) => {
              const scene = e.target.value
              const defaultTitle: Record<string, string> = {
                CONTRACT: '劳动合同书',
                RESIGNATION: '解除劳动合同协议书',
                POLICY: '规章制度签收确认书',
                PAYSLIP: '工资条确认书',
                ONBOARDING: '入职文件',
              }
              setForm({ ...form, scene, documentTitle: defaultTitle[scene] || '' })
            }}
          >
            {Object.entries(SCENE_CONFIG).map(([k, v]) => <option key={k} value={k}>{v.label}</option>)}
          </select>
        </div>
        <div>
          <Label>文件标题 *</Label>
          <Input value={form.documentTitle} onChange={(e) => setForm({ ...form, documentTitle: e.target.value })}
            placeholder="如：2024年度劳动合同" />
        </div>
        <div className="grid grid-cols-2 gap-2">
          <div>
            <Label>签署日期 *</Label>
            <Input type="date" max={new Date().toISOString().slice(0, 10)} value={form.signedAt} onChange={(e) => setForm({ ...form, signedAt: e.target.value })} />
          </div>
          <div>
            <Label>签署地点</Label>
            <Input value={form.signedLocation} onChange={(e) => setForm({ ...form, signedLocation: e.target.value })}
              placeholder="如：公司会议室" />
          </div>
          <div>
            <Label>见证人姓名</Label>
            <Input value={form.witnessName} onChange={(e) => setForm({ ...form, witnessName: e.target.value })}
              placeholder="可选" />
          </div>
          <div>
            <Label>见证人手机号</Label>
            <Input value={form.witnessPhone} onChange={(e) => setForm({ ...form, witnessPhone: e.target.value })}
              placeholder="可选" />
          </div>
        </div>
        <div>
          <Label>签署扫描件 *</Label>
          <div className="border-2 border-dashed border-gray-200 rounded-md p-4 text-center">
            <input
              ref={fileInputRef}
              type="file"
              multiple
              accept=".jpg,.jpeg,.png,.pdf,.bmp,.webp,.tiff,.tif"
              onChange={handleFileUpload}
              className="hidden"
            />
            <button
              onClick={() => fileInputRef.current?.click()}
              disabled={uploading}
              className="text-sm text-primary hover:underline"
            >
              <Upload className="w-4 h-4 inline mr-1" />
              {uploading ? '上传中...' : '点击上传扫描件'}
            </button>
            <div className="text-xs text-gray-400 mt-1">支持 JPG/PNG/PDF/BMP/WEBP/TIFF，单个最大10MB</div>
          </div>
          {scanFiles.length > 0 && (
            <div className="mt-2 space-y-1">
              {scanFiles.map((f, i) => (
                <div key={i} className="flex items-center gap-2 text-xs bg-gray-50 rounded px-2 py-1.5">
                  <FileText className="w-3.5 h-3.5 text-gray-400 shrink-0" />
                  <a href={f.url} target="_blank" rel="noopener noreferrer" className="text-primary hover:underline flex-1 truncate">{f.name}</a>
                  <button
                    onClick={() => setScanFiles(prev => prev.filter((_, idx) => idx !== i))}
                    className="text-gray-400 hover:text-danger"
                  >删除</button>
                </div>
              ))}
            </div>
          )}
        </div>
        <div>
          <Label>备注</Label>
          <Input value={form.remark} onChange={(e) => setForm({ ...form, remark: e.target.value })}
            placeholder="可选" />
        </div>
        <div className="flex justify-end gap-2 pt-2">
          <Button variant="secondary" size="sm" onClick={onClose}>取消</Button>
          <Button size="sm" onClick={handleSubmit} disabled={paperSignMutation.isPending || uploading}>
            {paperSignMutation.isPending ? '登记中...' : '确认登记'}
          </Button>
        </div>
      </div>
    </Modal>
  )
}

// ===== 签署详情组件 =====
function ESignDetail({ id, onBack }: { id: string; onBack: () => void }) {
  const { data: detail, isLoading } = useQuery<any>({
    queryKey: ['esign-detail', id],
    queryFn: () => esignApi.detail(id),
  })
  const { data: evidence = [] } = useQuery<any[]>({
    queryKey: ['esign-evidence', id],
    queryFn: () => esignApi.evidence(id),
  })

  if (isLoading) {
    return (
      <div className="space-y-4">
        <button onClick={onBack} className="flex items-center gap-1 text-gray-500 hover:text-gray-700 text-sm py-2">
          <ChevronLeft className="w-4 h-4" />返回列表
        </button>
        <Card className="p-6"><div className="text-center text-gray-400">加载中...</div></Card>
      </div>
    )
  }

  if (!detail) {
    return (
      <div className="space-y-4">
        <button onClick={onBack} className="flex items-center gap-1 text-gray-500 hover:text-gray-700 text-sm py-2">
          <ChevronLeft className="w-4 h-4" />返回列表
        </button>
        <Card className="p-6"><div className="text-center text-gray-400">记录不存在</div></Card>
      </div>
    )
  }

  const statusCfg = STATUS_CONFIG[detail.status] || STATUS_CONFIG.PENDING
  const sceneCfg = SCENE_CONFIG[detail.scene] || SCENE_CONFIG.CONTRACT

  return (
    <div className="space-y-4">
      <button onClick={onBack} className="flex items-center gap-1 text-gray-500 hover:text-gray-700 text-sm py-2">
        <ChevronLeft className="w-4 h-4" />返回列表
      </button>

      {/* 基本信息 */}
      <Card className="p-5">
        <div className="flex items-center gap-3 mb-4">
          <div className="w-10 h-10 rounded-xl bg-primary/10 flex items-center justify-center">
            <FileText className="w-5 h-5 text-primary" />
          </div>
          <div className="flex-1">
            <div className="flex items-center gap-2">
              <h2 className="text-base font-semibold">{detail.documentTitle}</h2>
              <span className={`px-1.5 py-0.5 rounded text-xs ${sceneCfg.color}`}>{sceneCfg.label}</span>
              <span className={`px-1.5 py-0.5 rounded text-xs ${(SIGN_METHOD_CONFIG[detail.signMethod] || SIGN_METHOD_CONFIG.ELECTRONIC).color}`}>
                {(SIGN_METHOD_CONFIG[detail.signMethod] || SIGN_METHOD_CONFIG.ELECTRONIC).label}
              </span>
            </div>
            <div className="text-xs text-gray-400 mt-0.5">签署人：{detail.employee?.name} · {detail.employee?.department}{detail.employee?.idCardNumber && <span className="ml-1 font-mono">{detail.employee.idCardNumber}</span>}</div>
          </div>
          <span className={`inline-flex items-center gap-1 px-2.5 py-1 rounded text-xs ${statusCfg.color}`}>
            {statusCfg.icon}{statusCfg.label}
          </span>
        </div>

        <div className="grid grid-cols-2 gap-3 text-xs">
          <div>
            <div className="text-gray-400">发起时间</div>
            <div className="text-gray-700">{new Date(detail.createdAt).toLocaleString('zh-CN')}</div>
          </div>
          <div>
            <div className="text-gray-400">完成时间</div>
            <div className="text-gray-700">{detail.completedAt ? new Date(detail.completedAt).toLocaleString('zh-CN') : '—'}</div>
          </div>
          {detail.signMethod === 'PAPER' ? (
            <>
              <div>
                <div className="text-gray-400">签署日期</div>
                <div className="text-gray-700">{detail.signedAt ? new Date(detail.signedAt).toLocaleDateString('zh-CN') : '—'}</div>
              </div>
              <div>
                <div className="text-gray-400">签署地点</div>
                <div className="text-gray-700">{detail.signedLocation || '—'}</div>
              </div>
              <div>
                <div className="text-gray-400">见证人</div>
                <div className="text-gray-700">{detail.witnessName || '—'} {detail.witnessPhone ? `· ${detail.witnessPhone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2')}` : ''}</div>
              </div>
            </>
          ) : (
            <>
              <div>
                <div className="text-gray-400">过期时间</div>
                <div className="text-gray-700">{detail.expiredAt ? new Date(detail.expiredAt).toLocaleString('zh-CN') : '—'}</div>
              </div>
              <div>
                <div className="text-gray-400">员工手机</div>
                <div className="text-gray-700">{detail.employee?.phone ? detail.employee.phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2') : '—'}</div>
              </div>
            </>
          )}
          {detail.remark && (
            <div className="col-span-2">
              <div className="text-gray-400">备注</div>
              <div className="text-gray-700">{detail.remark}</div>
            </div>
          )}
        </div>
      </Card>

      {/* 线下手签扫描件 */}
      {detail.signMethod === 'PAPER' && detail.scanFileUrls && (detail.scanFileUrls as any[]).length > 0 && (
        <Card className="p-5">
          <div className="text-sm font-medium mb-3 flex items-center gap-1.5">
            <FileCheck className="w-4 h-4 text-orange-500" />签署扫描件
            <span className="text-xs text-gray-400 font-normal">（{(detail.scanFileUrls as any[]).length}份）</span>
          </div>
          <div className="space-y-2">
            {(detail.scanFileUrls as any[]).map((f: any, i: number) => (
              <div key={i} className="flex items-center gap-2 text-xs bg-gray-50 rounded px-3 py-2">
                <FileText className="w-4 h-4 text-gray-400 shrink-0" />
                <a href={f.url} target="_blank" rel="noopener noreferrer" className="text-primary hover:underline flex-1 truncate">{f.name}</a>
                <ExternalLink className="w-3 h-3 text-gray-400" />
              </div>
            ))}
          </div>
        </Card>
      )}

      {/* 文件内容预览 */}
      {detail.documentContent && (
        <Card className="p-5">
          <div className="text-sm font-medium mb-3 flex items-center gap-1.5">
            <FileText className="w-4 h-4 text-gray-400" />文件内容
          </div>
          <div className="text-xs text-gray-600 max-h-96 overflow-y-auto bg-gray-50 rounded p-3 whitespace-pre-wrap border">
            {detail.documentContent}
          </div>
        </Card>
      )}

      {/* 证据链 */}
      <Card className="p-5">
        <div className="text-sm font-medium mb-3 flex items-center gap-1.5">
          <Shield className="w-4 h-4 text-primary" />证据链记录
          <span className="text-xs text-gray-400 font-normal">（{evidence.length}条证据链）</span>
        </div>
        {evidence.length === 0 ? (
          <div className="text-xs text-gray-400 text-center py-4">暂无证据链记录</div>
        ) : (
          <div className="space-y-3">
            {evidence.map((ev: any, idx: number) => {
              const events = ev.events as any[]
              return (
                <div key={ev.id} className="border rounded-md p-3">
                  <div className="text-xs text-gray-400 mb-2">证据链 #{idx + 1} · 创建于 {new Date(ev.createdAt).toLocaleString('zh-CN')}</div>
                  <div className="space-y-2">
                    {events?.map((event: any, i: number) => (
                      <div key={i} className="flex items-start gap-2 text-xs">
                        <div className="w-1.5 h-1.5 rounded-full bg-primary mt-1.5 shrink-0" />
                        <div className="flex-1">
                          <div className="text-gray-700 font-medium">{event.action}</div>
                          <div className="text-gray-400 mt-0.5">
                            {new Date(event.timestamp).toLocaleString('zh-CN')}
                            {event.ip && ` · IP: ${event.ip}`}
                            {event.location && ` · ${event.location}`}
                          </div>
                        </div>
                      </div>
                    ))}
                  </div>
                  <div className="text-xs text-gray-300 mt-2 font-mono">hash: {ev.hash?.slice(0, 32)}...</div>
                </div>
              )
            })}
          </div>
        )}
      </Card>
    </div>
  )
}

/**
 * 待签合同 Tab — 按员工聚合展示待签文件，支持催办
 */
function PendingTab({ pendingList, loading, onRemind, remindLoading, remindData, onDetail }: {
  pendingList: any[]
  loading: boolean
  onRemind: (employeeId: string) => void
  remindLoading: boolean
  remindData: any
  onDetail: (id: string) => void
}) {
  const queryClient = useQueryClient()
  const [expandedEmp, setExpandedEmp] = useState<string | null>(null)
  const [remindEmpId, setRemindEmpId] = useState<string | null>(null)
  const [copied, setCopied] = useState(false)
  const [signDateEditing, setSignDateEditing] = useState<string | null>(null)
  const [signDateValue, setSignDateValue] = useState('')
  const [signDateSaving, setSignDateSaving] = useState(false)

  /** 保存签署日期 */
  const handleSaveSignDate = async (contractId: string) => {
    if (!signDateValue) { toast.error('请选择签署日期'); return }
    setSignDateSaving(true)
    try {
      await esignApi.signDate(contractId, signDateValue)
      toast.success('签署日期已登记')
      setSignDateEditing(null)
      setSignDateValue('')
      queryClient.invalidateQueries({ queryKey: ['esign-pending'] })
    } catch (err: any) {
      toast.error(err?.response?.data?.error?.message || '登记失败')
    } finally {
      setSignDateSaving(false)
    }
  }

  const handleCopy = (url: string) => {
    navigator.clipboard?.writeText(url)
    setCopied(true)
    setTimeout(() => setCopied(false), 2000)
  }

  if (loading) {
    return <Card><div className="text-center py-8 text-gray-400">加载中...</div></Card>
  }

  if (pendingList.length === 0) {
    return (
      <Card>
        <div className="text-center py-8 text-gray-400 text-sm">
          <CheckCircle2 className="w-8 h-8 mx-auto mb-2 text-green-400" />
          所有合同均已签署，暂无待签项
        </div>
      </Card>
    )
  }

  return (
    <>
      <Card>
        <div className="overflow-x-auto">
          <table className="w-full text-sm">
            <thead>
              <tr className="border-b text-xs text-gray-500">
                <th className="py-2 px-3 text-left w-8"></th>
                <th className="py-2 px-3 text-left">员工</th>
                <th className="py-2 px-3 text-left">部门</th>
                <th className="py-2 px-3 text-left">手机号</th>
                <th className="py-2 px-3 text-left">待签内容</th>
                <th className="py-2 px-3 text-center">数量</th>
                <th className="py-2 px-3 text-right">操作</th>
              </tr>
            </thead>
            <tbody>
              {pendingList.map((emp: any) => {
                const expanded = expandedEmp === emp.employeeId
                return (
                  <Fragment key={emp.employeeId}>
                    <tr className="border-b last:border-0 hover:bg-gray-50 cursor-pointer"
                      onClick={() => setExpandedEmp(expanded ? null : emp.employeeId)}
                    >
                      <td className="py-2 px-3">
                        {expanded ? <ChevronDown className="w-4 h-4 text-gray-400" /> : <ChevronRight className="w-4 h-4 text-gray-400" />}
                      </td>
                      <td className="py-2 px-3">
                        <div className="flex items-center gap-2">
                          <div className="w-7 h-7 rounded-full bg-primary/10 flex items-center justify-center flex-shrink-0">
                            <User className="w-3.5 h-3.5 text-primary" />
                          </div>
                          <span className="font-medium">{emp.name}</span>
                          {emp.idCardNumber && <span className="text-xs text-gray-400 font-mono ml-1">{emp.idCardNumber}</span>}
                        </div>
                      </td>
                      <td className="py-2 px-3 text-gray-500">{emp.department || '—'}</td>
                      <td className="py-2 px-3 text-gray-500">{emp.phone || '—'}</td>
                      <td className="py-2 px-3">
                        <div className="flex flex-wrap gap-1">
                          {emp.pendingItems.map((item: any, idx: number) => {
                            const sceneCfg = SCENE_CONFIG[item.scene]
                            const methodCfg = SIGN_METHOD_CONFIG[item.signMethod] || SIGN_METHOD_CONFIG.ELECTRONIC
                            return (
                              <span key={idx} className={`inline-flex items-center gap-1 px-1.5 py-0.5 rounded text-xs ${sceneCfg ? sceneCfg.color : 'bg-gray-100 text-gray-600'}`} title={item.title}>
                                {sceneCfg ? sceneCfg.label : item.title}
                                <span className={`px-1 rounded text-[10px] ${methodCfg.color}`}>{methodCfg.label}</span>
                                {item.type === 'contract' && <span className="text-[10px] text-gray-400">未登记</span>}
                              </span>
                            )
                          })}
                        </div>
                      </td>
                      <td className="py-2 px-3 text-center">
                        <span className="inline-flex items-center justify-center px-2 py-0.5 rounded-full text-xs bg-yellow-100 text-yellow-700 font-medium">
                          {emp.pendingItems.length}
                        </span>
                      </td>
                      <td className="py-2 px-3 text-right" onClick={(e) => e.stopPropagation()}>
                        <Button
                          size="sm"
                          variant="secondary"
                          onClick={() => {
                            setRemindEmpId(emp.employeeId)
                            onRemind(emp.employeeId)
                          }}
                          disabled={remindLoading && remindEmpId === emp.employeeId}
                        >
                          <Bell className="w-3.5 h-3.5 mr-1" />
                          {remindLoading && remindEmpId === emp.employeeId ? '生成中...' : '催办'}
                        </Button>
                      </td>
                    </tr>
                    {/* 展开行：待签文件列表 */}
                    {expanded && (
                      <tr className="bg-gray-50/50">
                        <td></td>
                        <td colSpan={5} className="py-2 px-3">
                          <div className="space-y-1.5">
                            {emp.pendingItems.map((item: any, idx: number) => (
                              <div key={idx} className="flex items-center gap-2 px-3 py-2 bg-white rounded-md border text-xs">
                                <FileText className="w-3.5 h-3.5 text-gray-400 shrink-0" />
                                <span className="font-medium">{item.title}</span>
                                {SCENE_CONFIG[item.scene] && (
                                  <span className={`px-1.5 py-0.5 rounded ${SCENE_CONFIG[item.scene].color}`}>{SCENE_CONFIG[item.scene].label}</span>
                                )}
                                <span className={`px-1.5 py-0.5 rounded ${(SIGN_METHOD_CONFIG[item.signMethod] || SIGN_METHOD_CONFIG.ELECTRONIC).color}`}>
                                  {(SIGN_METHOD_CONFIG[item.signMethod] || SIGN_METHOD_CONFIG.ELECTRONIC).label}
                                </span>
                                <span className="text-gray-400">{new Date(item.createdAt).toLocaleDateString('zh-CN')}</span>
                                {item.type === 'esign' && item.recordId && (
                                  <button className="text-primary hover:underline ml-auto" onClick={() => onDetail(item.recordId)}>
                                    查看详情
                                  </button>
                                )}
                                {item.type === 'contract' && (
                                  <div className="ml-auto flex items-center gap-2">
                                    {signDateEditing === item.contractId ? (
                                      <>
                                        <input
                                          type="date"
                                          max={new Date().toISOString().slice(0, 10)}
                                          value={signDateValue}
                                          onChange={(e) => setSignDateValue(e.target.value)}
                                          className="h-7 px-2 text-xs border rounded"
                                        />
                                        <button
                                          className="text-xs text-primary hover:underline"
                                          disabled={signDateSaving}
                                          onClick={() => handleSaveSignDate(item.contractId)}
                                        >
                                          {signDateSaving ? '保存中...' : '保存'}
                                        </button>
                                        <button
                                          className="text-xs text-gray-400 hover:text-gray-600"
                                          onClick={() => { setSignDateEditing(null); setSignDateValue('') }}
                                        >
                                          取消
                                        </button>
                                      </>
                                    ) : (
                                      <>
                                        <span className="text-gray-400">未登记签署日期</span>
                                        <button
                                          className="text-xs text-primary hover:underline"
                                          onClick={() => {
                                            setSignDateEditing(item.contractId)
                                            setSignDateValue(new Date().toISOString().slice(0, 10))
                                          }}
                                        >
                                          登记签署日期
                                        </button>
                                      </>
                                    )}
                                  </div>
                                )}
                              </div>
                            ))}
                          </div>
                        </td>
                      </tr>
                    )}
                  </Fragment>
                )
              })}
            </tbody>
          </table>
        </div>
      </Card>

      {/* 催办结果弹窗：二维码 + 链接 */}
      {remindData && remindEmpId && (
        <Modal open onClose={() => { setRemindEmpId(null); }} title="催办 — 发送给员工" size="sm">
          <div className="py-4">
            <div className="flex flex-col items-center">
              <div className="p-4 bg-white rounded-xl border-2 border-gray-100 shadow-sm">
                <QRCodeSVG value={remindData.url} size={200} level="M" />
              </div>
              <p className="mt-3 text-xs text-gray-600 text-center">
               员工 <span className="font-medium">{remindData.employeeName}</span>{remindData.employeeIdCardNumber && <span className="font-mono text-gray-500 ml-1">{remindData.employeeIdCardNumber}</span>} 扫码后自动登录员工端签署页面
              </p>
              <p className="mt-1 text-xs text-gray-400">链接 24 小时内有效</p>
              <div className="mt-3 w-full">
                <div className="flex items-center gap-2 px-3 py-2 bg-gray-50 rounded-lg">
                  <span className="text-xs text-gray-500 flex-1 truncate">{remindData.url}</span>
                  <button
                    onClick={() => handleCopy(remindData.url)}
                    className="flex items-center gap-1 text-xs text-primary hover:text-primary/80 flex-shrink-0"
                  >
                    {copied ? <Check className="w-3.5 h-3.5" /> : <Copy className="w-3.5 h-3.5" />}
                    {copied ? '已复制' : '复制'}
                  </button>
                </div>
              </div>
            </div>
          </div>
        </Modal>
      )}
    </>
  )
}
