// List + Detail Hồ sơ Nhân sự (HRM) — 2-panel master-detail (NamGroup eoffice ref):
//   CỘT TRÁI dọc (hẹp): [Cây tổ chức] (trên) + [Danh sách + filter] (dưới), cuộn độc lập.
//   CỘT PHẢI (rộng):    [Chi tiết 5 tab] — avatar header + Tổng quan / Thân nhân /
//                       Trình độ / Kinh nghiệm / Hợp đồng.
// Refine S66 (2026-06-16) theo anh góp ý từ eoffice LIVE (3 việc):
//   1. layout 3-cột-ngang → 2-cột (tree+list xếp chồng cột trái · detail rộng phải).
//   2+3. tô màu panel chi tiết: section header có accent (icon-chip nền màu nhạt +
//        heading đậm) + nhãn field brand-tint, dùng palette teal/violet/amberx/greenx.
//   GIỮ brand #1F7DC1 + Be Vietnam Pro · avatar header gradient brand giữ.
// KHÔNG đổi logic — 100% chức năng giữ: 5 satellite inline CRUD (add/edit/delete +
// mutex), search, filter, cây gốc "SOLUTION COMPANY" + TreeNode đệ quy, mọi TanStack
// query/mutation key NGUYÊN (employees-list / employee-detail / departments-tree-hrm).
// URL params: id (selected), q (search), status, deptId.
import { useMemo, useState } from 'react'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { useNavigate, useSearchParams } from 'react-router-dom'
import { toast } from 'sonner'
import {
  UserCircle2, Search, Plus, X, Pencil, Trash2, ChevronRight, Building2,
  Users, IdCard, GraduationCap, Briefcase, FileText, Phone, Mail, MapPin,
  CalendarDays, Wallet, Landmark, HeartPulse, ShieldCheck,
} from 'lucide-react'
import { Input } from '@/components/ui/Input'
import { Select } from '@/components/ui/Select'
import { Textarea } from '@/components/ui/Textarea'
import { Button } from '@/components/ui/Button'
import { EmptyState } from '@/components/EmptyState'
import { api } from '@/lib/api'
import { getErrorMessage } from '@/lib/apiError'
import { cn } from '@/lib/cn'
import type { Paged } from '@/types/master'
import {
  EmployeeStatusColor,
  EmployeeStatusLabel,
  GenderLabel,
  MaritalStatusLabel,
  EmployeeTypeLabel,
  DegreeLevelLabel,
  EducationModeLabel,
  GradeLevelLabel,
  FamilyRelationKindLabel,
  SkillKind,
  SkillKindLabel,
  EmployeeDocumentType,
  EmployeeDocumentTypeLabel,
  type EmployeeListItem,
  type EmployeeDetail,
  type EmployeeWorkHistoryDto,
  type EmployeeEducationDto,
  type EmployeeFamilyRelationDto,
  type EmployeeSkillDto,
  type EmployeeDocumentDto,
  type CreateEmployeeWorkHistoryInput,
  type CreateEmployeeEducationInput,
  type CreateEmployeeFamilyRelationInput,
  type CreateEmployeeSkillInput,
  type CreateEmployeeDocumentInput,
} from '@/types/employee'

const fmtDate = (s: string | null) => (s ? new Date(s).toLocaleDateString('vi-VN') : '—')
const fmtDateTime = (s: string | null) => (s ? new Date(s).toLocaleString('vi-VN') : '—')
const fmtMoney = (n: number | null) => (n != null ? n.toLocaleString('vi-VN') + ' đ' : null)

// Org-tree node mirror BE DepartmentTreeNodeDto (DepartmentFeatures.cs).
type DepartmentTreeNode = {
  id: string
  code: string
  name: string
  parentId: string | null
  directEmployeeCount: number
  totalEmployeeCount: number
  children: DepartmentTreeNode[]
}

export function EmployeesListPage() {
  const navigate = useNavigate()
  const qc = useQueryClient()
  const [sp, setSp] = useSearchParams()
  const search = sp.get('q') ?? ''
  const statusFilter = sp.get('status') ?? ''
  const deptFilter = sp.get('deptId') ?? ''
  const selectedId = sp.get('id')

  const [localSearch, setLocalSearch] = useState(search)
  const [treeOpenMobile, setTreeOpenMobile] = useState(false)
  const [companyOpen, setCompanyOpen] = useState(true) // gốc công ty mở mặc định

  // Org tree (consume /departments/tree). Class-level [Authorize] only → any
  // authenticated user. Counts come pre-rolled-up from BE (TotalEmployeeCount).
  const tree = useQuery({
    queryKey: ['departments-tree-hrm'],
    queryFn: async () => (await api.get<DepartmentTreeNode[]>('/departments/tree')).data,
  })

  const list = useQuery({
    queryKey: ['employees-list', { search, statusFilter, deptFilter }],
    queryFn: async () => {
      const res = await api.get<Paged<EmployeeListItem>>('/employees', {
        params: {
          pageSize: 100,
          search: search || undefined,
          status: statusFilter || undefined,
          departmentId: deptFilter || undefined,
        },
      })
      return res.data
    },
  })

  const detail = useQuery({
    queryKey: ['employee-detail', selectedId],
    queryFn: async () => (await api.get<EmployeeDetail>(`/employees/${selectedId}`)).data,
    enabled: !!selectedId,
  })

  const del = useMutation({
    mutationFn: async (id: string) => api.delete(`/employees/${id}`),
    onSuccess: () => {
      toast.success('Đã xoá hồ sơ NV.')
      setParam('id', null)
      qc.invalidateQueries({ queryKey: ['employees-list'] })
    },
    onError: e => toast.error(getErrorMessage(e)),
  })

  function setParam(key: string, value: string | null) {
    const next = new URLSearchParams(sp)
    if (value == null || value === '') next.delete(key)
    else next.set(key, value)
    setSp(next, { replace: true })
  }

  function applySearch(e: React.FormEvent) {
    e.preventDefault()
    setParam('q', localSearch.trim() || null)
  }

  function resetFilters() {
    setLocalSearch('')
    setSp(new URLSearchParams(), { replace: true })
  }

  // Name of the currently filtered department (for the list-panel subtitle).
  const selectedDeptName = useMemo(() => {
    if (!deptFilter || !tree.data) return null
    let found: string | null = null
    const walk = (nodes: DepartmentTreeNode[]) => {
      for (const n of nodes) {
        if (n.id === deptFilter) { found = n.name; return }
        walk(n.children)
        if (found) return
      }
    }
    walk(tree.data)
    return found
  }, [deptFilter, tree.data])

  function pickDept(id: string | null) {
    setParam('deptId', id)
    setTreeOpenMobile(false)
  }

  return (
    // 2-column shell: left rail (tree + list stacked) | right detail (flex-1).
    // <lg: single column (tree → list → detail), tree collapses to a toggle.
    <div className="grid h-full grid-cols-1 gap-4 p-4 lg:grid-cols-[22rem_1fr] xl:grid-cols-[24rem_1fr]">
      {/* ===================== LEFT RAIL — tree (top) + list (bottom) ===================== */}
      <div className="flex min-h-0 flex-col gap-4">
        {/* ---- Org tree (cố định cao theo nội dung, tối đa ~44% rail) ---- */}
        <aside
          className={cn(
            'flex min-h-0 flex-col overflow-hidden rounded-xl border border-slate-200 bg-white shadow-sm',
            'lg:!flex lg:max-h-[44%] lg:shrink-0',
            treeOpenMobile ? 'flex' : 'hidden',
          )}
        >
          <header className="flex shrink-0 items-center gap-2 border-b border-slate-100 px-4 py-3">
            <span className="icon-chip" style={{ height: '2rem', width: '2rem' }}>
              <Building2 className="h-4 w-4" />
            </span>
            <div>
              <div className="text-sm font-semibold tracking-tight text-brand-800">Cây tổ chức</div>
              <div className="text-[11px] text-slate-400">Lọc theo phòng ban</div>
            </div>
          </header>
          <div className="min-h-0 flex-1 overflow-auto p-2">
            {tree.isLoading ? (
              <div className="px-2 py-6 text-center text-xs text-slate-400">Đang tải cây tổ chức…</div>
            ) : (
              <ul className="space-y-0.5">
                {/* Gốc công ty — bấm = tất cả NV; các phòng ban toả xuống dưới (cha→con) */}
                <li>
                  <div
                    className={cn(
                      'group flex items-center gap-1 rounded-lg pr-1.5 transition',
                      !deptFilter ? 'bg-brand-50' : 'hover:bg-slate-50',
                    )}
                  >
                    <button
                      type="button"
                      onClick={() => setCompanyOpen(v => !v)}
                      className="grid h-5 w-5 shrink-0 place-items-center rounded text-slate-400 hover:text-slate-700"
                      aria-label={companyOpen ? 'Thu gọn' : 'Mở rộng'}
                      aria-expanded={companyOpen}
                    >
                      <ChevronRight className={cn('h-3.5 w-3.5 transition-transform', companyOpen && 'rotate-90')} />
                    </button>
                    <button
                      type="button"
                      onClick={() => pickDept(null)}
                      className={cn(
                        'flex min-w-0 flex-1 items-center justify-between gap-2 py-1.5 text-left text-sm transition',
                        !deptFilter ? 'font-semibold text-brand-700' : 'text-slate-700',
                      )}
                      title="SOLUTION COMPANY"
                    >
                      <span className="flex min-w-0 items-center gap-2">
                        <Building2 className="h-4 w-4 shrink-0 text-brand-500" />
                        <span className="truncate font-semibold tracking-tight">SOLUTION COMPANY</span>
                      </span>
                      <CountBadge value={list.data?.total ?? 0} active={!deptFilter} />
                    </button>
                  </div>
                  {companyOpen &&
                    (!tree.data || tree.data.length === 0 ? (
                      <div className="py-3 pl-9 text-xs text-slate-400">Chưa có phòng ban.</div>
                    ) : (
                      <ul className="space-y-0.5">
                        {tree.data.map(n => (
                          <TreeNode key={n.id} node={n} depth={1} selectedId={deptFilter} onPick={pickDept} />
                        ))}
                      </ul>
                    ))}
                </li>
              </ul>
            )}
          </div>
        </aside>

        {/* ---- List + filter (chiếm phần còn lại của rail, cuộn riêng) ---- */}
        <section className="flex min-h-0 flex-1 flex-col gap-3">
          <div className="flex items-center justify-between gap-2">
            <div className="min-w-0">
              <h2 className="truncate text-sm font-semibold tracking-tight text-brand-800">Hồ sơ Nhân sự</h2>
              <p className="truncate text-xs text-slate-500">
                {selectedDeptName ? `Phòng: ${selectedDeptName}` : 'Tất cả phòng ban'}
                {' · '}
                <span className="font-medium text-slate-700">{list.data?.total ?? 0}</span> hồ sơ
              </p>
            </div>
            <div className="flex shrink-0 items-center gap-2">
              {/* mobile-only tree toggle */}
              <Button
                type="button"
                variant="outline"
                size="sm"
                className="lg:hidden"
                onClick={() => setTreeOpenMobile(v => !v)}
              >
                <Building2 className="h-3.5 w-3.5" />
                Phòng ban
              </Button>
              <Button size="sm" onClick={() => navigate('/employees/new')}>
                <Plus className="h-4 w-4" />
                Tạo mới
              </Button>
            </div>
          </div>

          {/* search + status filter strip */}
          <form onSubmit={applySearch} className="flex flex-wrap items-center gap-2">
            <div className="relative min-w-0 flex-1">
              <Search className="pointer-events-none absolute left-2.5 top-1/2 h-4 w-4 -translate-y-1/2 text-slate-400" />
              <Input
                value={localSearch}
                onChange={e => setLocalSearch(e.target.value)}
                placeholder="Tìm mã NV hoặc họ tên…"
                className="pl-8"
              />
            </div>
            <Select
              value={statusFilter}
              onChange={e => setParam('status', e.target.value || null)}
              className="w-auto min-w-[9.5rem]"
              aria-label="Lọc theo trạng thái"
            >
              <option value="">Mọi trạng thái</option>
              <option value="1">Đang làm việc</option>
              <option value="2">Nghỉ phép</option>
              <option value="3">Đã nghỉ việc</option>
            </Select>
            <Button type="submit" size="sm">Tìm</Button>
            {(search || statusFilter || deptFilter) && (
              <Button type="button" variant="ghost" size="sm" onClick={resetFilters} title="Xoá bộ lọc">
                <X className="h-3.5 w-3.5" />
              </Button>
            )}
          </form>

          {/* list — compact flex rows (KHÔNG bảng 3 cột → không tràn ngang rail hẹp) */}
          <div className="min-h-0 flex-1 overflow-y-auto overflow-x-hidden rounded-xl border border-slate-200 bg-white shadow-sm">
            {list.isLoading ? (
              <div className="p-10 text-center text-sm text-slate-500">Đang tải…</div>
            ) : !list.data || list.data.items.length === 0 ? (
              <EmptyState
                icon={UserCircle2}
                title="Không có hồ sơ phù hợp"
                description="Đổi bộ lọc, hoặc bấm 'Tạo mới' để thêm hồ sơ nhân viên."
              />
            ) : (
              <div className="divide-y divide-slate-100">
                {list.data.items.map(e => {
                  const active = selectedId === e.id
                  return (
                    <button
                      key={e.id}
                      type="button"
                      onClick={() => setParam('id', e.id)}
                      className={cn(
                        'flex w-full items-center gap-2.5 px-3 py-2 text-left transition hover:bg-slate-50',
                        active && 'bg-brand-50 hover:bg-brand-50',
                      )}
                    >
                      <Avatar name={e.fullName} size={30} dim={e.status === 3} />
                      <div className="min-w-0 flex-1">
                        <div className="flex items-center justify-between gap-2">
                          <span className="truncate text-[13px] font-medium text-brand-800">{e.fullName ?? '—'}</span>
                          <span className="shrink-0"><StatusBadge status={e.status} /></span>
                        </div>
                        <div className="mt-0.5 flex items-center gap-1.5 truncate text-[11px] text-slate-500">
                          <span className="font-mono text-slate-400">{e.employeeCode}</span>
                          {e.departmentName && <><span className="text-slate-300">·</span><span className="truncate">{e.departmentName}</span></>}
                        </div>
                      </div>
                    </button>
                  )
                })}
              </div>
            )}
          </div>
        </section>
      </div>

      {/* ===================== RIGHT — detail (5 tab) ===================== */}
      <section className="flex min-h-0 flex-col overflow-hidden rounded-xl border border-slate-200 bg-white shadow-sm">
        {!selectedId ? (
          <div className="flex h-full flex-col items-center justify-center gap-2 p-10 text-center">
            <span className="icon-chip" style={{ height: '3rem', width: '3rem' }}>
              <UserCircle2 className="h-6 w-6" />
            </span>
            <p className="text-sm font-medium text-slate-600">Chọn một nhân viên</p>
            <p className="max-w-xs text-xs text-slate-400">
              Bấm vào một dòng ở danh sách để xem hồ sơ chi tiết: tổng quan, thân nhân, trình độ, kinh nghiệm và hợp đồng.
            </p>
          </div>
        ) : detail.isLoading ? (
          <div className="p-10 text-center text-sm text-slate-500">Đang tải chi tiết…</div>
        ) : !detail.data ? (
          <div className="p-10 text-center text-sm text-red-600">Không tìm thấy hồ sơ.</div>
        ) : (
          <EmployeeDetailTabs detail={detail.data} onDelete={() => del.mutate(detail.data!.id)} />
        )}
      </section>
    </div>
  )
}

// ===================== Org tree node (recursive) =====================

function TreeNode({ node, depth, selectedId, onPick }: {
  node: DepartmentTreeNode
  depth: number
  selectedId: string
  onPick: (id: string) => void
}) {
  const hasChildren = node.children.length > 0
  const [open, setOpen] = useState(depth < 1) // top level expanded by default
  const active = selectedId === node.id

  return (
    <li>
      <div
        className={cn(
          'group flex items-center gap-1 rounded-lg pr-1.5 transition',
          active ? 'bg-brand-50' : 'hover:bg-slate-50',
        )}
        style={{ paddingLeft: `${depth * 12 + 4}px` }}
      >
        {hasChildren ? (
          <button
            type="button"
            onClick={() => setOpen(v => !v)}
            className="grid h-5 w-5 shrink-0 place-items-center rounded text-slate-400 hover:text-slate-700"
            aria-label={open ? 'Thu gọn' : 'Mở rộng'}
            aria-expanded={open}
          >
            <ChevronRight className={cn('h-3.5 w-3.5 transition-transform', open && 'rotate-90')} />
          </button>
        ) : (
          <span className="h-5 w-5 shrink-0" />
        )}
        <button
          type="button"
          onClick={() => onPick(node.id)}
          className={cn(
            'flex min-w-0 flex-1 items-center justify-between gap-2 py-1.5 text-left text-sm transition',
            active ? 'font-semibold text-brand-700' : 'text-slate-700',
          )}
          title={node.name}
        >
          <span className="truncate">{node.name}</span>
          <CountBadge value={node.totalEmployeeCount} active={active} />
        </button>
      </div>
      {hasChildren && open && (
        <ul className="space-y-0.5">
          {node.children.map(c => (
            <TreeNode key={c.id} node={c} depth={depth + 1} selectedId={selectedId} onPick={onPick} />
          ))}
        </ul>
      )}
    </li>
  )
}

function CountBadge({ value, active }: { value: number; active: boolean }) {
  return (
    <span
      className={cn(
        'shrink-0 rounded-full px-1.5 py-0.5 text-[10px] font-semibold tabular-nums',
        active ? 'bg-brand-600 text-white' : 'bg-slate-100 text-slate-500',
      )}
    >
      {value}
    </span>
  )
}

// ===================== Avatar + status badge =====================

const AVATAR_TONES = [
  'from-brand-500 to-brand-700',
  'from-teal-500 to-teal-700',
  'from-violet-500 to-violet-700',
  'from-amberx-500 to-amberx-700',
  'from-greenx-500 to-greenx-700',
] as const

function initials(name: string | null): string {
  if (!name) return '?'
  const parts = name.trim().split(/\s+/)
  if (parts.length === 1) return parts[0].slice(0, 2).toUpperCase()
  return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase()
}

function toneFor(name: string | null): string {
  const s = name ?? ''
  let h = 0
  for (let i = 0; i < s.length; i++) h = (h * 31 + s.charCodeAt(i)) >>> 0
  return AVATAR_TONES[h % AVATAR_TONES.length]
}

function Avatar({ name, size, dim }: { name: string | null; size: number; dim?: boolean }) {
  return (
    <span
      className={cn(
        'inline-flex shrink-0 select-none items-center justify-center rounded-full bg-gradient-to-br font-semibold text-white',
        toneFor(name),
        dim && 'opacity-50 grayscale',
      )}
      style={{ height: size, width: size, fontSize: Math.round(size * 0.4) }}
      aria-hidden
    >
      {initials(name)}
    </span>
  )
}

function StatusBadge({ status }: { status: number }) {
  return (
    <span className={cn('inline-flex items-center rounded-full px-2 py-0.5 text-[11px] font-medium', EmployeeStatusColor[status])}>
      {EmployeeStatusLabel[status]}
    </span>
  )
}

// ===================== Section accent system (việc 2+3) =====================
// Mỗi section nhận MỘT accent từ palette (teal/violet/amberx/greenx + brand). Accent
// tô icon-chip (nền nhạt + chữ đậm), heading, và rail trái — tinh tế, KHÔNG loè loẹt.
// Mọi cặp bg-{x}-50 + text-{x}-700 đã đạt WCAG-AA (xem index.css §ACCENT PALETTE).
type Accent = 'brand' | 'teal' | 'violet' | 'amberx' | 'greenx'

// NOTE: accent palettes (teal/violet/amberx/greenx) ship stops 50/100/500/600/700
// ONLY — no -800 (see index.css §ACCENT PALETTE). So headings use -700 across the
// board (all clear WCAG-AA on white). Using a non-existent stop would silently emit
// no class in Tailwind v4 → uncolored heading.
const ACCENT: Record<Accent, { chipBg: string; chipFg: string; head: string; rail: string; labelText: string }> = {
  brand:  { chipBg: 'var(--color-brand-50)',  chipFg: 'var(--color-brand-600)',  head: 'text-brand-700',  rail: 'before:bg-brand-500',  labelText: 'text-brand-700' },
  teal:   { chipBg: 'var(--color-teal-50)',   chipFg: 'var(--color-teal-700)',   head: 'text-teal-700',   rail: 'before:bg-teal-500',   labelText: 'text-teal-700' },
  violet: { chipBg: 'var(--color-violet-50)', chipFg: 'var(--color-violet-700)', head: 'text-violet-700', rail: 'before:bg-violet-500', labelText: 'text-violet-700' },
  amberx: { chipBg: 'var(--color-amberx-50)', chipFg: 'var(--color-amberx-700)', head: 'text-amberx-700', rail: 'before:bg-amberx-500', labelText: 'text-amberx-700' },
  greenx: { chipBg: 'var(--color-greenx-50)', chipFg: 'var(--color-greenx-700)', head: 'text-greenx-700', rail: 'before:bg-greenx-500', labelText: 'text-greenx-700' },
}

// ===================== Detail with 5 tabs + satellite CRUD =====================

const TABS = [
  { key: 'overview', label: 'Tổng quan', icon: IdCard },
  { key: 'family', label: 'Thân nhân', icon: Users },
  { key: 'education', label: 'Trình độ', icon: GraduationCap },
  { key: 'experience', label: 'Kinh nghiệm', icon: Briefcase },
  { key: 'contract', label: 'Hợp đồng', icon: FileText },
] as const
type TabKey = typeof TABS[number]['key']

function EmployeeDetailTabs({ detail, onDelete }: { detail: EmployeeDetail; onDelete: () => void }) {
  const qc = useQueryClient()
  const employeeId = detail.id
  const [tab, setTab] = useState<TabKey>('overview')

  // State for inline add/edit forms (5 satellite) — UNCHANGED logic.
  const [addingWorkHistory, setAddingWorkHistory] = useState(false)
  const [editingWorkHistoryId, setEditingWorkHistoryId] = useState<string | null>(null)
  const [addingEducation, setAddingEducation] = useState(false)
  const [editingEducationId, setEditingEducationId] = useState<string | null>(null)
  const [addingFamilyRelation, setAddingFamilyRelation] = useState(false)
  const [editingFamilyRelationId, setEditingFamilyRelationId] = useState<string | null>(null)
  const [addingSkill, setAddingSkill] = useState(false)
  const [editingSkillId, setEditingSkillId] = useState<string | null>(null)
  const [addingDocument, setAddingDocument] = useState(false)
  const [editingDocumentId, setEditingDocumentId] = useState<string | null>(null)

  const invalidate = () => qc.invalidateQueries({ queryKey: ['employee-detail', employeeId] })

  // ===== WorkHistory mutations =====
  const createWorkHistory = useMutation({
    mutationFn: async (payload: CreateEmployeeWorkHistoryInput) =>
      api.post(`/employees/${employeeId}/work-history`, { employeeProfileId: employeeId, ...payload }),
    onSuccess: () => { toast.success('Đã thêm quá trình công tác.'); invalidate(); setAddingWorkHistory(false) },
    onError: e => toast.error(getErrorMessage(e)),
  })
  const updateWorkHistory = useMutation({
    mutationFn: async ({ satId, payload }: { satId: string; payload: CreateEmployeeWorkHistoryInput }) =>
      api.put(`/employees/${employeeId}/work-history/${satId}`, { id: satId, ...payload }),
    onSuccess: () => { toast.success('Đã cập nhật quá trình công tác.'); invalidate(); setEditingWorkHistoryId(null) },
    onError: e => toast.error(getErrorMessage(e)),
  })
  const deleteWorkHistory = useMutation({
    mutationFn: async (satId: string) => api.delete(`/employees/${employeeId}/work-history/${satId}`),
    onSuccess: () => { toast.success('Đã xoá quá trình công tác.'); invalidate() },
    onError: e => toast.error(getErrorMessage(e)),
  })

  // ===== Education mutations =====
  const createEducation = useMutation({
    mutationFn: async (payload: CreateEmployeeEducationInput) =>
      api.post(`/employees/${employeeId}/education`, { employeeProfileId: employeeId, ...payload }),
    onSuccess: () => { toast.success('Đã thêm quá trình đào tạo.'); invalidate(); setAddingEducation(false) },
    onError: e => toast.error(getErrorMessage(e)),
  })
  const updateEducation = useMutation({
    mutationFn: async ({ satId, payload }: { satId: string; payload: CreateEmployeeEducationInput }) =>
      api.put(`/employees/${employeeId}/education/${satId}`, { id: satId, ...payload }),
    onSuccess: () => { toast.success('Đã cập nhật quá trình đào tạo.'); invalidate(); setEditingEducationId(null) },
    onError: e => toast.error(getErrorMessage(e)),
  })
  const deleteEducation = useMutation({
    mutationFn: async (satId: string) => api.delete(`/employees/${employeeId}/education/${satId}`),
    onSuccess: () => { toast.success('Đã xoá quá trình đào tạo.'); invalidate() },
    onError: e => toast.error(getErrorMessage(e)),
  })

  // ===== FamilyRelation mutations =====
  const createFamilyRelation = useMutation({
    mutationFn: async (payload: CreateEmployeeFamilyRelationInput) =>
      api.post(`/employees/${employeeId}/family-relations`, { employeeProfileId: employeeId, ...payload }),
    onSuccess: () => { toast.success('Đã thêm thân nhân.'); invalidate(); setAddingFamilyRelation(false) },
    onError: e => toast.error(getErrorMessage(e)),
  })
  const updateFamilyRelation = useMutation({
    mutationFn: async ({ satId, payload }: { satId: string; payload: CreateEmployeeFamilyRelationInput }) =>
      api.put(`/employees/${employeeId}/family-relations/${satId}`, { id: satId, ...payload }),
    onSuccess: () => { toast.success('Đã cập nhật thân nhân.'); invalidate(); setEditingFamilyRelationId(null) },
    onError: e => toast.error(getErrorMessage(e)),
  })
  const deleteFamilyRelation = useMutation({
    mutationFn: async (satId: string) => api.delete(`/employees/${employeeId}/family-relations/${satId}`),
    onSuccess: () => { toast.success('Đã xoá thân nhân.'); invalidate() },
    onError: e => toast.error(getErrorMessage(e)),
  })

  // ===== Skill mutations =====
  const createSkill = useMutation({
    mutationFn: async (payload: CreateEmployeeSkillInput) =>
      api.post(`/employees/${employeeId}/skills`, { employeeProfileId: employeeId, ...payload }),
    onSuccess: () => { toast.success('Đã thêm kỹ năng.'); invalidate(); setAddingSkill(false) },
    onError: e => toast.error(getErrorMessage(e)),
  })
  const updateSkill = useMutation({
    mutationFn: async ({ satId, payload }: { satId: string; payload: CreateEmployeeSkillInput }) =>
      api.put(`/employees/${employeeId}/skills/${satId}`, { id: satId, ...payload }),
    onSuccess: () => { toast.success('Đã cập nhật kỹ năng.'); invalidate(); setEditingSkillId(null) },
    onError: e => toast.error(getErrorMessage(e)),
  })
  const deleteSkill = useMutation({
    mutationFn: async (satId: string) => api.delete(`/employees/${employeeId}/skills/${satId}`),
    onSuccess: () => { toast.success('Đã xoá kỹ năng.'); invalidate() },
    onError: e => toast.error(getErrorMessage(e)),
  })

  // ===== Document mutations =====
  const createDocument = useMutation({
    mutationFn: async (payload: CreateEmployeeDocumentInput) =>
      api.post(`/employees/${employeeId}/documents`, { employeeProfileId: employeeId, ...payload }),
    onSuccess: () => { toast.success('Đã thêm hồ sơ.'); invalidate(); setAddingDocument(false) },
    onError: e => toast.error(getErrorMessage(e)),
  })
  const updateDocument = useMutation({
    mutationFn: async ({ satId, payload }: { satId: string; payload: CreateEmployeeDocumentInput }) =>
      api.put(`/employees/${employeeId}/documents/${satId}`, { id: satId, ...payload }),
    onSuccess: () => { toast.success('Đã cập nhật hồ sơ.'); invalidate(); setEditingDocumentId(null) },
    onError: e => toast.error(getErrorMessage(e)),
  })
  const deleteDocument = useMutation({
    mutationFn: async (satId: string) => api.delete(`/employees/${employeeId}/documents/${satId}`),
    onSuccess: () => { toast.success('Đã xoá hồ sơ.'); invalidate() },
    onError: e => toast.error(getErrorMessage(e)),
  })

  // Contracts tab = documents of type LaborContract; the rest live under "Hợp đồng"
  // alongside other paperwork (keeps original 6th section's full document CRUD).
  const tabCount: Record<TabKey, number | null> = {
    overview: null,
    family: detail.familyRelations.length,
    education: detail.educations.length + detail.skills.length,
    experience: detail.workHistories.length,
    contract: detail.documents.length,
  }

  return (
    <div className="flex min-h-0 flex-col">
      {/* ===== Avatar header (brand gradient) ===== */}
      <header className="app-gradient-brand relative shrink-0 px-5 py-4 text-white">
        <div className="flex items-start justify-between gap-3">
          <div className="flex min-w-0 items-center gap-3.5">
            <span
              className="grid h-14 w-14 shrink-0 place-items-center rounded-2xl bg-white/15 text-xl font-bold ring-1 ring-white/25 backdrop-blur-sm"
              aria-hidden
            >
              {initials(detail.fullName)}
            </span>
            <div className="min-w-0">
              <h2 className="truncate text-lg font-bold leading-tight text-white! drop-shadow-sm">{detail.fullName ?? '—'}</h2>
              <div className="mt-1.5 flex flex-wrap items-center gap-x-2 gap-y-1 text-[13px] font-medium text-white">
                <span className="font-mono font-semibold tracking-tight">{detail.employeeCode}</span>
                {detail.departmentName && (<><span className="text-white/55">•</span><span className="truncate">{detail.departmentName}</span></>)}
                {detail.workLocation && (<><span className="text-white/55">•</span><span className="truncate">{detail.workLocation}</span></>)}
              </div>
              <div className="mt-2">
                <span className={cn(
                  'inline-flex items-center gap-1.5 rounded-full px-2.5 py-1 text-xs font-bold shadow-sm ring-1 ring-black/5',
                  EmployeeStatusColor[detail.employeeStatus],
                )}>
                  <span className="h-1.5 w-1.5 rounded-full bg-current opacity-70" />
                  {EmployeeStatusLabel[detail.employeeStatus]}
                </span>
              </div>
            </div>
          </div>
          <Button
            variant="danger"
            size="sm"
            className="shrink-0 border border-white/25 bg-white/10 shadow-none hover:bg-white/20"
            onClick={() => { if (confirm(`Xoá hồ sơ "${detail.fullName ?? detail.employeeCode}"?`)) onDelete() }}
          >
            <Trash2 className="h-3.5 w-3.5" />
            Xoá
          </Button>
        </div>
      </header>

      {/* ===== Tab bar ===== */}
      <nav className="flex shrink-0 items-stretch gap-0.5 overflow-x-auto border-b border-slate-200 bg-slate-50/60 px-2" role="tablist">
        {TABS.map(t => {
          const Icon = t.icon
          const on = tab === t.key
          const count = tabCount[t.key]
          return (
            <button
              key={t.key}
              type="button"
              role="tab"
              aria-selected={on}
              onClick={() => setTab(t.key)}
              className={cn(
                'relative flex items-center gap-1.5 whitespace-nowrap px-3 py-2.5 text-[13px] font-medium transition',
                on ? 'text-brand-700' : 'text-slate-500 hover:text-slate-800',
              )}
            >
              <Icon className="h-4 w-4" />
              {t.label}
              {count != null && count > 0 && (
                <span className={cn(
                  'rounded-full px-1.5 text-[10px] font-semibold tabular-nums',
                  on ? 'bg-brand-100 text-brand-700' : 'bg-slate-200 text-slate-500',
                )}>
                  {count}
                </span>
              )}
              {on && <span className="absolute inset-x-2 -bottom-px h-0.5 rounded-full bg-brand-600" />}
            </button>
          )
        })}
      </nav>

      {/* ===== Tab body (scroll) ===== */}
      <div className="min-h-0 flex-1 overflow-auto bg-slate-50/40 p-4">
        {tab === 'overview' && <OverviewTab detail={detail} />}

        {tab === 'family' && (
          <Card
            title="Quan hệ gia đình"
            icon={Users}
            accent="violet"
            count={detail.familyRelations.length}
            action={
              <Button size="sm" variant="outline" onClick={() => { setAddingFamilyRelation(true); setEditingFamilyRelationId(null) }} disabled={addingFamilyRelation}>
                <Plus className="h-3.5 w-3.5" /> Thêm thân nhân
              </Button>
            }
          >
            {addingFamilyRelation && (
              <FamilyRelationForm
                onSave={p => createFamilyRelation.mutate(p)}
                onCancel={() => setAddingFamilyRelation(false)}
                isPending={createFamilyRelation.isPending}
              />
            )}
            {detail.familyRelations.length === 0 && !addingFamilyRelation ? (
              <EmptyHint text="Chưa có thông tin thân nhân." />
            ) : (
              <div className="space-y-2">
                {detail.familyRelations.map(f => (
                  editingFamilyRelationId === f.id ? (
                    <FamilyRelationForm
                      key={f.id}
                      initial={f}
                      onSave={p => updateFamilyRelation.mutate({ satId: f.id, payload: p })}
                      onCancel={() => setEditingFamilyRelationId(null)}
                      isPending={updateFamilyRelation.isPending}
                    />
                  ) : (
                    <div key={f.id} className="relative grid grid-cols-1 gap-1 rounded-lg border border-slate-200 bg-white p-3 pr-16 text-sm md:grid-cols-5">
                      <div><span className="text-xs text-slate-500">Họ tên: </span><span className="font-medium text-brand-800">{f.fullName}</span></div>
                      <div><span className="text-xs text-slate-500">Quan hệ: </span><span className="text-brand-800">{FamilyRelationKindLabel[f.relationship]}</span></div>
                      <div><span className="text-xs text-slate-500">Năm sinh: </span><span className="text-brand-800">{f.birthYear ?? '—'}</span></div>
                      <div><span className="text-xs text-slate-500">Nghề: </span><span className="text-brand-800">{f.occupation ?? '—'}</span></div>
                      <div><span className="text-xs text-slate-500">SĐT: </span><span className="text-brand-800">{f.phone ?? '—'}</span></div>
                      <RowActions
                        onEdit={() => { setEditingFamilyRelationId(f.id); setAddingFamilyRelation(false) }}
                        onDelete={() => { if (confirm(`Xoá thân nhân "${f.fullName}"?`)) deleteFamilyRelation.mutate(f.id) }}
                      />
                    </div>
                  )
                ))}
              </div>
            )}
          </Card>
        )}

        {tab === 'education' && (
          <div className="space-y-4">
            <Card
              title="Quá trình đào tạo"
              icon={GraduationCap}
              accent="teal"
              count={detail.educations.length}
              action={
                <Button size="sm" variant="outline" onClick={() => { setAddingEducation(true); setEditingEducationId(null) }} disabled={addingEducation}>
                  <Plus className="h-3.5 w-3.5" /> Thêm
                </Button>
              }
            >
              {addingEducation && (
                <EducationForm
                  onSave={p => createEducation.mutate(p)}
                  onCancel={() => setAddingEducation(false)}
                  isPending={createEducation.isPending}
                />
              )}
              {detail.educations.length === 0 && !addingEducation ? (
                <EmptyHint text="Chưa có quá trình đào tạo nào." />
              ) : (
                <div className="space-y-2">
                  {detail.educations.map(ed => (
                    editingEducationId === ed.id ? (
                      <EducationForm
                        key={ed.id}
                        initial={ed}
                        onSave={p => updateEducation.mutate({ satId: ed.id, payload: p })}
                        onCancel={() => setEditingEducationId(null)}
                        isPending={updateEducation.isPending}
                      />
                    ) : (
                      <div key={ed.id} className="relative rounded-lg border border-slate-200 bg-white p-3 pr-16 text-sm">
                        <div className="flex items-baseline justify-between">
                          <div className="font-medium text-brand-800">{ed.schoolName}</div>
                          <div className="text-xs text-slate-500">
                            {fmtDate(ed.fromDate)} → {fmtDate(ed.toDate)}
                          </div>
                        </div>
                        <div className="mt-1 flex flex-wrap gap-x-4 gap-y-1 text-xs text-slate-600">
                          {ed.major && <span>Chuyên ngành: {ed.major}</span>}
                          {ed.degreeLevel != null && <span>Bằng cấp: {DegreeLevelLabel[ed.degreeLevel]}</span>}
                          {ed.educationMode != null && <span>Hình thức: {EducationModeLabel[ed.educationMode]}</span>}
                          {ed.gradeLevel != null && <span>Xếp loại: {GradeLevelLabel[ed.gradeLevel]}</span>}
                        </div>
                        {ed.certificateIssueDate && <div className="mt-1 text-xs text-slate-500">Ngày cấp bằng: {fmtDate(ed.certificateIssueDate)}</div>}
                        {ed.notes && <div className="mt-1 whitespace-pre-wrap text-xs text-slate-600">{ed.notes}</div>}
                        <RowActions
                          onEdit={() => { setEditingEducationId(ed.id); setAddingEducation(false) }}
                          onDelete={() => { if (confirm(`Xoá quá trình đào tạo tại "${ed.schoolName}"?`)) deleteEducation.mutate(ed.id) }}
                        />
                      </div>
                    )
                  ))}
                </div>
              )}
            </Card>

            <Card
              title="Kỹ năng"
              icon={ShieldCheck}
              accent="greenx"
              count={detail.skills.length}
              action={
                <Button size="sm" variant="outline" onClick={() => { setAddingSkill(true); setEditingSkillId(null) }} disabled={addingSkill}>
                  <Plus className="h-3.5 w-3.5" /> Thêm
                </Button>
              }
            >
              {addingSkill && (
                <SkillForm
                  onSave={p => createSkill.mutate(p)}
                  onCancel={() => setAddingSkill(false)}
                  isPending={createSkill.isPending}
                />
              )}
              {detail.skills.length === 0 && !addingSkill ? (
                <EmptyHint text="Chưa có thông tin kỹ năng." />
              ) : (
                <div className="space-y-3">
                  {[SkillKind.Computer, SkillKind.Language, SkillKind.Other].map(kind => {
                    const group = detail.skills.filter(s => s.kind === kind)
                    if (group.length === 0) return null
                    return (
                      <div key={kind}>
                        <div className="mb-1 text-xs font-semibold uppercase tracking-wide text-slate-500">
                          {SkillKindLabel[kind]}
                        </div>
                        <ul className="space-y-1">
                          {group.map(s => (
                            editingSkillId === s.id ? (
                              <SkillForm
                                key={s.id}
                                initial={s}
                                onSave={p => updateSkill.mutate({ satId: s.id, payload: p })}
                                onCancel={() => setEditingSkillId(null)}
                                isPending={updateSkill.isPending}
                              />
                            ) : (
                              <li key={s.id} className="relative rounded-lg border border-slate-200 bg-white px-3 py-2 pr-16 text-sm">
                                <div className="flex items-baseline justify-between">
                                  <span className="font-medium text-brand-800">{s.name}</span>
                                  {s.level && <span className="text-xs text-slate-500">{s.level}</span>}
                                </div>
                                {s.languageId && <div className="text-xs text-slate-500">Mã: {s.languageId}</div>}
                                <RowActions
                                  onEdit={() => { setEditingSkillId(s.id); setAddingSkill(false) }}
                                  onDelete={() => { if (confirm(`Xoá kỹ năng "${s.name}"?`)) deleteSkill.mutate(s.id) }}
                                />
                              </li>
                            )
                          ))}
                        </ul>
                      </div>
                    )
                  })}
                </div>
              )}
            </Card>
          </div>
        )}

        {tab === 'experience' && (
          <Card
            title="Quá trình công tác"
            icon={Briefcase}
            accent="amberx"
            count={detail.workHistories.length}
            action={
              <Button size="sm" variant="outline" onClick={() => { setAddingWorkHistory(true); setEditingWorkHistoryId(null) }} disabled={addingWorkHistory}>
                <Plus className="h-3.5 w-3.5" /> Thêm kinh nghiệm
              </Button>
            }
          >
            {addingWorkHistory && (
              <WorkHistoryForm
                onSave={p => createWorkHistory.mutate(p)}
                onCancel={() => setAddingWorkHistory(false)}
                isPending={createWorkHistory.isPending}
              />
            )}
            {detail.workHistories.length === 0 && !addingWorkHistory ? (
              <EmptyHint text="Chưa có quá trình công tác nào." />
            ) : (
              <div className="space-y-2">
                {detail.workHistories.map(w => (
                  editingWorkHistoryId === w.id ? (
                    <WorkHistoryForm
                      key={w.id}
                      initial={w}
                      onSave={p => updateWorkHistory.mutate({ satId: w.id, payload: p })}
                      onCancel={() => setEditingWorkHistoryId(null)}
                      isPending={updateWorkHistory.isPending}
                    />
                  ) : (
                    <div key={w.id} className="relative rounded-lg border border-slate-200 bg-white p-3 pr-16 text-sm">
                      <div className="flex items-baseline justify-between">
                        <div className="font-medium text-brand-800">{w.companyName}</div>
                        <div className="text-xs text-slate-500">
                          {fmtDate(w.fromDate)} → {fmtDate(w.toDate)}
                        </div>
                      </div>
                      {w.jobTitle && <div className="mt-1 text-xs text-slate-600">Chức vụ: {w.jobTitle}</div>}
                      {w.industry && <div className="text-xs text-slate-600">Ngành: {w.industry}</div>}
                      {w.companyAddress && <div className="text-xs text-slate-500">Địa chỉ: {w.companyAddress}</div>}
                      {w.jobDescription && <div className="mt-1 whitespace-pre-wrap text-xs text-slate-600">{w.jobDescription}</div>}
                      {w.resignReason && <div className="mt-1 text-xs italic text-slate-500">Lý do nghỉ: {w.resignReason}</div>}
                      <RowActions
                        onEdit={() => { setEditingWorkHistoryId(w.id); setAddingWorkHistory(false) }}
                        onDelete={() => { if (confirm(`Xoá quá trình công tác tại "${w.companyName}"?`)) deleteWorkHistory.mutate(w.id) }}
                      />
                    </div>
                  )
                ))}
              </div>
            )}
          </Card>
        )}

        {tab === 'contract' && (
          <Card
            title="Hồ sơ & hợp đồng giấy tờ"
            icon={FileText}
            accent="brand"
            count={detail.documents.length}
            action={
              <Button size="sm" variant="outline" onClick={() => { setAddingDocument(true); setEditingDocumentId(null) }} disabled={addingDocument}>
                <Plus className="h-3.5 w-3.5" /> Thêm hồ sơ
              </Button>
            }
          >
            {addingDocument && (
              <DocumentForm
                onSave={p => createDocument.mutate(p)}
                onCancel={() => setAddingDocument(false)}
                isPending={createDocument.isPending}
              />
            )}
            {detail.documents.length === 0 && !addingDocument ? (
              <EmptyHint text="Chưa có hồ sơ giấy tờ / hợp đồng nào." />
            ) : (
              <div className="space-y-2">
                {detail.documents.map(doc => (
                  editingDocumentId === doc.id ? (
                    <DocumentForm
                      key={doc.id}
                      initial={doc}
                      onSave={p => updateDocument.mutate({ satId: doc.id, payload: p })}
                      onCancel={() => setEditingDocumentId(null)}
                      isPending={updateDocument.isPending}
                    />
                  ) : (
                    <div key={doc.id} className="relative grid grid-cols-1 gap-1 rounded-lg border border-slate-200 bg-white p-3 pr-16 text-sm md:grid-cols-4">
                      <div>
                        <span className="text-xs text-slate-500">Loại: </span>
                        <span className={cn(
                          'inline-flex rounded-full px-1.5 py-0.5 text-[11px] font-medium',
                          doc.documentType === EmployeeDocumentType.LaborContract
                            ? 'bg-brand-50 text-brand-700'
                            : 'bg-slate-100 text-slate-600',
                        )}>
                          {EmployeeDocumentTypeLabel[doc.documentType]}
                        </span>
                      </div>
                      <div>
                        <span className="text-xs text-slate-500">Tên file: </span>
                        <a href={doc.filePath} target="_blank" rel="noreferrer" className="text-brand-700 hover:underline">{doc.fileName}</a>
                      </div>
                      <div><span className="text-xs text-slate-500">Ngày cấp: </span><span className="text-brand-800">{fmtDate(doc.issueDate)}</span></div>
                      <div><span className="text-xs text-slate-500">Hết hạn: </span><span className="text-brand-800">{fmtDate(doc.expiryDate)}</span></div>
                      <RowActions
                        onEdit={() => { setEditingDocumentId(doc.id); setAddingDocument(false) }}
                        onDelete={() => { if (confirm(`Xoá hồ sơ "${doc.fileName}"?`)) deleteDocument.mutate(doc.id) }}
                      />
                    </div>
                  )
                ))}
              </div>
            )}
          </Card>
        )}

        <footer className="mt-4 border-t border-slate-200 pt-2 text-xs text-slate-400">
          Tạo: {fmtDateTime(detail.createdAt)}
          {detail.updatedAt && <> · Cập nhật: {fmtDateTime(detail.updatedAt)}</>}
        </footer>
      </div>
    </div>
  )
}

// ===================== Overview tab (2-column layout) =====================
// Mỗi card mang một accent từ palette → section header có màu rõ, dễ scan, tinh tế.

function OverviewTab({ detail }: { detail: EmployeeDetail }) {
  return (
    <div className="grid grid-cols-1 gap-4 xl:grid-cols-2">
      {/* LEFT column */}
      <div className="space-y-4">
        <Card title="Thông tin chung" icon={IdCard} accent="brand">
          <Grid2>
            <Field label="Ngày sinh" value={fmtDate(detail.dateOfBirth)} icon={CalendarDays} accent="brand" />
            <Field label="Giới tính" value={detail.gender != null ? GenderLabel[detail.gender] : null} accent="brand" />
            <Field label="Tình trạng hôn nhân" value={detail.maritalStatus != null ? MaritalStatusLabel[detail.maritalStatus] : null} accent="brand" />
            <Field label="Dân tộc" value={detail.ethnicity} accent="brand" />
            <Field label="Tôn giáo" value={detail.religion} accent="brand" />
            <Field label="Quốc tịch" value={detail.nationality} accent="brand" />
            <Field label="Nơi sinh" value={detail.birthPlace} accent="brand" />
            <Field label="Quê quán" value={detail.hometown} accent="brand" />
            <Field label="SĐT" value={detail.phone} icon={Phone} accent="brand" />
            <Field label="SĐT nội bộ" value={detail.internalPhone} accent="brand" />
            <Field label="Email" value={detail.email} icon={Mail} accent="brand" />
            <Field label="Email cá nhân" value={detail.personalEmail} accent="brand" />
          </Grid2>
        </Card>

        <Card title="Sức khoẻ" icon={HeartPulse} accent="greenx">
          <Grid2>
            <Field label="Chiều cao" value={detail.heightCm != null ? `${detail.heightCm} cm` : null} accent="greenx" />
            <Field label="Cân nặng" value={detail.weightKg != null ? `${detail.weightKg} kg` : null} accent="greenx" />
            <Field label="Nhóm máu" value={detail.bloodType} accent="greenx" />
            <Field label="Nơi đăng ký KCB" value={detail.medicalRegistrationPlace} accent="greenx" />
          </Grid2>
        </Card>

        <Card title="Liên hệ & địa chỉ" icon={MapPin} accent="teal">
          <Grid2>
            <Field label="Thường trú" value={detail.permanentAddressText} accent="teal" />
            <Field label="Số nhà / Đường (Thường trú)" value={detail.streetAddressPermanent} accent="teal" />
            <Field label="Tạm trú" value={detail.temporaryAddressText} accent="teal" />
            <Field label="Số nhà / Đường (Tạm trú)" value={detail.streetAddressTemporary} accent="teal" />
            <Field label="Liên hệ khẩn cấp" value={detail.emergencyContactName} accent="teal" />
            <Field label="SĐT khẩn cấp" value={detail.emergencyContactPhone} accent="teal" />
            <Field label="Địa chỉ khẩn cấp" value={detail.emergencyContactAddress} full accent="teal" />
          </Grid2>
        </Card>

        <Card title="Giấy tờ tuỳ thân" icon={IdCard} accent="violet">
          <Grid2>
            <Field label="CMND/CCCD" value={detail.idCardNumber} mono accent="violet" />
            <Field label="Ngày cấp" value={fmtDate(detail.idCardIssueDate)} accent="violet" />
            <Field label="Nơi cấp" value={detail.idCardIssuePlace} full accent="violet" />
            <Field label="Hộ chiếu" value={detail.passportNumber} mono accent="violet" />
            <Field label="MST cá nhân" value={detail.taxCode} mono accent="violet" />
            <Field label="Số BHXH" value={detail.socialInsuranceNumber} mono accent="violet" />
          </Grid2>
        </Card>
      </div>

      {/* RIGHT column */}
      <div className="space-y-4">
        <Card title="Công việc & chế độ" icon={Briefcase} accent="amberx">
          <Grid2>
            <Field label="Mã NV" value={detail.employeeCode} mono accent="amberx" />
            <Field label="Loại NV" value={detail.employeeType != null ? EmployeeTypeLabel[detail.employeeType] : null} accent="amberx" />
            <Field label="Phòng ban" value={detail.departmentName} accent="amberx" />
            <Field label="Vị trí công tác" value={detail.workLocation} accent="amberx" />
            <Field label="Ngày vào làm" value={fmtDate(detail.hireDate)} icon={CalendarDays} accent="amberx" />
            <Field label="Ngày nghỉ việc" value={fmtDate(detail.resignDate)} accent="amberx" />
            <Field label="Mã chấm công" value={detail.timekeepingCode} mono accent="amberx" />
            <Field label="Trình độ chuyên môn" value={detail.qualification} accent="amberx" />
          </Grid2>
        </Card>

        <Card title="Lương & bảo hiểm" icon={Wallet} accent="greenx">
          <Grid2>
            <Field label="Lương cơ bản" value={fmtMoney(detail.baseSalary)} accent="greenx" />
            <Field label="Tổng lương" value={fmtMoney(detail.totalSalary)} accent="greenx" />
            <Field label="BHXH bắt đầu" value={fmtDate(detail.socialInsuranceStartDate)} accent="greenx" />
            <Field label="Số BHXH" value={detail.socialInsuranceNumber} mono accent="greenx" />
          </Grid2>
          <SubLabel accent="greenx">Ngày phép</SubLabel>
          <Grid2>
            <Field label="Phép năm" value={detail.annualLeaveDays != null ? `${detail.annualLeaveDays} ngày` : null} accent="greenx" />
            <Field label="Phép còn lại" value={detail.remainingLeaveDays != null ? `${detail.remainingLeaveDays} ngày` : null} accent="greenx" />
            <Field label="Phép bù" value={detail.compensatoryLeaveDays != null ? `${detail.compensatoryLeaveDays} ngày` : null} accent="greenx" />
            <Field label="Phép thâm niên" value={detail.seniorityLeaveDays != null ? `${detail.seniorityLeaveDays} ngày` : null} accent="greenx" />
          </Grid2>
        </Card>

        <Card title="Ngân hàng" icon={Landmark} accent="teal">
          <Grid2>
            <Field label="Số tài khoản" value={detail.bankAccount} mono accent="teal" />
            <Field label="Ngân hàng" value={detail.bankName} accent="teal" />
            <Field label="Chi nhánh" value={detail.bankBranch} full accent="teal" />
          </Grid2>
        </Card>

        <Card title="Đoàn thể" icon={ShieldCheck} accent="violet">
          <Grid2>
            <Field label="Đảng viên" value={detail.isCommunistParty ? 'Có' : 'Không'} accent="violet" />
            <Field label="Ngày kết nạp Đảng" value={fmtDate(detail.communistPartyJoinDate)} accent="violet" />
            <Field label="Đoàn viên" value={detail.isYouthUnion ? 'Có' : 'Không'} accent="violet" />
            <Field label="Ngày kết nạp Đoàn" value={fmtDate(detail.youthUnionJoinDate)} accent="violet" />
            <Field label="Công đoàn" value={detail.isTradeUnion ? 'Có' : 'Không'} accent="violet" />
            <Field label="Ngày kết nạp CĐ" value={fmtDate(detail.tradeUnionJoinDate)} accent="violet" />
          </Grid2>
        </Card>

        {detail.notes && (
          <Card title="Ghi chú" icon={FileText} accent="brand">
            <p className="whitespace-pre-wrap text-sm text-brand-800">{detail.notes}</p>
          </Card>
        )}
      </div>
    </div>
  )
}

// ===================== Inline forms for 5 satellite (cookie-cutter, UNCHANGED) =====================

const nullable = (s: string) => s.trim() || null
const nullableNumber = (s: string): number | null => {
  const n = Number(s)
  return s.trim() === '' || isNaN(n) ? null : n
}

function WorkHistoryForm({ initial, onSave, onCancel, isPending }: {
  initial?: EmployeeWorkHistoryDto
  onSave: (p: CreateEmployeeWorkHistoryInput) => void
  onCancel: () => void
  isPending: boolean
}) {
  const [form, setForm] = useState({
    companyName: initial?.companyName ?? '',
    companyAddress: initial?.companyAddress ?? '',
    industry: initial?.industry ?? '',
    fromDate: initial?.fromDate ?? '',
    toDate: initial?.toDate ?? '',
    jobTitle: initial?.jobTitle ?? '',
    jobDescription: initial?.jobDescription ?? '',
    resignReason: initial?.resignReason ?? '',
  })

  function handleSubmit(e: React.FormEvent) {
    e.preventDefault()
    onSave({
      companyName: form.companyName.trim(),
      companyAddress: nullable(form.companyAddress),
      industry: nullable(form.industry),
      fromDate: form.fromDate || null,
      toDate: form.toDate || null,
      jobTitle: nullable(form.jobTitle),
      jobDescription: nullable(form.jobDescription),
      resignReason: nullable(form.resignReason),
    })
  }

  return (
    <form onSubmit={handleSubmit} className="space-y-3 rounded-lg border-2 border-brand-200 bg-brand-50/40 p-3">
      <Grid2>
        <FormField label="Tên công ty *">
          <Input value={form.companyName} onChange={e => setForm({ ...form, companyName: e.target.value })} required maxLength={200} />
        </FormField>
        <FormField label="Địa chỉ công ty">
          <Input value={form.companyAddress} onChange={e => setForm({ ...form, companyAddress: e.target.value })} maxLength={500} />
        </FormField>
        <FormField label="Ngành nghề">
          <Input value={form.industry} onChange={e => setForm({ ...form, industry: e.target.value })} maxLength={100} />
        </FormField>
        <FormField label="Chức vụ">
          <Input value={form.jobTitle} onChange={e => setForm({ ...form, jobTitle: e.target.value })} maxLength={200} />
        </FormField>
        <FormField label="Từ ngày">
          <Input type="date" value={form.fromDate} onChange={e => setForm({ ...form, fromDate: e.target.value })} />
        </FormField>
        <FormField label="Đến ngày">
          <Input type="date" value={form.toDate} onChange={e => setForm({ ...form, toDate: e.target.value })} />
        </FormField>
      </Grid2>
      <FormField label="Mô tả công việc">
        <Textarea value={form.jobDescription} onChange={e => setForm({ ...form, jobDescription: e.target.value })} maxLength={2000} rows={2} />
      </FormField>
      <FormField label="Lý do nghỉ">
        <Input value={form.resignReason} onChange={e => setForm({ ...form, resignReason: e.target.value })} maxLength={500} />
      </FormField>
      <FormFooter onCancel={onCancel} isPending={isPending} isEdit={!!initial} />
    </form>
  )
}

function EducationForm({ initial, onSave, onCancel, isPending }: {
  initial?: EmployeeEducationDto
  onSave: (p: CreateEmployeeEducationInput) => void
  onCancel: () => void
  isPending: boolean
}) {
  const [form, setForm] = useState({
    schoolName: initial?.schoolName ?? '',
    major: initial?.major ?? '',
    degreeLevel: initial?.degreeLevel != null ? String(initial.degreeLevel) : '',
    educationMode: initial?.educationMode != null ? String(initial.educationMode) : '',
    gradeLevel: initial?.gradeLevel != null ? String(initial.gradeLevel) : '',
    fromDate: initial?.fromDate ?? '',
    toDate: initial?.toDate ?? '',
    certificateIssueDate: initial?.certificateIssueDate ?? '',
    notes: initial?.notes ?? '',
  })

  function handleSubmit(e: React.FormEvent) {
    e.preventDefault()
    onSave({
      schoolName: form.schoolName.trim(),
      major: nullable(form.major),
      degreeLevel: nullableNumber(form.degreeLevel),
      educationMode: nullableNumber(form.educationMode),
      gradeLevel: nullableNumber(form.gradeLevel),
      fromDate: form.fromDate || null,
      toDate: form.toDate || null,
      certificateIssueDate: form.certificateIssueDate || null,
      notes: nullable(form.notes),
    })
  }

  return (
    <form onSubmit={handleSubmit} className="space-y-3 rounded-lg border-2 border-brand-200 bg-brand-50/40 p-3">
      <Grid2>
        <FormField label="Tên trường *">
          <Input value={form.schoolName} onChange={e => setForm({ ...form, schoolName: e.target.value })} required maxLength={200} />
        </FormField>
        <FormField label="Chuyên ngành">
          <Input value={form.major} onChange={e => setForm({ ...form, major: e.target.value })} maxLength={200} />
        </FormField>
        <FormField label="Bằng cấp">
          <Select value={form.degreeLevel} onChange={e => setForm({ ...form, degreeLevel: e.target.value })}>
            <option value="">— Chọn —</option>
            <option value="1">Cao đẳng</option>
            <option value="2">Đại học</option>
            <option value="3">Thạc sĩ</option>
            <option value="4">Tiến sĩ</option>
          </Select>
        </FormField>
        <FormField label="Hình thức">
          <Select value={form.educationMode} onChange={e => setForm({ ...form, educationMode: e.target.value })}>
            <option value="">— Chọn —</option>
            <option value="1">Chính quy</option>
            <option value="2">Tại chức</option>
            <option value="3">Từ xa</option>
          </Select>
        </FormField>
        <FormField label="Xếp loại">
          <Select value={form.gradeLevel} onChange={e => setForm({ ...form, gradeLevel: e.target.value })}>
            <option value="">— Chọn —</option>
            <option value="1">Trung bình</option>
            <option value="2">Khá</option>
            <option value="3">Giỏi</option>
          </Select>
        </FormField>
        <FormField label="Ngày cấp bằng">
          <Input type="date" value={form.certificateIssueDate} onChange={e => setForm({ ...form, certificateIssueDate: e.target.value })} />
        </FormField>
        <FormField label="Từ ngày">
          <Input type="date" value={form.fromDate} onChange={e => setForm({ ...form, fromDate: e.target.value })} />
        </FormField>
        <FormField label="Đến ngày">
          <Input type="date" value={form.toDate} onChange={e => setForm({ ...form, toDate: e.target.value })} />
        </FormField>
      </Grid2>
      <FormField label="Ghi chú">
        <Textarea value={form.notes} onChange={e => setForm({ ...form, notes: e.target.value })} maxLength={1000} rows={2} />
      </FormField>
      <FormFooter onCancel={onCancel} isPending={isPending} isEdit={!!initial} />
    </form>
  )
}

function FamilyRelationForm({ initial, onSave, onCancel, isPending }: {
  initial?: EmployeeFamilyRelationDto
  onSave: (p: CreateEmployeeFamilyRelationInput) => void
  onCancel: () => void
  isPending: boolean
}) {
  const [form, setForm] = useState({
    fullName: initial?.fullName ?? '',
    relationship: initial?.relationship != null ? String(initial.relationship) : '1',
    birthYear: initial?.birthYear != null ? String(initial.birthYear) : '',
    occupation: initial?.occupation ?? '',
    currentAddress: initial?.currentAddress ?? '',
    phone: initial?.phone ?? '',
  })

  function handleSubmit(e: React.FormEvent) {
    e.preventDefault()
    onSave({
      fullName: form.fullName.trim(),
      relationship: Number(form.relationship),
      birthYear: nullableNumber(form.birthYear),
      occupation: nullable(form.occupation),
      currentAddress: nullable(form.currentAddress),
      phone: nullable(form.phone),
    })
  }

  return (
    <form onSubmit={handleSubmit} className="space-y-3 rounded-lg border-2 border-brand-200 bg-brand-50/40 p-3">
      <Grid2>
        <FormField label="Họ tên *">
          <Input value={form.fullName} onChange={e => setForm({ ...form, fullName: e.target.value })} required maxLength={200} />
        </FormField>
        <FormField label="Quan hệ *">
          <Select value={form.relationship} onChange={e => setForm({ ...form, relationship: e.target.value })} required>
            <option value="1">Cha</option>
            <option value="2">Mẹ</option>
            <option value="3">Vợ/Chồng</option>
            <option value="4">Con</option>
            <option value="5">Anh/Chị/Em ruột</option>
            <option value="99">Khác</option>
          </Select>
        </FormField>
        <FormField label="Năm sinh">
          <Input type="number" min={1900} max={2026} value={form.birthYear} onChange={e => setForm({ ...form, birthYear: e.target.value })} />
        </FormField>
        <FormField label="Nghề nghiệp">
          <Input value={form.occupation} onChange={e => setForm({ ...form, occupation: e.target.value })} maxLength={200} />
        </FormField>
        <FormField label="SĐT">
          <Input value={form.phone} onChange={e => setForm({ ...form, phone: e.target.value })} maxLength={20} />
        </FormField>
        <FormField label="Địa chỉ hiện tại">
          <Input value={form.currentAddress} onChange={e => setForm({ ...form, currentAddress: e.target.value })} maxLength={500} />
        </FormField>
      </Grid2>
      <FormFooter onCancel={onCancel} isPending={isPending} isEdit={!!initial} />
    </form>
  )
}

function SkillForm({ initial, onSave, onCancel, isPending }: {
  initial?: EmployeeSkillDto
  onSave: (p: CreateEmployeeSkillInput) => void
  onCancel: () => void
  isPending: boolean
}) {
  const [form, setForm] = useState({
    kind: initial?.kind != null ? String(initial.kind) : '1',
    name: initial?.name ?? '',
    languageId: initial?.languageId ?? '',
    level: initial?.level ?? '',
  })

  function handleSubmit(e: React.FormEvent) {
    e.preventDefault()
    onSave({
      kind: Number(form.kind),
      name: form.name.trim(),
      languageId: nullable(form.languageId),
      level: nullable(form.level),
    })
  }

  return (
    <form onSubmit={handleSubmit} className="space-y-3 rounded-lg border-2 border-brand-200 bg-brand-50/40 p-3">
      <Grid2>
        <FormField label="Loại *">
          <Select value={form.kind} onChange={e => setForm({ ...form, kind: e.target.value })} required>
            <option value="1">Kỹ năng vi tính</option>
            <option value="2">Ngoại ngữ</option>
            <option value="3">Kỹ năng khác</option>
          </Select>
        </FormField>
        <FormField label="Tên kỹ năng *">
          <Input value={form.name} onChange={e => setForm({ ...form, name: e.target.value })} required maxLength={200} />
        </FormField>
        <FormField label="Mã ngôn ngữ">
          <Input value={form.languageId} onChange={e => setForm({ ...form, languageId: e.target.value })} maxLength={10} placeholder="vi/en/ja..." />
        </FormField>
        <FormField label="Trình độ">
          <Input value={form.level} onChange={e => setForm({ ...form, level: e.target.value })} maxLength={200} placeholder="B1/IELTS 6.5/N2..." />
        </FormField>
      </Grid2>
      <FormFooter onCancel={onCancel} isPending={isPending} isEdit={!!initial} />
    </form>
  )
}

function DocumentForm({ initial, onSave, onCancel, isPending }: {
  initial?: EmployeeDocumentDto
  onSave: (p: CreateEmployeeDocumentInput) => void
  onCancel: () => void
  isPending: boolean
}) {
  const [form, setForm] = useState({
    documentType: initial?.documentType != null ? String(initial.documentType) : '1',
    fileName: initial?.fileName ?? '',
    filePath: initial?.filePath ?? '',
    fileSize: initial?.fileSize != null ? String(initial.fileSize) : '0',
    contentType: initial?.contentType ?? 'application/octet-stream',
    issueDate: initial?.issueDate ?? '',
    expiryDate: initial?.expiryDate ?? '',
    notes: initial?.notes ?? '',
  })

  function handleSubmit(e: React.FormEvent) {
    e.preventDefault()
    onSave({
      documentType: Number(form.documentType),
      fileName: form.fileName.trim(),
      filePath: form.filePath.trim(),
      fileSize: Number(form.fileSize) || 0,
      contentType: form.contentType.trim(),
      issueDate: form.issueDate || null,
      expiryDate: form.expiryDate || null,
      notes: nullable(form.notes),
    })
  }

  return (
    <form onSubmit={handleSubmit} className="space-y-3 rounded-lg border-2 border-brand-200 bg-brand-50/40 p-3">
      <Grid2>
        <FormField label="Loại hồ sơ *">
          <Select value={form.documentType} onChange={e => setForm({ ...form, documentType: e.target.value })} required>
            <option value="1">CMND/CCCD</option>
            <option value="2">Hộ chiếu</option>
            <option value="3">Bằng cấp</option>
            <option value="4">Chứng chỉ</option>
            <option value="5">HĐLĐ</option>
            <option value="99">Khác</option>
          </Select>
        </FormField>
        <FormField label="Tên file *">
          <Input value={form.fileName} onChange={e => setForm({ ...form, fileName: e.target.value })} required maxLength={500} />
        </FormField>
        <FormField label="Đường dẫn file *">
          <Input value={form.filePath} onChange={e => setForm({ ...form, filePath: e.target.value })} required maxLength={1000} />
        </FormField>
        <FormField label="Content-Type *">
          <Input value={form.contentType} onChange={e => setForm({ ...form, contentType: e.target.value })} required maxLength={100} />
        </FormField>
        <FormField label="Kích thước (bytes)">
          <Input type="number" min={0} value={form.fileSize} onChange={e => setForm({ ...form, fileSize: e.target.value })} />
        </FormField>
        <FormField label="Ngày cấp">
          <Input type="date" value={form.issueDate} onChange={e => setForm({ ...form, issueDate: e.target.value })} />
        </FormField>
        <FormField label="Ngày hết hạn">
          <Input type="date" value={form.expiryDate} onChange={e => setForm({ ...form, expiryDate: e.target.value })} />
        </FormField>
      </Grid2>
      <FormField label="Ghi chú">
        <Textarea value={form.notes} onChange={e => setForm({ ...form, notes: e.target.value })} maxLength={1000} rows={2} />
      </FormField>
      <FormFooter onCancel={onCancel} isPending={isPending} isEdit={!!initial} />
    </form>
  )
}

// ===================== Form + layout helpers =====================

function FormField({ label, children }: { label: string; children: React.ReactNode }) {
  return (
    <div>
      <label className="mb-1 block text-xs font-medium text-slate-700">{label}</label>
      {children}
    </div>
  )
}

function FormFooter({ onCancel, isPending, isEdit }: { onCancel: () => void; isPending: boolean; isEdit: boolean }) {
  return (
    <div className="flex justify-end gap-2 border-t border-brand-100 pt-2">
      <Button type="button" variant="outline" size="sm" onClick={onCancel} disabled={isPending}>Huỷ</Button>
      <Button type="submit" size="sm" disabled={isPending}>
        {isPending ? 'Đang lưu...' : (isEdit ? 'Cập nhật' : 'Thêm')}
      </Button>
    </div>
  )
}

function RowActions({ onEdit, onDelete }: { onEdit: () => void; onDelete: () => void }) {
  return (
    <div className="absolute right-2 top-2 flex gap-1">
      <button
        type="button"
        onClick={onEdit}
        className="rounded p-1 text-slate-400 transition hover:bg-brand-50 hover:text-brand-600"
        title="Sửa"
      >
        <Pencil className="h-3.5 w-3.5" />
      </button>
      <button
        type="button"
        onClick={onDelete}
        className="rounded p-1 text-slate-400 transition hover:bg-red-50 hover:text-red-600"
        title="Xoá"
      >
        <Trash2 className="h-3.5 w-3.5" />
      </button>
    </div>
  )
}

// Card = section container for the tab body (replaces the old <details> Section).
// việc 2+3: nhận accent → icon-chip nền màu nhạt + chữ đậm, heading màu đậm, rail trái.
function Card({ title, icon: Icon, count, action, accent = 'brand', children }: {
  title: string
  icon: typeof IdCard
  count?: number
  action?: React.ReactNode
  accent?: Accent
  children: React.ReactNode
}) {
  const a = ACCENT[accent]
  return (
    <section
      className={cn(
        'relative overflow-hidden rounded-xl border border-slate-200 bg-white shadow-sm',
        // colored left rail (pseudo-element clips to the rounded corner cleanly)
        "before:absolute before:inset-y-0 before:left-0 before:w-1 before:content-['']", a.rail,
      )}
    >
      <header className="flex items-center justify-between gap-2 border-b border-slate-100 px-4 py-2.5 pl-5">
        <div className="flex items-center gap-2">
          <span
            className="icon-chip"
            style={{ height: '1.75rem', width: '1.75rem', ['--chip-bg' as string]: a.chipBg, ['--chip-fg' as string]: a.chipFg }}
          >
            <Icon className="h-4 w-4" />
          </span>
          <h3 className={cn('text-sm font-semibold tracking-tight', a.head)}>{title}</h3>
          {count != null && count > 0 && (
            <span className="rounded-full bg-slate-100 px-1.5 py-0.5 text-[10px] font-semibold tabular-nums text-slate-500">{count}</span>
          )}
        </div>
        {action}
      </header>
      <div className="p-4 pl-5">{children}</div>
    </section>
  )
}

function SubLabel({ children, accent = 'brand' }: { children: React.ReactNode; accent?: Accent }) {
  return <div className={cn('mb-1 mt-3 text-xs font-semibold uppercase tracking-wide', ACCENT[accent].labelText)}>{children}</div>
}

function Grid2({ children }: { children: React.ReactNode }) {
  return <div className="grid grid-cols-1 gap-x-4 gap-y-2.5 sm:grid-cols-2">{children}</div>
}

// Field — nhãn uppercase brand/accent-tint (việc 3), value đậm rõ. Empty = dấu —.
function Field({ label, value, mono, icon: Icon, full, accent = 'brand' }: {
  label: string
  value: string | number | null
  mono?: boolean
  icon?: typeof Phone
  full?: boolean
  accent?: Accent
}) {
  const empty = value == null || value === ''
  return (
    <div className={cn('min-w-0 text-sm', full && 'sm:col-span-2')}>
      <div className={cn('flex items-center gap-1 text-[11px] font-semibold uppercase tracking-wide', ACCENT[accent].labelText)}>
        {Icon && <Icon className="h-3 w-3" />}
        {label}
      </div>
      <div className={cn('mt-0.5 break-words text-sm', empty ? 'text-slate-300' : 'font-medium text-brand-800', mono && !empty && 'font-mono')}>
        {empty ? '—' : value}
      </div>
    </div>
  )
}

function EmptyHint({ text }: { text: string }) {
  return <div className="py-4 text-center text-sm text-slate-400">{text}</div>
}
