// Tab "Chi tiết" — hiện table line items theo loại HĐ (7 schema khác nhau,
// auto pick render component theo bundle.type). Add row form ở footer (chỉ
// khi Phase=DangSoanThao và user là drafter — owner mới được edit details).
import { useEffect, useMemo, useState } from 'react'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { Pencil, Plus, Trash2 } from 'lucide-react'
import { toast } from 'sonner'
import { Button } from '@/components/ui/Button'
import { Input } from '@/components/ui/Input'
import { Dialog } from '@/components/ui/Dialog'
import { api } from '@/lib/api'
import { getErrorMessage } from '@/lib/apiError'
import { ContractPhase, type ContractDetail } from '@/types/contracts'
import type {
  ContractDetailsBundle,
  ThauPhuDetail,
  GiaoKhoanDetail,
  NhaCungCapDetail,
  DichVuDetail,
  MuaBanDetail,
  NguyenTacNccDetail,
  NguyenTacDvDetail,
} from '@/types/contract-details'

// Generic shape của 1 row đang edit (parent state). Sub-tables type-narrow
// qua bundle.type khi dispatch onEdit.
type EditTarget = { row: Record<string, unknown> }

const fmtMoney = (v: number) => v.toLocaleString('vi-VN')

// Map ContractType → URL slug + render config
type TypeKey = 'thau-phu' | 'giao-khoan' | 'nha-cung-cap' | 'dich-vu' | 'mua-ban' | 'nguyen-tac-ncc' | 'nguyen-tac-dv'
const TYPE_TO_SLUG: Record<number, TypeKey> = {
  1: 'thau-phu',
  2: 'giao-khoan',
  3: 'nha-cung-cap',
  4: 'dich-vu',
  5: 'mua-ban',
  6: 'nguyen-tac-ncc',
  7: 'nguyen-tac-dv',
}

export function ContractDetailsTab({ contract }: { contract: ContractDetail }) {
  const qc = useQueryClient()
  const canEdit = contract.phase === ContractPhase.DangSoanThao
  const [editTarget, setEditTarget] = useState<EditTarget | null>(null)

  const bundleQuery = useQuery({
    queryKey: ['contract-details', contract.id],
    queryFn: async () => (await api.get<ContractDetailsBundle>(`/contracts/${contract.id}/details`)).data,
  })

  function invalidate() {
    qc.invalidateQueries({ queryKey: ['contract-details', contract.id] })
    qc.invalidateQueries({ queryKey: ['contract-changelogs', contract.id] })
  }

  const deleteRow = useMutation({
    mutationFn: async (detailId: string) => {
      await api.delete(`/contracts/${contract.id}/details/${detailId}`)
    },
    onSuccess: () => { invalidate(); toast.success('Đã xóa') },
    onError: err => toast.error(getErrorMessage(err)),
  })

  if (bundleQuery.isLoading) return <div className="text-sm text-slate-500">Đang tải chi tiết…</div>
  if (!bundleQuery.data) return <div className="text-sm text-slate-500">Không có chi tiết.</div>

  const bundle = bundleQuery.data

  const onEdit = canEdit
    ? (row: Record<string, unknown>) => setEditTarget({ row })
    : undefined

  return (
    <div className="space-y-3">
      {bundle.type === 1 && <ThauPhuTable rows={bundle.thauPhu} onDelete={deleteRow.mutate} onEdit={onEdit} canEdit={canEdit} />}
      {bundle.type === 2 && <GiaoKhoanTable rows={bundle.giaoKhoan} onDelete={deleteRow.mutate} onEdit={onEdit} canEdit={canEdit} />}
      {bundle.type === 3 && <NhaCungCapTable rows={bundle.nhaCungCap} onDelete={deleteRow.mutate} onEdit={onEdit} canEdit={canEdit} />}
      {bundle.type === 4 && <DichVuTable rows={bundle.dichVu} onDelete={deleteRow.mutate} onEdit={onEdit} canEdit={canEdit} />}
      {bundle.type === 5 && <MuaBanTable rows={bundle.muaBan} onDelete={deleteRow.mutate} onEdit={onEdit} canEdit={canEdit} />}
      {bundle.type === 6 && <NguyenTacNccTable rows={bundle.nguyenTacNcc} onDelete={deleteRow.mutate} onEdit={onEdit} canEdit={canEdit} />}
      {bundle.type === 7 && <NguyenTacDvTable rows={bundle.nguyenTacDv} onDelete={deleteRow.mutate} onEdit={onEdit} canEdit={canEdit} />}

      {canEdit && (
        <AddRowForm
          contractId={contract.id}
          contractType={contract.type}
          existingCount={getRowCount(bundle)}
          onAdded={invalidate}
        />
      )}

      {!canEdit && (
        <div className="rounded-md border border-amber-200 bg-amber-50 px-3 py-2 text-xs text-amber-700">
          ⚠ Chỉ sửa được chi tiết khi HĐ ở phase "Đang soạn thảo". Hiện tại HĐ đã chuyển sang phase khác.
        </div>
      )}

      <EditRowDialog
        target={editTarget}
        contractId={contract.id}
        contractType={contract.type}
        onClose={() => setEditTarget(null)}
        onSaved={() => { invalidate(); setEditTarget(null) }}
      />
    </div>
  )
}

function getRowCount(bundle: ContractDetailsBundle): number {
  return (
    bundle.thauPhu.length + bundle.giaoKhoan.length + bundle.nhaCungCap.length +
    bundle.dichVu.length + bundle.muaBan.length + bundle.nguyenTacNcc.length +
    bundle.nguyenTacDv.length
  )
}

// ===== Per-type table renderers (gộp 1 file để dễ maintain) =====

function TableShell({ headers, totalRow, children }: { headers: string[]; totalRow?: React.ReactNode; children: React.ReactNode }) {
  return (
    <div className="overflow-x-auto rounded-lg border border-slate-200">
      <table className="min-w-full text-sm">
        <thead className="bg-slate-50 text-[11px] uppercase tracking-wider text-slate-500">
          <tr>
            <th className="w-10 px-2 py-2 text-left">#</th>
            {headers.map(h => <th key={h} className="px-2 py-2 text-left">{h}</th>)}
            <th className="w-10 px-2 py-2"></th>
          </tr>
        </thead>
        <tbody className="divide-y divide-slate-100">
          {children}
        </tbody>
        {totalRow}
      </table>
    </div>
  )
}

function ActionBtns({ onEdit, onDelete }: { onEdit?: () => void; onDelete: () => void }) {
  return (
    <div className="flex justify-end gap-0.5">
      {onEdit && (
        <button
          onClick={onEdit}
          className="rounded p-0.5 text-slate-400 hover:bg-slate-100 hover:text-brand-600"
          aria-label="Sửa"
          title="Sửa dòng"
        >
          <Pencil className="h-3.5 w-3.5" />
        </button>
      )}
      <button
        onClick={() => { if (confirm('Xóa dòng này?')) onDelete() }}
        className="rounded p-0.5 text-slate-400 hover:bg-slate-100 hover:text-red-600"
        aria-label="Xóa"
        title="Xóa dòng"
      >
        <Trash2 className="h-3.5 w-3.5" />
      </button>
    </div>
  )
}

function totalOf(rows: { thanhTien: number }[]): number {
  return rows.reduce((s, r) => s + (r.thanhTien ?? 0), 0)
}

function ThauPhuTable({ rows, onDelete, onEdit, canEdit }: { rows: ThauPhuDetail[]; onDelete: (id: string) => void; onEdit?: (row: Record<string, unknown>) => void; canEdit: boolean }) {
  return (
    <TableShell
      headers={['Hạng mục', 'ĐVT', 'Khối lượng', 'Đơn giá', 'Thành tiền', 'Hoàn thành', 'Ghi chú']}
      totalRow={rows.length > 0 ? <tfoot className="bg-slate-50"><tr><td colSpan={5} className="px-2 py-2 text-right text-xs font-semibold">Tổng:</td><td className="px-2 py-2 font-semibold text-brand-700">{fmtMoney(totalOf(rows))}</td><td colSpan={3} /></tr></tfoot> : undefined}
    >
      {rows.length === 0 && <tr><td colSpan={9} className="px-3 py-6 text-center text-xs text-slate-400">Chưa có hạng mục.</td></tr>}
      {rows.map((r, i) => (
        <tr key={r.id} className="hover:bg-slate-50">
          <td className="px-2 py-1.5 text-xs text-slate-500">{i + 1}</td>
          <td className="px-2 py-1.5">{r.hangMuc}</td>
          <td className="px-2 py-1.5 text-xs">{r.donViTinh}</td>
          <td className="px-2 py-1.5 text-right">{fmtMoney(r.khoiLuong)}</td>
          <td className="px-2 py-1.5 text-right">{fmtMoney(r.donGia)}</td>
          <td className="px-2 py-1.5 text-right font-medium">{fmtMoney(r.thanhTien)}</td>
          <td className="px-2 py-1.5 text-xs text-slate-500">{r.thoiGianHoanThanh ? new Date(r.thoiGianHoanThanh).toLocaleDateString('vi-VN') : '—'}</td>
          <td className="px-2 py-1.5 text-xs text-slate-500">{r.ghiChu ?? ''}</td>
          <td className="px-2 py-1.5">{canEdit && <ActionBtns onEdit={onEdit ? () => onEdit(r as unknown as Record<string, unknown>) : undefined} onDelete={() => onDelete(r.id)} />}</td>
        </tr>
      ))}
    </TableShell>
  )
}

function GiaoKhoanTable({ rows, onDelete, onEdit, canEdit }: { rows: GiaoKhoanDetail[]; onDelete: (id: string) => void; onEdit?: (row: Record<string, unknown>) => void; canEdit: boolean }) {
  return (
    <TableShell
      headers={['Mã CV', 'Tên công việc', 'ĐVT', 'KL', 'Đơn giá', 'Thành tiền', 'Hoàn thành']}
      totalRow={rows.length > 0 ? <tfoot className="bg-slate-50"><tr><td colSpan={6} className="px-2 py-2 text-right text-xs font-semibold">Tổng:</td><td className="px-2 py-2 font-semibold text-brand-700">{fmtMoney(totalOf(rows))}</td><td colSpan={2} /></tr></tfoot> : undefined}
    >
      {rows.length === 0 && <tr><td colSpan={9} className="px-3 py-6 text-center text-xs text-slate-400">Chưa có công việc.</td></tr>}
      {rows.map((r, i) => (
        <tr key={r.id} className="hover:bg-slate-50">
          <td className="px-2 py-1.5 text-xs text-slate-500">{i + 1}</td>
          <td className="px-2 py-1.5 font-mono text-xs">{r.maCongViec}</td>
          <td className="px-2 py-1.5">{r.tenCongViec}</td>
          <td className="px-2 py-1.5 text-xs">{r.donViTinh}</td>
          <td className="px-2 py-1.5 text-right">{fmtMoney(r.khoiLuong)}</td>
          <td className="px-2 py-1.5 text-right">{fmtMoney(r.donGia)}</td>
          <td className="px-2 py-1.5 text-right font-medium">{fmtMoney(r.thanhTien)}</td>
          <td className="px-2 py-1.5 text-xs text-slate-500">{r.thoiGianHoanThanh ? new Date(r.thoiGianHoanThanh).toLocaleDateString('vi-VN') : '—'}</td>
          <td className="px-2 py-1.5">{canEdit && <ActionBtns onEdit={onEdit ? () => onEdit(r as unknown as Record<string, unknown>) : undefined} onDelete={() => onDelete(r.id)} />}</td>
        </tr>
      ))}
    </TableShell>
  )
}

function NhaCungCapTable({ rows, onDelete, onEdit, canEdit }: { rows: NhaCungCapDetail[]; onDelete: (id: string) => void; onEdit?: (row: Record<string, unknown>) => void; canEdit: boolean }) {
  return (
    <TableShell
      headers={['Mã SP', 'Tên SP', 'ĐVT', 'SL', 'Đơn giá', 'Thành tiền', 'Giao hàng']}
      totalRow={rows.length > 0 ? <tfoot className="bg-slate-50"><tr><td colSpan={6} className="px-2 py-2 text-right text-xs font-semibold">Tổng:</td><td className="px-2 py-2 font-semibold text-brand-700">{fmtMoney(totalOf(rows))}</td><td colSpan={2} /></tr></tfoot> : undefined}
    >
      {rows.length === 0 && <tr><td colSpan={9} className="px-3 py-6 text-center text-xs text-slate-400">Chưa có sản phẩm.</td></tr>}
      {rows.map((r, i) => (
        <tr key={r.id} className="hover:bg-slate-50">
          <td className="px-2 py-1.5 text-xs text-slate-500">{i + 1}</td>
          <td className="px-2 py-1.5 font-mono text-xs">{r.maSP}</td>
          <td className="px-2 py-1.5">{r.tenSP}</td>
          <td className="px-2 py-1.5 text-xs">{r.donViTinh}</td>
          <td className="px-2 py-1.5 text-right">{fmtMoney(r.soLuong)}</td>
          <td className="px-2 py-1.5 text-right">{fmtMoney(r.donGia)}</td>
          <td className="px-2 py-1.5 text-right font-medium">{fmtMoney(r.thanhTien)}</td>
          <td className="px-2 py-1.5 text-xs text-slate-500">{r.thoiGianGiao ? new Date(r.thoiGianGiao).toLocaleDateString('vi-VN') : '—'}</td>
          <td className="px-2 py-1.5">{canEdit && <ActionBtns onEdit={onEdit ? () => onEdit(r as unknown as Record<string, unknown>) : undefined} onDelete={() => onDelete(r.id)} />}</td>
        </tr>
      ))}
    </TableShell>
  )
}

function DichVuTable({ rows, onDelete, onEdit, canEdit }: { rows: DichVuDetail[]; onDelete: (id: string) => void; onEdit?: (row: Record<string, unknown>) => void; canEdit: boolean }) {
  return (
    <TableShell
      headers={['Mã DV', 'Tên DV', 'ĐVT', 'Thời gian', 'Đơn giá', 'Thành tiền']}
      totalRow={rows.length > 0 ? <tfoot className="bg-slate-50"><tr><td colSpan={5} className="px-2 py-2 text-right text-xs font-semibold">Tổng:</td><td className="px-2 py-2 font-semibold text-brand-700">{fmtMoney(totalOf(rows))}</td><td colSpan={2} /></tr></tfoot> : undefined}
    >
      {rows.length === 0 && <tr><td colSpan={8} className="px-3 py-6 text-center text-xs text-slate-400">Chưa có dịch vụ.</td></tr>}
      {rows.map((r, i) => (
        <tr key={r.id} className="hover:bg-slate-50">
          <td className="px-2 py-1.5 text-xs text-slate-500">{i + 1}</td>
          <td className="px-2 py-1.5 font-mono text-xs">{r.maDichVu}</td>
          <td className="px-2 py-1.5">{r.tenDichVu}</td>
          <td className="px-2 py-1.5 text-xs">{r.donViTinh}</td>
          <td className="px-2 py-1.5 text-right">{fmtMoney(r.thoiGian)}</td>
          <td className="px-2 py-1.5 text-right">{fmtMoney(r.donGia)}</td>
          <td className="px-2 py-1.5 text-right font-medium">{fmtMoney(r.thanhTien)}</td>
          <td className="px-2 py-1.5">{canEdit && <ActionBtns onEdit={onEdit ? () => onEdit(r as unknown as Record<string, unknown>) : undefined} onDelete={() => onDelete(r.id)} />}</td>
        </tr>
      ))}
    </TableShell>
  )
}

function MuaBanTable({ rows, onDelete, onEdit, canEdit }: { rows: MuaBanDetail[]; onDelete: (id: string) => void; onEdit?: (row: Record<string, unknown>) => void; canEdit: boolean }) {
  return (
    <TableShell
      headers={['Mã SP', 'Tên SP', 'ĐVT', 'SL', 'Đơn giá', 'VAT (%)', 'Thành tiền']}
      totalRow={rows.length > 0 ? <tfoot className="bg-slate-50"><tr><td colSpan={7} className="px-2 py-2 text-right text-xs font-semibold">Tổng:</td><td className="px-2 py-2 font-semibold text-brand-700">{fmtMoney(totalOf(rows))}</td><td /></tr></tfoot> : undefined}
    >
      {rows.length === 0 && <tr><td colSpan={9} className="px-3 py-6 text-center text-xs text-slate-400">Chưa có sản phẩm.</td></tr>}
      {rows.map((r, i) => (
        <tr key={r.id} className="hover:bg-slate-50">
          <td className="px-2 py-1.5 text-xs text-slate-500">{i + 1}</td>
          <td className="px-2 py-1.5 font-mono text-xs">{r.maSP}</td>
          <td className="px-2 py-1.5">{r.tenSP}</td>
          <td className="px-2 py-1.5 text-xs">{r.donViTinh}</td>
          <td className="px-2 py-1.5 text-right">{fmtMoney(r.soLuong)}</td>
          <td className="px-2 py-1.5 text-right">{fmtMoney(r.donGia)}</td>
          <td className="px-2 py-1.5 text-right text-xs">{r.thueVAT}%</td>
          <td className="px-2 py-1.5 text-right font-medium">{fmtMoney(r.thanhTien)}</td>
          <td className="px-2 py-1.5">{canEdit && <ActionBtns onEdit={onEdit ? () => onEdit(r as unknown as Record<string, unknown>) : undefined} onDelete={() => onDelete(r.id)} />}</td>
        </tr>
      ))}
    </TableShell>
  )
}

function NguyenTacNccTable({ rows, onDelete, onEdit, canEdit }: { rows: NguyenTacNccDetail[]; onDelete: (id: string) => void; onEdit?: (row: Record<string, unknown>) => void; canEdit: boolean }) {
  return (
    <TableShell headers={['Nhóm SP', 'Tên SP', 'ĐVT', 'Giá min', 'Giá max', 'Điều kiện thanh toán']}>
      {rows.length === 0 && <tr><td colSpan={8} className="px-3 py-6 text-center text-xs text-slate-400">Chưa có SP.</td></tr>}
      {rows.map((r, i) => (
        <tr key={r.id} className="hover:bg-slate-50">
          <td className="px-2 py-1.5 text-xs text-slate-500">{i + 1}</td>
          <td className="px-2 py-1.5">{r.nhomSP}</td>
          <td className="px-2 py-1.5">{r.tenSP}</td>
          <td className="px-2 py-1.5 text-xs">{r.donViTinh}</td>
          <td className="px-2 py-1.5 text-right">{fmtMoney(r.donGiaToiThieu)}</td>
          <td className="px-2 py-1.5 text-right">{fmtMoney(r.donGiaToiDa)}</td>
          <td className="px-2 py-1.5 text-xs text-slate-500">{r.dieuKienThanhToan ?? '—'}</td>
          <td className="px-2 py-1.5">{canEdit && <ActionBtns onEdit={onEdit ? () => onEdit(r as unknown as Record<string, unknown>) : undefined} onDelete={() => onDelete(r.id)} />}</td>
        </tr>
      ))}
    </TableShell>
  )
}

function NguyenTacDvTable({ rows, onDelete, onEdit, canEdit }: { rows: NguyenTacDvDetail[]; onDelete: (id: string) => void; onEdit?: (row: Record<string, unknown>) => void; canEdit: boolean }) {
  return (
    <TableShell headers={['Loại DV', 'Tên DV', 'ĐVT', 'Giá min', 'Giá max', 'SLA']}>
      {rows.length === 0 && <tr><td colSpan={8} className="px-3 py-6 text-center text-xs text-slate-400">Chưa có DV.</td></tr>}
      {rows.map((r, i) => (
        <tr key={r.id} className="hover:bg-slate-50">
          <td className="px-2 py-1.5 text-xs text-slate-500">{i + 1}</td>
          <td className="px-2 py-1.5">{r.loaiDichVu}</td>
          <td className="px-2 py-1.5">{r.tenDichVu}</td>
          <td className="px-2 py-1.5 text-xs">{r.donViTinh}</td>
          <td className="px-2 py-1.5 text-right">{fmtMoney(r.donGiaToiThieu)}</td>
          <td className="px-2 py-1.5 text-right">{fmtMoney(r.donGiaToiDa)}</td>
          <td className="px-2 py-1.5 text-xs text-slate-500">{r.sla ?? '—'}</td>
          <td className="px-2 py-1.5">{canEdit && <ActionBtns onEdit={onEdit ? () => onEdit(r as unknown as Record<string, unknown>) : undefined} onDelete={() => onDelete(r.id)} />}</td>
        </tr>
      ))}
    </TableShell>
  )
}

// ===== Add row form — minimal: chỉ field bắt buộc, advanced edit qua FE
// fullpage form sau (Iter 2). Hiện tại hỗ trợ quick-add 5-7 field per type.

function AddRowForm({
  contractId, contractType, existingCount, onAdded,
}: {
  contractId: string
  contractType: number
  existingCount: number
  onAdded: () => void
}) {
  const [open, setOpen] = useState(false)
  const slug = useMemo(() => TYPE_TO_SLUG[contractType], [contractType])

  if (!slug) return null

  return (
    <div>
      {!open && (
        <Button variant="outline" onClick={() => setOpen(true)}>
          <Plus className="h-4 w-4" />
          Thêm dòng
        </Button>
      )}
      {open && (
        <AddRowFields
          contractId={contractId}
          slug={slug}
          contractType={contractType}
          nextOrder={existingCount + 1}
          onCancel={() => setOpen(false)}
          onAdded={() => { setOpen(false); onAdded() }}
        />
      )}
    </div>
  )
}

function AddRowFields({
  contractId, slug, contractType, nextOrder, onCancel, onAdded,
}: {
  contractId: string
  slug: TypeKey
  contractType: number
  nextOrder: number
  onCancel: () => void
  onAdded: () => void
}) {
  const [form, setForm] = useState<Record<string, string>>({})

  // Load 4 catalogs cho datalist autocomplete (1 lần, cache TanStack)
  const units = useQuery({
    queryKey: ['catalogs', 'units'],
    queryFn: async () => (await api.get<CatalogItem[]>('/catalogs/units')).data,
  })
  const materials = useQuery({
    queryKey: ['catalogs', 'materials'],
    queryFn: async () => (await api.get<CatalogItem[]>('/catalogs/materials')).data,
  })
  const services = useQuery({
    queryKey: ['catalogs', 'services'],
    queryFn: async () => (await api.get<CatalogItem[]>('/catalogs/services')).data,
  })
  const workItems = useQuery({
    queryKey: ['catalogs', 'work-items'],
    queryFn: async () => (await api.get<CatalogItem[]>('/catalogs/work-items')).data,
  })

  const catalogData: Record<NonNullable<FieldDef['datalist']>, CatalogItem[]> = {
    units: units.data ?? [],
    materials: materials.data ?? [],
    services: services.data ?? [],
    'work-items': workItems.data ?? [],
  }

  const submit = useMutation({
    mutationFn: async () => {
      const payload = buildPayload(contractType, nextOrder, form)
      await api.post(`/contracts/${contractId}/details/${slug}`, payload)
    },
    onSuccess: () => { toast.success('Đã thêm dòng'); onAdded() },
    onError: err => toast.error(getErrorMessage(err)),
  })

  const fields = FIELDS_BY_TYPE[contractType] ?? []

  // Smart-fill: khi user pick value khớp catalog item, autofill các field
  // liên quan (defaultUnit cho donViTinh, name cho codeField siblings).
  function handleFieldChange(name: string, value: string) {
    setForm(s => {
      const next = { ...s, [name]: value }
      const fieldDef = fields.find(f => f.name === name)
      if (!fieldDef?.datalist) return next

      const items = catalogData[fieldDef.datalist]
      // Match theo `code` hoặc `name` (user có thể type either)
      const match = items.find(it => it.code === value || it.name === value)
      if (!match) return next

      // Auto-fill sibling fields nếu trống
      // - Nếu user pick code → fill name (sibling field same datalist)
      // - Nếu sibling field name 'donViTinh' chưa có giá trị → fill defaultUnit
      for (const sibling of fields) {
        if (sibling.name === name) continue
        if (sibling.datalist === fieldDef.datalist && !next[sibling.name]) {
          // Sibling cùng catalog — fill code/name correlate
          if (sibling.name.startsWith('ma') || sibling.name === 'maSP' || sibling.name === 'maCongViec' || sibling.name === 'maDichVu') {
            next[sibling.name] = match.code
          } else if (sibling.name.startsWith('ten') || sibling.name === 'tenSP' || sibling.name === 'hangMuc' || sibling.name === 'tenCongViec' || sibling.name === 'tenDichVu') {
            next[sibling.name] = match.name
          }
        }
        if (sibling.name === 'donViTinh' && !next.donViTinh && match.defaultUnit) {
          next.donViTinh = match.defaultUnit
        }
      }
      return next
    })
  }

  return (
    <form
      onSubmit={e => { e.preventDefault(); submit.mutate() }}
      className="space-y-2 rounded-lg border border-brand-200 bg-brand-50/30 p-3"
    >
      <div className="grid grid-cols-2 gap-2 md:grid-cols-3 lg:grid-cols-4">
        {fields.map(f => {
          const datalistId = f.datalist ? `dl-${f.datalist}-${f.name}` : undefined
          const items = f.datalist ? catalogData[f.datalist] : []
          return (
            <div key={f.name} className="space-y-1">
              <label className="text-[11px] font-medium text-slate-600">{f.label}</label>
              <Input
                type={f.type === 'number' ? 'number' : f.type === 'date' ? 'date' : 'text'}
                value={form[f.name] ?? ''}
                onChange={e => handleFieldChange(f.name, e.target.value)}
                placeholder={f.placeholder}
                step={f.type === 'number' ? 'any' : undefined}
                required={f.required}
                className="text-xs"
                list={datalistId}
              />
              {datalistId && items.length > 0 && (
                <datalist id={datalistId}>
                  {items.map(it => (
                    <option key={it.id} value={f.datalistField === 'code' ? it.code : it.name}>
                      {f.datalistField === 'code' ? it.name : it.code}
                    </option>
                  ))}
                </datalist>
              )}
            </div>
          )
        })}
      </div>
      <div className="flex justify-end gap-2">
        <Button type="button" variant="outline" onClick={onCancel}>Hủy</Button>
        <Button type="submit" disabled={submit.isPending}>
          {submit.isPending ? 'Đang thêm…' : 'Thêm'}
        </Button>
      </div>
    </form>
  )
}

type CatalogItem = {
  id: string
  code: string
  name: string
  defaultUnit?: string | null
  category?: string | null
}

type FieldDef = {
  name: string
  label: string
  type: 'text' | 'number' | 'date'
  required?: boolean
  placeholder?: string
  /** Catalog source cho datalist autocomplete */
  datalist?: 'units' | 'materials' | 'services' | 'work-items'
  /** Field nào của catalog item là value: 'code' hoặc 'name' (default: 'name') */
  datalistField?: 'code' | 'name'
}

// Per-type field config + datalist source. User type/pick → smart-fill sibling
// fields qua handleFieldChange (vd pick MaSP từ materials → autofill TenSP +
// donViTinh từ defaultUnit).
const FIELDS_BY_TYPE: Record<number, FieldDef[]> = {
  1: [ // ThauPhu — autocomplete WorkItems + Units
    { name: 'hangMuc', label: 'Hạng mục *', type: 'text', required: true, datalist: 'work-items', datalistField: 'name' },
    { name: 'donViTinh', label: 'ĐVT *', type: 'text', required: true, placeholder: 'm2, kg...', datalist: 'units', datalistField: 'code' },
    { name: 'khoiLuong', label: 'Khối lượng *', type: 'number', required: true },
    { name: 'donGia', label: 'Đơn giá *', type: 'number', required: true },
    { name: 'thoiGianHoanThanh', label: 'Hoàn thành', type: 'date' },
    { name: 'ghiChu', label: 'Ghi chú', type: 'text' },
  ],
  2: [ // GiaoKhoan — autocomplete WorkItems + Units
    { name: 'maCongViec', label: 'Mã CV *', type: 'text', required: true, datalist: 'work-items', datalistField: 'code' },
    { name: 'tenCongViec', label: 'Tên công việc *', type: 'text', required: true, datalist: 'work-items', datalistField: 'name' },
    { name: 'donViTinh', label: 'ĐVT *', type: 'text', required: true, datalist: 'units', datalistField: 'code' },
    { name: 'khoiLuong', label: 'KL *', type: 'number', required: true },
    { name: 'donGia', label: 'Đơn giá *', type: 'number', required: true },
    { name: 'thoiGianHoanThanh', label: 'Hoàn thành', type: 'date' },
  ],
  3: [ // NhaCungCap — autocomplete Materials + Units
    { name: 'maSP', label: 'Mã SP *', type: 'text', required: true, datalist: 'materials', datalistField: 'code' },
    { name: 'tenSP', label: 'Tên SP *', type: 'text', required: true, datalist: 'materials', datalistField: 'name' },
    { name: 'donViTinh', label: 'ĐVT *', type: 'text', required: true, datalist: 'units', datalistField: 'code' },
    { name: 'soLuong', label: 'SL *', type: 'number', required: true },
    { name: 'donGia', label: 'Đơn giá *', type: 'number', required: true },
    { name: 'thoiGianGiao', label: 'Giao hàng', type: 'date' },
    { name: 'xuatXu', label: 'Xuất xứ', type: 'text' },
  ],
  4: [ // DichVu — autocomplete Services + Units
    { name: 'maDichVu', label: 'Mã DV *', type: 'text', required: true, datalist: 'services', datalistField: 'code' },
    { name: 'tenDichVu', label: 'Tên DV *', type: 'text', required: true, datalist: 'services', datalistField: 'name' },
    { name: 'donViTinh', label: 'ĐVT *', type: 'text', required: true, datalist: 'units', datalistField: 'code' },
    { name: 'thoiGian', label: 'Thời gian *', type: 'number', required: true },
    { name: 'donGia', label: 'Đơn giá *', type: 'number', required: true },
  ],
  5: [ // MuaBan — autocomplete Materials + Units
    { name: 'maSP', label: 'Mã SP *', type: 'text', required: true, datalist: 'materials', datalistField: 'code' },
    { name: 'tenSP', label: 'Tên SP *', type: 'text', required: true, datalist: 'materials', datalistField: 'name' },
    { name: 'donViTinh', label: 'ĐVT *', type: 'text', required: true, datalist: 'units', datalistField: 'code' },
    { name: 'soLuong', label: 'SL *', type: 'number', required: true },
    { name: 'donGia', label: 'Đơn giá *', type: 'number', required: true },
    { name: 'thueVAT', label: 'VAT (%)', type: 'number', placeholder: '10' },
  ],
  6: [ // NguyenTacNcc — autocomplete Materials + Units
    { name: 'nhomSP', label: 'Nhóm SP *', type: 'text', required: true },
    { name: 'tenSP', label: 'Tên SP *', type: 'text', required: true, datalist: 'materials', datalistField: 'name' },
    { name: 'donViTinh', label: 'ĐVT *', type: 'text', required: true, datalist: 'units', datalistField: 'code' },
    { name: 'donGiaToiThieu', label: 'Giá min *', type: 'number', required: true },
    { name: 'donGiaToiDa', label: 'Giá max *', type: 'number', required: true },
  ],
  7: [ // NguyenTacDv — autocomplete Services + Units
    { name: 'loaiDichVu', label: 'Loại DV *', type: 'text', required: true },
    { name: 'tenDichVu', label: 'Tên DV *', type: 'text', required: true, datalist: 'services', datalistField: 'name' },
    { name: 'donViTinh', label: 'ĐVT *', type: 'text', required: true, datalist: 'units', datalistField: 'code' },
    { name: 'donGiaToiThieu', label: 'Giá min *', type: 'number', required: true },
    { name: 'donGiaToiDa', label: 'Giá max *', type: 'number', required: true },
  ],
}

// Build payload — convert string form values to typed fields BE expects.
// thanhTien auto compute = soLuong * donGia (or khoiLuong * donGia).
function buildPayload(contractType: number, order: number, form: Record<string, string>): Record<string, unknown> {
  const num = (k: string) => Number(form[k] ?? 0)
  const str = (k: string) => form[k] ?? null
  const date = (k: string) => form[k] ? new Date(form[k]).toISOString() : null

  const common = { id: '00000000-0000-0000-0000-000000000000', order, ghiChu: str('ghiChu') }

  switch (contractType) {
    case 1: // ThauPhu
      return { ...common, hangMuc: form.hangMuc, donViTinh: form.donViTinh, khoiLuong: num('khoiLuong'), donGia: num('donGia'), thanhTien: num('khoiLuong') * num('donGia'), thoiGianHoanThanh: date('thoiGianHoanThanh') }
    case 2: // GiaoKhoan
      return { ...common, maCongViec: form.maCongViec, tenCongViec: form.tenCongViec, donViTinh: form.donViTinh, khoiLuong: num('khoiLuong'), donGia: num('donGia'), thanhTien: num('khoiLuong') * num('donGia'), thoiGianHoanThanh: date('thoiGianHoanThanh'), yeuCauKyThuat: str('yeuCauKyThuat') }
    case 3: // NhaCungCap
      return { ...common, maSP: form.maSP, tenSP: form.tenSP, thongSoKyThuat: str('thongSoKyThuat'), donViTinh: form.donViTinh, soLuong: num('soLuong'), donGia: num('donGia'), thanhTien: num('soLuong') * num('donGia'), thoiGianGiao: date('thoiGianGiao'), xuatXu: str('xuatXu') }
    case 4: // DichVu
      return { ...common, maDichVu: form.maDichVu, tenDichVu: form.tenDichVu, moTa: str('moTa'), donViTinh: form.donViTinh, thoiGian: num('thoiGian'), donGia: num('donGia'), thanhTien: num('thoiGian') * num('donGia'), tuNgay: date('tuNgay'), denNgay: date('denNgay') }
    case 5: // MuaBan — thanhTien = SL * DonGia * (1 + VAT/100)
      return { ...common, maSP: form.maSP, tenSP: form.tenSP, moTa: str('moTa'), donViTinh: form.donViTinh, soLuong: num('soLuong'), donGia: num('donGia'), thueVAT: num('thueVAT'), thanhTien: num('soLuong') * num('donGia') * (1 + num('thueVAT') / 100), xuatXu: str('xuatXu') }
    case 6: // NguyenTacNcc
      return { ...common, nhomSP: form.nhomSP, tenSP: form.tenSP, donViTinh: form.donViTinh, donGiaToiThieu: num('donGiaToiThieu'), donGiaToiDa: num('donGiaToiDa'), dieuKienGiaoHang: str('dieuKienGiaoHang'), dieuKienThanhToan: str('dieuKienThanhToan') }
    case 7: // NguyenTacDv
      return { ...common, loaiDichVu: form.loaiDichVu, tenDichVu: form.tenDichVu, donViTinh: form.donViTinh, donGiaToiThieu: num('donGiaToiThieu'), donGiaToiDa: num('donGiaToiDa'), phamViDichVu: str('phamViDichVu'), sla: str('sla') }
  }
  return common
}

// ===== Edit dialog — populated từ row data, PUT thay POST =====

function EditRowDialog({
  target, contractId, contractType, onClose, onSaved,
}: {
  target: { row: Record<string, unknown> } | null
  contractId: string
  contractType: number
  onClose: () => void
  onSaved: () => void
}) {
  const [form, setForm] = useState<Record<string, string>>({})

  // Populate khi target thay đổi (open dialog với row data)
  useEffect(() => {
    if (!target) return
    const init: Record<string, string> = {}
    for (const f of FIELDS_BY_TYPE[contractType] ?? []) {
      const v = target.row[f.name]
      if (v == null) init[f.name] = ''
      else if (f.type === 'date') {
        // ISO string → yyyy-MM-dd cho input[type=date]
        const d = new Date(String(v))
        init[f.name] = isNaN(d.getTime()) ? '' : d.toISOString().slice(0, 10)
      } else {
        init[f.name] = String(v)
      }
    }
    setForm(init)
  }, [target, contractType])

  const submit = useMutation({
    mutationFn: async () => {
      if (!target) return
      const slug = TYPE_TO_SLUG[contractType]
      const detailId = target.row.id as string
      const order = Number(target.row.order ?? 1)
      const payload = buildPayload(contractType, order, form)
      // Patch id field cho BE PUT (URL có detailId nhưng body cũng cần)
      payload.id = detailId
      await api.put(`/contracts/${contractId}/details/${slug}/${detailId}`, payload)
    },
    onSuccess: () => { toast.success('Đã lưu'); onSaved() },
    onError: err => toast.error(getErrorMessage(err)),
  })

  if (!target) return null
  const fields = FIELDS_BY_TYPE[contractType] ?? []

  return (
    <Dialog
      open={!!target}
      onClose={onClose}
      title="Sửa chi tiết"
      size="lg"
      footer={
        <>
          <Button variant="outline" onClick={onClose}>Hủy</Button>
          <Button onClick={() => submit.mutate()} disabled={submit.isPending}>
            {submit.isPending ? 'Đang lưu…' : 'Lưu'}
          </Button>
        </>
      }
    >
      <div className="grid grid-cols-2 gap-3">
        {fields.map(f => (
          <div key={f.name} className="space-y-1">
            <label className="text-[11px] font-medium text-slate-600">{f.label}</label>
            <Input
              type={f.type === 'number' ? 'number' : f.type === 'date' ? 'date' : 'text'}
              value={form[f.name] ?? ''}
              onChange={e => setForm(s => ({ ...s, [f.name]: e.target.value }))}
              placeholder={f.placeholder}
              step={f.type === 'number' ? 'any' : undefined}
              required={f.required}
            />
          </div>
        ))}
      </div>
    </Dialog>
  )
}
