import { useState, useRef } from 'react'
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import { toast } from 'sonner'
import { CalendarCheck, CheckCircle, Clock, AlertCircle, Plus, Trash2, Calendar, Users, BarChart3, Plane, Upload, Download, X, Send, Loader2, CheckCheck } from 'lucide-react'
import api from '../lib/api'
import { useAuthStore } from '../store/authStore'
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 { InlineAlert } from '../components/ui/InlineAlert'
import { useConfirm } from '../hooks/useConfirm'

const STATUS_CONFIG: Record<string, { label: string; color: string; bg: string; icon: typeof CheckCircle }> = {
  PENDING: { label: '待确认', color: 'text-amber-700', bg: 'bg-amber-100', icon: Clock },
  CONFIRMED: { label: '已确认', color: 'text-green-700', bg: 'bg-green-100', icon: CheckCircle },
  DISPUTED: { label: '有异议', color: 'text-red-700', bg: 'bg-red-100', icon: AlertCircle },
}

const ATTENDANCE_STATUS: Record<string, string> = {
  NORMAL: '正常',
  LATE: '迟到',
  EARLY_LEAVE: '早退',
  ABSENT: '缺勤',
  LEAVE: '请假',
  BUSINESS_TRIP: '出差',
  UNREGISTERED: '未打卡',
}

const LEAVE_TYPES: Record<string, string> = {
  SICK: '病假',
  PERSONAL: '事假',
  ANNUAL: '年假',
  MATERNITY: '产假',
  OTHER: '其他',
}

const TABS = [
  { key: 'confirm', label: '考勤确认', icon: CalendarCheck },
  { key: 'shifts', label: '班次管理', icon: Clock },
  { key: 'schedule', label: '排班', icon: Calendar },
  { key: 'daily', label: '每日出勤', icon: Users },
  { key: 'monthly', label: '月度报表', icon: BarChart3 },
  { key: 'leaves', label: '休假记录', icon: Plane },
]

export default function Attendance() {
  const [activeTab, setActiveTab] = useState('confirm')

  return (
    <div className="space-y-4">
      <div>
        <div className="flex items-center gap-2">
          <CalendarCheck className="h-5 w-5 text-primary" />
          <h1 className="text-base font-semibold">考勤管理</h1>
        </div>
        <p className="mt-1 text-sm text-gray-500">班次设定、排班、出勤查询、月度报表、休假记录</p>
      </div>

      {/* Tab 导航 */}
      <div className="flex flex-wrap gap-1 border-b border-gray-200">
        {TABS.map(tab => {
          const Icon = tab.icon
          return (
            <button
              key={tab.key}
              onClick={() => setActiveTab(tab.key)}
              className={`flex items-center gap-1.5 px-3 py-2 text-sm font-medium border-b-2 transition-colors ${
                activeTab === tab.key
                  ? 'border-primary text-primary'
                  : 'border-transparent text-gray-500 hover:text-gray-700'
              }`}
            >
              <Icon className="w-4 h-4" />
              {tab.label}
            </button>
          )
        })}
      </div>

      {activeTab === 'confirm' && <ConfirmTab />}
      {activeTab === 'shifts' && <ShiftsTab />}
      {activeTab === 'schedule' && <ScheduleTab />}
      {activeTab === 'daily' && <DailyTab />}
      {activeTab === 'monthly' && <MonthlyTab />}
      {activeTab === 'leaves' && <LeavesTab />}
    </div>
  )
}

// ========== 考勤确认 Tab ==========
function ConfirmTab() {
  const queryClient = useQueryClient()
  const confirm = useConfirm()
  const [month, setMonth] = useState(new Date().toISOString().slice(0, 7))
  const [filterDepartment, setFilterDepartment] = useState('')
  const [filterStatus, setFilterStatus] = useState('')
  const [showImport, setShowImport] = useState(false)
  const [importFile, setImportFile] = useState<File | null>(null)
  const [importResult, setImportResult] = useState<any>(null)
  const [importing, setImporting] = useState(false)
  const [selectedIds, setSelectedIds] = useState<Set<string>>(new Set())
  const fileInputRef = useRef<HTMLInputElement>(null)

  const { data: list, isLoading } = useQuery<any>({
    queryKey: ['attendance', month, filterDepartment, filterStatus],
    queryFn: async () => {
      const params: any = { month }
      if (filterDepartment) params.department = filterDepartment
      if (filterStatus) params.status = filterStatus
      const res = await api.get('/attendance', { params }) as any
      return res.data
    },
  })

  const { data: stats } = useQuery<any>({
    queryKey: ['attendance-stats', month],
    queryFn: async () => {
      const res = await api.get(`/attendance/stats?month=${month}`) as any
      return res.data
    },
  })

  const { data: departmentList } = useQuery<string[]>({
    queryKey: ['roster-departments'],
    queryFn: async () => {
      const res = await api.get('/roster/departments') as any
      return res.data || []
    },
  })

  const { data: publishRecords } = useQuery<any[]>({
    queryKey: ['attendance-publish-records'],
    queryFn: async () => {
      const res = await api.get('/attendance/publish-records') as any
      return res.data
    },
  })

  const publishMutation = useMutation({
    mutationFn: async () => {
      const res = await api.post('/attendance/publish', { month }) as any
      return res.data
    },
    onSuccess: () => {
      toast.success(`${month}月考勤表已发布`)
      queryClient.invalidateQueries({ queryKey: ['attendance-publish-records'] })
    },
    onError: (err: any) => toast.error(err?.response?.data?.error?.message || '发布失败'),
  })

  const cancelPublishMutation = useMutation({
    mutationFn: async (id: string) => {
      const res = await api.post(`/attendance/publish/${id}/cancel`) as any
      return res.data
    },
    onSuccess: () => {
      toast.success('已取消发布')
      queryClient.invalidateQueries({ queryKey: ['attendance-publish-records'] })
    },
    onError: (err: any) => toast.error(err?.response?.data?.error?.message || '取消失败'),
  })

  const batchConfirmMutation = useMutation({
    mutationFn: async (params: { all?: boolean; ids?: string[] }) => {
      const res = await api.post('/attendance/batch-confirm', { month, ...params }) as any
      return res.data
    },
    onSuccess: (data: any) => {
      toast.success(`已批量确认 ${data.count} 条考勤记录`)
      queryClient.invalidateQueries({ queryKey: ['attendance'] })
      queryClient.invalidateQueries({ queryKey: ['attendance-stats'] })
      setSelectedIds(new Set())
    },
    onError: (err: any) => toast.error(err?.response?.data?.error?.message || '批量确认失败'),
  })

  const singleConfirmMutation = useMutation({
    mutationFn: async (id: string) => {
      const res = await api.post('/attendance/confirm', { employeeId: list.find((i: any) => i.id === id)?.employeeId, month }) as any
      return res.data
    },
    onSuccess: () => {
      toast.success('已确认')
      queryClient.invalidateQueries({ queryKey: ['attendance'] })
      queryClient.invalidateQueries({ queryKey: ['attendance-stats'] })
    },
    onError: (err: any) => toast.error(err?.response?.data?.error?.message || '确认失败'),
  })

  const currentPublish = publishRecords?.find((r: any) => r.month === month && r.status === 'PUBLISHED')
  const pendingCount = stats?.pending || 0
  const pendingItems = (list || []).filter((i: any) => i.status === 'PENDING')
  const allPendingSelected = pendingItems.length > 0 && pendingItems.every((i: any) => selectedIds.has(i.id))

  const toggleSelect = (id: string) => {
    const next = new Set(selectedIds)
    if (next.has(id)) next.delete(id)
    else next.add(id)
    setSelectedIds(next)
  }

  const toggleSelectAllPending = () => {
    if (allPendingSelected) {
      const next = new Set(selectedIds)
      pendingItems.forEach((i: any) => next.delete(i.id))
      setSelectedIds(next)
    } else {
      const next = new Set(selectedIds)
      pendingItems.forEach((i: any) => next.add(i.id))
      setSelectedIds(next)
    }
  }

  // 流程步骤
  const FLOW_STEPS = [
    { label: '导入考勤', desc: 'Excel 批量导入', done: (list?.length || 0) > 0 },
    { label: 'HR 确认', desc: `待确认 ${pendingCount} 人`, done: pendingCount === 0 && (list?.length || 0) > 0 },
    { label: '发布考勤表', desc: currentPublish ? '已发布' : '未发布', done: !!currentPublish },
    { label: '员工确认', desc: stats ? `已确认 ${stats.confirmed}/${stats.total}` : '', done: stats?.confirmed === stats?.total && stats?.total > 0 },
  ]

  return (
    <div className="space-y-3">
      {/* 流程指示器 */}
      <div className="flex items-center gap-1 overflow-x-auto pb-1">
        {FLOW_STEPS.map((step, i) => (
          <div key={i} className="flex items-center gap-1 shrink-0">
            <div className={`flex items-center gap-1.5 px-2.5 py-1.5 rounded-lg text-xs ${step.done ? 'bg-green-50 text-green-700' : 'bg-gray-50 text-gray-500'}`}>
              {step.done ? <CheckCircle className="w-3.5 h-3.5" /> : <Clock className="w-3.5 h-3.5" />}
              <span className="font-medium">{step.label}</span>
              <span className="text-gray-400">{step.desc}</span>
            </div>
            {i < FLOW_STEPS.length - 1 && <span className="text-gray-300">→</span>}
          </div>
        ))}
      </div>

      {/* 指引提示 */}
      {!currentPublish && pendingCount > 0 && (
        <InlineAlert type="info" title="考勤确认流程">
          请核对考勤数据后批量确认，确认无误后点击「发布考勤表」推送给员工端确认。员工有异议时可提交异议说明。
        </InlineAlert>
      )}
      {currentPublish && (
        <InlineAlert type="success" title="考勤表已发布">
          {month}月考勤表已发布至员工端，员工可自行查看并确认。已确认 {stats?.confirmed || 0}/{stats?.total || 0} 人。
        </InlineAlert>
      )}
      {stats?.disputed > 0 && (
        <InlineAlert type="warning" title="有员工提出异议">
          {stats.disputed} 名员工对考勤数据有异议，请查看异议说明并处理。
        </InlineAlert>
      )}

      <div className="flex items-center gap-2 justify-between flex-wrap">
        <div className="flex items-center gap-2">
          {pendingCount > 0 && (
            <>
              <Button
                size="sm"
                variant="secondary"
                onClick={toggleSelectAllPending}
              >
                {allPendingSelected ? '取消全选' : '全选待确认'}
              </Button>
              {selectedIds.size > 0 && (
                <Button
                  size="sm"
                  onClick={async () => {
                    const ok = await confirm({ title: '批量确认考勤', message: `确认将选中的 ${selectedIds.size} 条考勤记录标记为已确认？` })
                    if (ok) batchConfirmMutation.mutate({ ids: Array.from(selectedIds) })
                  }}
                  disabled={batchConfirmMutation.isPending}
                >
                  <CheckCheck className="w-3.5 h-3.5 mr-1" />
                  确认选中 ({selectedIds.size})
                </Button>
              )}
              <Button
                size="sm"
                variant="secondary"
                onClick={async () => {
                  const ok = await confirm({ title: '全部确认', message: `确认将全部 ${pendingCount} 条待确认记录标记为已确认？` })
                  if (ok) batchConfirmMutation.mutate({ all: true })
                }}
                disabled={batchConfirmMutation.isPending}
              >
                全部确认 ({pendingCount})
              </Button>
            </>
          )}
        </div>
        <div className="flex items-center gap-2">
          {currentPublish ? (
            <Button size="sm" variant="secondary" onClick={async () => {
              const ok = await confirm({ title: '取消发布', message: '取消发布后员工端将无法查看该月考勤表，确定操作？' })
              if (ok) cancelPublishMutation.mutate(currentPublish.id)
            }}>
              <X className="w-3.5 h-3.5 mr-1" />取消发布
            </Button>
          ) : (
            <Button size="sm" onClick={() => publishMutation.mutate()} disabled={publishMutation.isPending || pendingCount > 0}>
              {publishMutation.isPending ? <Loader2 className="w-3.5 h-3.5 mr-1 animate-spin" /> : <Send className="w-3.5 h-3.5 mr-1" />}
              发布考勤表
            </Button>
          )}
          <Button size="sm" variant="secondary" onClick={() => setShowImport(true)}>
            <Upload className="w-3.5 h-3.5 mr-1" />导入考勤
          </Button>
          <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>
            <option value="PENDING">待确认</option>
            <option value="CONFIRMED">已确认</option>
            <option value="DISPUTED">有异议</option>
          </select>
          <select
            value={filterDepartment}
            onChange={e => setFilterDepartment(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>
            {departmentList?.map((d: string) => <option key={d} value={d}>{d}</option>)}
          </select>
          <input
            type="month"
            value={month}
            onChange={e => setMonth(e.target.value)}
            className="px-3 py-1.5 text-sm border rounded-lg focus:outline-none focus:ring-2 focus:ring-primary"
          />
        </div>
      </div>

      {stats && (
        <div className="grid grid-cols-2 sm:grid-cols-4 gap-2">
          {[
            { label: '总计', value: stats.total, color: 'text-gray-700' },
            { label: '待确认', value: stats.pending, color: 'text-amber-600' },
            { label: '已确认', value: stats.confirmed, color: 'text-green-600' },
            { label: '有异议', value: stats.disputed, color: 'text-red-600' },
          ].map(s => (
            <Card key={s.label} className="text-center">
              <div className={`text-lg font-bold ${s.color}`}>{s.value}</div>
              <div className="text-xs text-gray-500">{s.label}</div>
            </Card>
          ))}
        </div>
      )}

      {isLoading ? (
        <div className="text-center py-8 text-gray-500">加载中...</div>
      ) : !list || list.length === 0 ? (
        <EmptyState title="本月暂无考勤确认记录" description="请先批量导入考勤数据" />
      ) : (
        <div className="space-y-2">
          {list.map((item: any) => {
            const config = STATUS_CONFIG[item.status] || STATUS_CONFIG.PENDING
            const StatusIcon = config.icon
            const isSelected = selectedIds.has(item.id)
            return (
              <Card key={item.id}>
                <div className="flex items-center justify-between">
                  <div className="flex items-center gap-3 flex-1 min-w-0">
                    {item.status === 'PENDING' && (
                      <input
                        type="checkbox"
                        checked={isSelected}
                        onChange={() => toggleSelect(item.id)}
                        className="w-4 h-4 rounded border-gray-300 text-primary focus:ring-primary shrink-0"
                      />
                    )}
                    <div className="flex items-center justify-center w-8 h-8 rounded-lg bg-gray-50 flex-shrink-0">
                      <CalendarCheck className="w-4 h-4 text-gray-600" />
                    </div>
                    <div className="flex-1 min-w-0">
                      <div className="flex items-center gap-2">
                        <span className="text-sm font-medium">{item.employee?.name}</span>
                        <span className="text-xs text-gray-500">{item.employee?.department}</span>
                      </div>
                      <div className="flex items-center gap-3 text-xs text-gray-500 mt-0.5">
                        <span>出勤 {item.workDays} 天</span>
                        <span>工作日加班 {item.weekdayHours}h</span>
                        <span>周末加班 {item.weekendHours}h</span>
                        <span>法定加班 {item.holidayHours}h</span>
                        <span className="text-gray-700">加班费 ¥{item.overtimePay?.toFixed(2)}</span>
                      </div>
                      {item.disputeNote && (
                        <div className="text-xs text-red-600 mt-1">异议说明：{item.disputeNote}</div>
                      )}
                    </div>
                  </div>
                  <div className="flex items-center gap-2 flex-shrink-0">
                    {item.status === 'PENDING' && (
                      <button
                        className="text-xs text-primary hover:underline"
                        onClick={() => singleConfirmMutation.mutate(item.id)}
                        disabled={singleConfirmMutation.isPending}
                      >
                        确认
                      </button>
                    )}
                    <div className={`flex items-center gap-1 px-2 py-1 rounded-lg ${config.bg} ${config.color}`}>
                      <StatusIcon className="w-3.5 h-3.5" />
                      <span className="text-xs font-medium">{config.label}</span>
                    </div>
                  </div>
                </div>
              </Card>
            )
          })}
        </div>
      )}

      {/* 导入考勤弹窗 */}
      {showImport && (
        <div className="fixed inset-0 bg-black/30 flex items-center justify-center z-50 p-4" onClick={() => setShowImport(false)}>
          <Card className="max-w-lg w-full" >
            <div onClick={(e) => e.stopPropagation()} className="p-4">
              <div className="flex items-center justify-between mb-3">
                <h2 className="text-sm font-medium">导入考勤数据 — {month}</h2>
                <button onClick={() => { setShowImport(false); setImportFile(null); setImportResult(null) }} className="text-gray-400 hover:text-gray-600"><X className="w-4 h-4" /></button>
              </div>

              <div className="space-y-3">
                <div className="flex gap-2">
                  <Button size="sm" variant="secondary" onClick={async () => {
                    try {
                      const token = useAuthStore.getState().accessToken
                      const baseURL = import.meta.env.DEV ? 'http://localhost:3000/api/v1' : '/api/v1'
                      const res = await fetch(`${baseURL}/import/template`, {
                        headers: token ? { Authorization: `Bearer ${token}` } : {},
                      })
                      const blob = await res.blob()
                      const url = URL.createObjectURL(blob)
                      const a = document.createElement('a')
                      a.href = url
                      a.download = '员工导入模板.xlsx'
                      a.click()
                      URL.revokeObjectURL(url)
                    } catch { toast.error('下载模板失败') }
                  }}>
                    <Download className="w-3.5 h-3.5 mr-1" />下载模板
                  </Button>
                </div>

                <div className="text-xs text-gray-500 bg-blue-50/50 rounded-md p-2">
                  模板中「考勤记录」Sheet 包含：姓名、身份证号、日期、考勤状态、上下班时间。身份证号优先匹配，未填时用姓名匹配。
                </div>

                <div className="border-2 border-dashed border-gray-200 rounded-lg p-6 text-center">
                  <input ref={fileInputRef} type="file" accept=".xlsx,.xls" className="hidden" id="attendance-import-file" onChange={(e) => { setImportFile(e.target.files?.[0] || null); setImportResult(null) }} />
                  <label htmlFor="attendance-import-file" className="cursor-pointer text-xs text-primary hover:underline">
                    {importFile ? importFile.name : '点击选择 Excel 文件'}
                  </label>
                </div>

                {importResult && (
                  <div className="px-3 py-2 rounded-md bg-green-50 text-green-700 text-xs space-y-1">
                    <div className="font-medium">导入完成</div>
                    {importResult.attendance > 0 && <div>考勤记录：{importResult.attendance} 条</div>}
                    {importResult.overtime > 0 && <div>加班记录：{importResult.overtime} 条</div>}
                    {importResult.employees > 0 && <div>员工：{importResult.employees} 人</div>}
                    {importResult.contracts > 0 && <div>合同：{importResult.contracts} 份</div>}
                    {importResult.skipped > 0 && <div className="text-amber-600">跳过 {importResult.skipped} 条</div>}
                    {importResult.errors?.length > 0 && (
                      <div className="mt-1 pt-1 border-t border-green-200">
                        {importResult.errors.slice(0, 5).map((e: string, i: number) => <div key={i} className="text-amber-600">{e}</div>)}
                        {importResult.errors.length > 5 && <div className="text-amber-600">...还有 {importResult.errors.length - 5} 条</div>}
                      </div>
                    )}
                  </div>
                )}

                <div className="flex justify-end gap-2">
                  <Button variant="secondary" size="sm" onClick={() => { setShowImport(false); setImportFile(null); setImportResult(null) }}>取消</Button>
                  <Button size="sm" onClick={async () => {
                    if (!importFile) return toast.error('请选择文件')
                    setImporting(true)
                    setImportResult(null)
                    try {
                      const token = useAuthStore.getState().accessToken
                      const formData = new FormData()
                      formData.append('file', importFile)
                      const res = await fetch('/api/v1/import/excel', {
                        method: 'POST',
                        headers: token ? { Authorization: `Bearer ${token}` } : {},
                        body: formData,
                      })
                      const data = await res.json()
                      if (!data.success) { toast.error(data.error?.message || '导入失败') }
                      else {
                        setImportResult(data.data)
                        queryClient.invalidateQueries({ queryKey: ['attendance'] })
                        queryClient.invalidateQueries({ queryKey: ['attendance-stats'] })
                        toast.success('考勤数据导入完成')
                      }
                    } catch (e: any) { toast.error(e?.message || '导入失败') }
                    finally { setImporting(false) }
                  }} disabled={!importFile || importing}>{importing ? '导入中...' : '开始导入'}</Button>
                </div>
              </div>
            </div>
          </Card>
        </div>
      )}
    </div>
  )
}

// ========== 班次管理 Tab ==========
function ShiftsTab() {
  const queryClient = useQueryClient()
  const [showAdd, setShowAdd] = useState(false)
  const [editShift, setEditShift] = useState<any>(null)
  const [form, setForm] = useState({ name: '', startTime: '09:00', endTime: '18:00', flexibleMinutes: 0, restMinutes: 60, color: '#3b82f6' })

  const { data: shifts, isLoading } = useQuery<any>({
    queryKey: ['shifts'],
    queryFn: async () => {
      const res = await api.get('/attendance/shifts') as any
      return res.data
    },
  })

  const saveMutation = useMutation({
    mutationFn: async (data: any) => {
      if (editShift) {
        return api.put(`/attendance/shifts/${editShift.id}`, data)
      }
      return api.post('/attendance/shifts', data)
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['shifts'] })
      setShowAdd(false)
      setEditShift(null)
      setForm({ name: '', startTime: '09:00', endTime: '18:00', flexibleMinutes: 0, restMinutes: 60, color: '#3b82f6' })
    },
  })

  const deleteMutation = useMutation({
    mutationFn: (id: string) => api.delete(`/attendance/shifts/${id}`),
    onSuccess: () => queryClient.invalidateQueries({ queryKey: ['shifts'] }),
  })

  const handleSubmit = () => {
    if (!form.name.trim()) return toast.error('请输入班次名称')
    saveMutation.mutate(form)
  }

  return (
    <div className="space-y-3">
      <div className="flex justify-end">
        <Button onClick={() => { setEditShift(null); setForm({ name: '', startTime: '09:00', endTime: '18:00', flexibleMinutes: 0, restMinutes: 60, color: '#3b82f6' }); setShowAdd(true) }}>
          <Plus className="w-4 h-4 mr-1" />新增班次
        </Button>
      </div>

      {isLoading ? (
        <div className="text-center py-8 text-gray-500">加载中...</div>
      ) : !shifts || shifts.length === 0 ? (
        <EmptyState title="暂无班次" description="请先创建班次" />
      ) : (
        <div className="grid sm:grid-cols-2 lg:grid-cols-3 gap-3">
          {shifts.map((s: any) => (
            <Card key={s.id}>
              <div className="flex items-center justify-between">
                <div className="flex items-center gap-2">
                  <div className="w-3 h-3 rounded-full" style={{ background: s.color }} />
                  <span className="font-medium text-sm">{s.name}</span>
                </div>
                <div className="flex gap-1">
                  <button className="text-xs text-gray-400 hover:text-primary px-1" onClick={() => { setEditShift(s); setForm(s); setShowAdd(true) }}>编辑</button>
                  <button className="text-xs text-gray-400 hover:text-red-500 px-1" onClick={() => { if (confirm('确认删除？')) deleteMutation.mutate(s.id) }}>删除</button>
                </div>
              </div>
              <div className="mt-2 text-xs text-gray-500 space-y-0.5">
                <div>上班时间：{s.startTime} — 下班时间：{s.endTime}</div>
                <div>弹性时长：{s.flexibleMinutes} 分钟 — 休息时长：{s.restMinutes} 分钟</div>
              </div>
            </Card>
          ))}
        </div>
      )}

      <Modal open={showAdd} onClose={() => setShowAdd(false)} title={editShift ? '编辑班次' : '新增班次'}>
        <div className="space-y-3">
          <div>
            <Label>班次名称</Label>
            <Input value={form.name} onChange={e => setForm({ ...form, name: e.target.value })} placeholder="如：早班、白班、夜班" />
          </div>
          <div className="grid grid-cols-2 gap-3">
            <div>
              <Label>上班时间</Label>
              <Input type="time" value={form.startTime} onChange={e => setForm({ ...form, startTime: e.target.value })} />
            </div>
            <div>
              <Label>下班时间</Label>
              <Input type="time" value={form.endTime} onChange={e => setForm({ ...form, endTime: e.target.value })} />
            </div>
          </div>
          <div className="grid grid-cols-2 gap-3">
            <div>
              <Label>弹性时长（分钟）</Label>
              <Input type="number" value={form.flexibleMinutes} onChange={e => setForm({ ...form, flexibleMinutes: Number(e.target.value) })} />
            </div>
            <div>
              <Label>休息时长（分钟）</Label>
              <Input type="number" value={form.restMinutes} onChange={e => setForm({ ...form, restMinutes: Number(e.target.value) })} />
            </div>
          </div>
          <div>
            <Label>显示颜色</Label>
            <input type="color" value={form.color} onChange={e => setForm({ ...form, color: e.target.value })} className="h-9 w-16 rounded border border-gray-200" />
          </div>
          <div className="flex justify-end gap-2 pt-2">
            <Button variant="secondary" onClick={() => setShowAdd(false)}>取消</Button>
            <Button onClick={handleSubmit} disabled={saveMutation.isPending}>{saveMutation.isPending ? '保存中...' : '保存'}</Button>
          </div>
        </div>
      </Modal>
    </div>
  )
}

// ========== 排班 Tab ==========
function ScheduleTab() {
  const queryClient = useQueryClient()
  const [date, setDate] = useState(new Date().toISOString().slice(0, 10))
  const [showAssign, setShowAssign] = useState(false)
  const [selectedShiftId, setSelectedShiftId] = useState('')
  const [selectedEmployeeIds, setSelectedEmployeeIds] = useState<Set<string>>(new Set())
  const [searchQuery, setSearchQuery] = useState('')

  const { data: shifts } = useQuery<any>({
    queryKey: ['shifts'],
    queryFn: async () => {
      const res = await api.get('/attendance/shifts') as any
      return res.data
    },
  })

  const { data: assignments, isLoading } = useQuery<any>({
    queryKey: ['shift-assignments', date],
    queryFn: async () => {
      const res = await api.get(`/attendance/shift-assignments?date=${date}`) as any
      return res.data
    },
  })

  const { data: dailyData } = useQuery<any>({
    queryKey: ['daily-attendance', date],
    queryFn: async () => {
      const res = await api.get(`/attendance/daily?date=${date}`) as any
      return res.data
    },
  })

  const batchAssignMutation = useMutation({
    mutationFn: (items: any[]) => api.post('/attendance/shift-assignments/batch', { items }),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['shift-assignments'] })
      queryClient.invalidateQueries({ queryKey: ['daily-attendance'] })
      setShowAssign(false)
      setSelectedEmployeeIds(new Set())
      setSelectedShiftId('')
      toast.success('排班成功')
    },
  })

  const deleteAssignmentMutation = useMutation({
    mutationFn: (id: string) => api.delete(`/attendance/shift-assignments/${id}`),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['shift-assignments'] })
      queryClient.invalidateQueries({ queryKey: ['daily-attendance'] })
    },
  })

  const handleBatchAssign = () => {
    if (!selectedShiftId) return toast.error('请选择班次')
    if (selectedEmployeeIds.size === 0) return toast.error('请选择员工')
    const items = Array.from(selectedEmployeeIds).map(empId => ({ employeeId: empId, shiftId: selectedShiftId, date }))
    batchAssignMutation.mutate(items)
  }

  const employees = dailyData || []
  const assignmentMap: Map<string, any> = new Map((assignments || []).map((a: any) => [a.employeeId, a]))

  const toggleEmployee = (id: string) => {
    const next = new Set(selectedEmployeeIds)
    if (next.has(id)) next.delete(id)
    else next.add(id)
    setSelectedEmployeeIds(next)
  }

  return (
    <div className="space-y-3">
      <div className="flex items-center justify-between">
        <input
          type="date"
          value={date}
          onChange={e => setDate(e.target.value)}
          className="px-3 py-1.5 text-sm border rounded-lg focus:outline-none focus:ring-2 focus:ring-primary"
        />
        <Button onClick={() => setShowAssign(true)}>
          <Plus className="w-4 h-4 mr-1" />批量排班
        </Button>
      </div>

      {isLoading ? (
        <div className="text-center py-8 text-gray-500">加载中...</div>
      ) : employees.length === 0 ? (
        <EmptyState title="暂无员工" description="没有可排班的员工" />
      ) : (
        <Card className="overflow-hidden p-0">
          <table className="w-full text-sm">
            <thead className="bg-gray-50/90">
              <tr className="border-b border-gray-200 text-xs font-medium text-gray-500">
                <th className="px-4 py-3 text-left">姓名</th>
                <th className="px-4 py-3 text-left">部门</th>
                <th className="px-4 py-3 text-left">班次</th>
                <th className="px-4 py-3 text-center">操作</th>
              </tr>
            </thead>
            <tbody>
              {employees.map((emp: any) => {
                const assignment = assignmentMap.get(emp.employeeId)
                return (
                  <tr key={emp.employeeId} className="border-b border-gray-100 last:border-0">
                    <td className="px-4 py-3 font-medium">{emp.name}</td>
                    <td className="px-4 py-3 text-gray-500">{emp.department}</td>
                    <td className="px-4 py-3">
                      {assignment ? (
                        <span className="inline-flex items-center gap-1.5 px-2 py-0.5 rounded text-xs" style={{ background: (assignment.shift as any)?.color + '20', color: (assignment.shift as any)?.color }}>
                          <div className="w-2 h-2 rounded-full" style={{ background: (assignment.shift as any)?.color }} />
                          {(assignment.shift as any)?.name} {(assignment.shift as any)?.startTime}-{(assignment.shift as any)?.endTime}
                        </span>
                      ) : (
                        <span className="text-xs text-gray-400">未排班</span>
                      )}
                    </td>
                    <td className="px-4 py-3 text-center">
                      {assignment && (
                        <button className="text-xs text-gray-400 hover:text-red-500" onClick={() => deleteAssignmentMutation.mutate(assignment.id)}>移除</button>
                      )}
                    </td>
                  </tr>
                )
              })}
            </tbody>
          </table>
        </Card>
      )}

      <Modal open={showAssign} onClose={() => setShowAssign(false)} title="批量排班">
        <div className="space-y-3">
          <div>
            <Label>选择班次</Label>
            <Select value={selectedShiftId} onChange={e => setSelectedShiftId(e.target.value)}>
              <option value="">请选择班次</option>
              {(shifts || []).map((s: any) => (
                <option key={s.id} value={s.id}>{s.name} ({s.startTime}-{s.endTime})</option>
              ))}
            </Select>
          </div>
          <div>
            <Label>选择员工（{selectedEmployeeIds.size} 人已选）</Label>
            <input
              type="text"
              placeholder="搜索员工姓名或部门..."
              value={searchQuery}
              onChange={e => setSearchQuery(e.target.value)}
              className="w-full px-3 py-2 mb-2 text-sm border rounded-lg focus:outline-none focus:ring-2 focus:ring-primary"
            />
            <div className="max-h-60 overflow-y-auto border rounded-lg divide-y">
              {employees.filter((emp: any) => {
                if (!searchQuery.trim()) return true
                const q = searchQuery.trim().toLowerCase()
                return emp.name?.toLowerCase().includes(q) || emp.department?.toLowerCase().includes(q)
              }).map((emp: any) => (
                <label key={emp.employeeId} className="flex items-center gap-2 px-3 py-2 hover:bg-gray-50 cursor-pointer">
                  <input type="checkbox" checked={selectedEmployeeIds.has(emp.employeeId)} onChange={() => toggleEmployee(emp.employeeId)} />
                  <span className="text-sm">{emp.name}</span>
                  <span className="text-xs text-gray-400">{emp.department}</span>
                </label>
              ))}
            </div>
          </div>
          <div className="flex justify-end gap-2 pt-2">
            <Button variant="secondary" onClick={() => setShowAssign(false)}>取消</Button>
            <Button onClick={handleBatchAssign} disabled={batchAssignMutation.isPending}>{batchAssignMutation.isPending ? '排班中...' : '确认排班'}</Button>
          </div>
        </div>
      </Modal>
    </div>
  )
}

// ========== 每日出勤 Tab ==========
function DailyTab() {
  const [date, setDate] = useState(new Date().toISOString().slice(0, 10))

  const { data, isLoading } = useQuery<any>({
    queryKey: ['daily-attendance', date],
    queryFn: async () => {
      const res = await api.get(`/attendance/daily?date=${date}`) as any
      return res.data
    },
  })

  const statusColors: Record<string, string> = {
    NORMAL: 'bg-green-50 text-green-700',
    LATE: 'bg-amber-50 text-amber-700',
    EARLY_LEAVE: 'bg-orange-50 text-orange-700',
    ABSENT: 'bg-red-50 text-red-700',
    LEAVE: 'bg-blue-50 text-blue-700',
    BUSINESS_TRIP: 'bg-purple-50 text-purple-700',
    UNREGISTERED: 'bg-gray-100 text-gray-500',
  }

  return (
    <div className="space-y-3">
      <div className="flex justify-end">
        <input
          type="date"
          value={date}
          onChange={e => setDate(e.target.value)}
          className="px-3 py-1.5 text-sm border rounded-lg focus:outline-none focus:ring-2 focus:ring-primary"
        />
      </div>

      {isLoading ? (
        <div className="text-center py-8 text-gray-500">加载中...</div>
      ) : !data || data.length === 0 ? (
        <EmptyState title="暂无员工" description="没有出勤数据" />
      ) : (
        <Card className="overflow-hidden p-0">
          <table className="w-full text-sm">
            <thead className="bg-gray-50/90">
              <tr className="border-b border-gray-200 text-xs font-medium text-gray-500">
                <th className="px-4 py-3 text-left">姓名</th>
                <th className="px-4 py-3 text-left">部门</th>
                <th className="px-4 py-3 text-left">班次</th>
                <th className="px-4 py-3 text-left">签到</th>
                <th className="px-4 py-3 text-left">签退</th>
                <th className="px-4 py-3 text-left">状态</th>
                <th className="px-4 py-3 text-right">工时</th>
              </tr>
            </thead>
            <tbody>
              {data.map((emp: any) => (
                <tr key={emp.employeeId} className="border-b border-gray-100 last:border-0">
                  <td className="px-4 py-3 font-medium">{emp.name}</td>
                  <td className="px-4 py-3 text-gray-500">{emp.department}</td>
                  <td className="px-4 py-3 text-xs text-gray-500">{emp.shift ? `${emp.shift.name}` : '—'}</td>
                  <td className="px-4 py-3 text-xs font-mono">{emp.checkInTime || '—'}</td>
                  <td className="px-4 py-3 text-xs font-mono">{emp.checkOutTime || '—'}</td>
                  <td className="px-4 py-3">
                    <span className={`px-2 py-0.5 rounded text-xs ${statusColors[emp.status] || 'bg-gray-100 text-gray-500'}`}>
                      {ATTENDANCE_STATUS[emp.status] || emp.status}
                    </span>
                  </td>
                  <td className="px-4 py-3 text-right text-xs">{emp.workHours > 0 ? `${emp.workHours}h` : '—'}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </Card>
      )}
    </div>
  )
}

// ========== 月度报表 Tab ==========
function MonthlyTab() {
  const [month, setMonth] = useState(new Date().toISOString().slice(0, 7))

  const { data, isLoading } = useQuery<any>({
    queryKey: ['monthly-report', month],
    queryFn: async () => {
      const res = await api.get(`/attendance/monthly-report?month=${month}`) as any
      return res.data
    },
  })

  const handleExport = () => {
    if (!data || data.length === 0) return
    const headers = ['姓名', '部门', '出勤天数', '迟到次数', '早退次数', '缺勤天数', '请假天数', '加班工时', '加班费', '确认状态']
    const rows = data.map((r: any) => [
      r.name, r.department, r.workDays, r.lateCount, r.earlyLeaveCount, r.absentDays, r.leaveDays,
      r.overtimeHours, r.overtimePay, r.confirmationStatus === 'CONFIRMED' ? '已确认' : r.confirmationStatus === 'PENDING' ? '待确认' : r.confirmationStatus === 'DISPUTED' ? '有异议' : '未创建',
    ])
    const csv = [headers, ...rows].map(r => r.join(',')).join('\n')
    const blob = new Blob(['\ufeff' + csv], { type: 'text/csv;charset=utf-8' })
    const url = URL.createObjectURL(blob)
    const a = document.createElement('a')
    a.href = url
    a.download = `attendance-report-${month}.csv`
    a.click()
    URL.revokeObjectURL(url)
  }

  return (
    <div className="space-y-3">
      <div className="flex items-center justify-between">
        <input
          type="month"
          value={month}
          onChange={e => setMonth(e.target.value)}
          className="px-3 py-1.5 text-sm border rounded-lg focus:outline-none focus:ring-2 focus:ring-primary"
        />
        <Button variant="secondary" onClick={handleExport} disabled={!data || data.length === 0}>
          <BarChart3 className="w-4 h-4 mr-1" />导出 CSV
        </Button>
      </div>

      {isLoading ? (
        <div className="text-center py-8 text-gray-500">加载中...</div>
      ) : !data || data.length === 0 ? (
        <EmptyState title="暂无报表数据" description="该月份没有出勤数据" />
      ) : (
        <Card className="overflow-hidden p-0">
          <table className="w-full text-sm">
            <thead className="bg-gray-50/90">
              <tr className="border-b border-gray-200 text-xs font-medium text-gray-500">
                <th className="px-4 py-3 text-left">姓名</th>
                <th className="px-4 py-3 text-left">部门</th>
                <th className="px-4 py-3 text-center">出勤</th>
                <th className="px-4 py-3 text-center">迟到</th>
                <th className="px-4 py-3 text-center">早退</th>
                <th className="px-4 py-3 text-center">缺勤</th>
                <th className="px-4 py-3 text-center">请假</th>
                <th className="px-4 py-3 text-center">加班(h)</th>
                <th className="px-4 py-3 text-right">加班费</th>
                <th className="px-4 py-3 text-center">确认</th>
              </tr>
            </thead>
            <tbody>
              {data.map((r: any) => (
                <tr key={r.employeeId} className="border-b border-gray-100 last:border-0">
                  <td className="px-4 py-3 font-medium">{r.name}</td>
                  <td className="px-4 py-3 text-gray-500">{r.department}</td>
                  <td className="px-4 py-3 text-center">{r.workDays}</td>
                  <td className="px-4 py-3 text-center">{r.lateCount > 0 ? <span className="text-amber-600">{r.lateCount}</span> : '0'}</td>
                  <td className="px-4 py-3 text-center">{r.earlyLeaveCount > 0 ? <span className="text-orange-600">{r.earlyLeaveCount}</span> : '0'}</td>
                  <td className="px-4 py-3 text-center">{r.absentDays > 0 ? <span className="text-red-600">{r.absentDays}</span> : '0'}</td>
                  <td className="px-4 py-3 text-center">{r.leaveDays > 0 ? <span className="text-blue-600">{r.leaveDays}</span> : '0'}</td>
                  <td className="px-4 py-3 text-center">{r.overtimeHours > 0 ? r.overtimeHours.toFixed(1) : '—'}</td>
                  <td className="px-4 py-3 text-right">{r.overtimePay > 0 ? `¥${r.overtimePay.toFixed(2)}` : '—'}</td>
                  <td className="px-4 py-3 text-center">
                    {r.confirmationStatus === 'CONFIRMED' ? <span className="text-xs text-green-600">已确认</span>
                      : r.confirmationStatus === 'PENDING' ? <span className="text-xs text-amber-600">待确认</span>
                      : r.confirmationStatus === 'DISPUTED' ? <span className="text-xs text-red-600">有异议</span>
                      : <span className="text-xs text-gray-400">—</span>}
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </Card>
      )}
    </div>
  )
}

// ========== 休假记录 Tab ==========
function LeavesTab() {
  const queryClient = useQueryClient()
  const [showAdd, setShowAdd] = useState(false)
  const [form, setForm] = useState({ employeeId: '', leaveType: 'PERSONAL', startDate: '', endDate: '', days: 1, reason: '', remark: '' })

  const { data: leaves, isLoading } = useQuery<any>({
    queryKey: ['leave-records'],
    queryFn: async () => {
      const res = await api.get('/attendance/leaves') as any
      return res.data
    },
  })

  const { data: rosterData } = useQuery<any>({
    queryKey: ['roster-employees'],
    queryFn: async () => {
      const res = await api.get('/roster?pageSize=200') as any
      return res.data
    },
  })

  const createMutation = useMutation({
    mutationFn: (data: any) => api.post('/attendance/leaves', data),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['leave-records'] })
      setShowAdd(false)
      setForm({ employeeId: '', leaveType: 'PERSONAL', startDate: '', endDate: '', days: 1, reason: '', remark: '' })
      toast.success('休假记录已添加')
    },
  })

  const deleteMutation = useMutation({
    mutationFn: (id: string) => api.delete(`/attendance/leaves/${id}`),
    onSuccess: () => queryClient.invalidateQueries({ queryKey: ['leave-records'] }),
  })

  const handleSubmit = () => {
    if (!form.employeeId) return toast.error('请选择员工')
    if (!form.startDate || !form.endDate) return toast.error('请选择日期')
    createMutation.mutate(form)
  }

  const employees = rosterData || []

  return (
    <div className="space-y-3">
      <div className="flex justify-end">
        <Button onClick={() => setShowAdd(true)}>
          <Plus className="w-4 h-4 mr-1" />新增休假记录
        </Button>
      </div>

      {isLoading ? (
        <div className="text-center py-8 text-gray-500">加载中...</div>
      ) : !leaves || leaves.length === 0 ? (
        <EmptyState title="暂无休假记录" description="点击右上角添加休假记录" />
      ) : (
        <div className="space-y-2">
          {leaves.map((lv: any) => (
            <Card key={lv.id}>
              <div className="flex items-center justify-between">
                <div className="flex items-center gap-3 flex-1 min-w-0">
                  <div className="flex items-center justify-center w-8 h-8 rounded-lg bg-blue-50 flex-shrink-0">
                    <Plane className="w-4 h-4 text-blue-600" />
                  </div>
                  <div className="flex-1 min-w-0">
                    <div className="flex items-center gap-2">
                      <span className="text-sm font-medium">{lv.employee?.name}</span>
                      <span className="text-xs text-gray-500">{lv.employee?.department}</span>
                      <span className="px-1.5 py-0.5 rounded text-xs bg-blue-50 text-blue-700">{LEAVE_TYPES[lv.leaveType] || lv.leaveType}</span>
                    </div>
                    <div className="text-xs text-gray-500 mt-0.5">
                      {lv.startDate?.toString().slice(0, 10)} ~ {lv.endDate?.toString().slice(0, 10)}（{lv.days}天）
                      {lv.reason && <span className="ml-2">原因：{lv.reason}</span>}
                    </div>
                  </div>
                </div>
                <button className="text-xs text-gray-400 hover:text-red-500 flex-shrink-0" onClick={() => { if (confirm('确认删除？')) deleteMutation.mutate(lv.id) }}>
                  <Trash2 className="w-3.5 h-3.5" />
                </button>
              </div>
            </Card>
          ))}
        </div>
      )}

      <Modal open={showAdd} onClose={() => setShowAdd(false)} title="新增休假记录">
        <div className="space-y-3">
          <div>
            <Label>选择员工</Label>
            <Select value={form.employeeId} onChange={e => setForm({ ...form, employeeId: e.target.value })}>
              <option value="">请选择员工</option>
              {employees.map((emp: any) => (
                <option key={emp.id} value={emp.id}>{emp.name} - {emp.department}</option>
              ))}
            </Select>
          </div>
          <div>
            <Label>休假类型</Label>
            <Select value={form.leaveType} onChange={e => setForm({ ...form, leaveType: e.target.value })}>
              {Object.entries(LEAVE_TYPES).map(([k, v]) => (
                <option key={k} value={k}>{v}</option>
              ))}
            </Select>
          </div>
          <div className="grid grid-cols-2 gap-3">
            <div>
              <Label>开始日期</Label>
              <Input type="date" value={form.startDate} onChange={e => setForm({ ...form, startDate: e.target.value })} />
            </div>
            <div>
              <Label>结束日期</Label>
              <Input type="date" value={form.endDate} onChange={e => setForm({ ...form, endDate: e.target.value })} />
            </div>
          </div>
          <div>
            <Label>请假天数</Label>
            <Input type="number" step="0.5" value={form.days} onChange={e => setForm({ ...form, days: Number(e.target.value) })} />
          </div>
          <div>
            <Label>原因（选填）</Label>
            <Input value={form.reason} onChange={e => setForm({ ...form, reason: e.target.value })} placeholder="请简述请假原因" />
          </div>
          <div className="flex justify-end gap-2 pt-2">
            <Button variant="secondary" onClick={() => setShowAdd(false)}>取消</Button>
            <Button onClick={handleSubmit} disabled={createMutation.isPending}>{createMutation.isPending ? '保存中...' : '保存'}</Button>
          </div>
        </div>
      </Modal>
    </div>
  )
}
