// "Thao tác HĐ" — 2-panel UX cho Ct_*_Create menu. Panel 1 list HĐ theo
// type + nút "Thêm mới" cuối list | Panel 2 form Header + Chi tiết section
// (khi edit mode). Giữ tên file ContractCreatePage để route /contracts/new
// không cần đổi.
//
// URL state:
//   ?type=X         → Panel 2 empty state
//   ?type=X&mode=new → Form trống (create mode)
//   ?type=X&id=abc  → Form populated (edit mode) + Chi tiết
//
// Sau khi tạo xong → redirect URL ?id=newId tự động chuyển edit mode +
// hiển thị Chi tiết section.
import { useState, useMemo, type FormEvent, useEffect } from 'react'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { Link, useSearchParams } from 'react-router-dom'
import { FileText, Plus, Search, Save, Pencil, Trash2, Lock } from 'lucide-react'
import { toast } from 'sonner'
import { ContractDetailsTab } from '@/components/contracts/ContractDetailsTab'
import { PhaseBadge } from '@/components/PhaseBadge'
import { SlaTimer } from '@/components/SlaTimer'
import { EmptyState } from '@/components/EmptyState'
import { Button } from '@/components/ui/Button'
import { Input } from '@/components/ui/Input'
import { Label } from '@/components/ui/Label'
import { Select } from '@/components/ui/Select'
import { Textarea } from '@/components/ui/Textarea'
import { api } from '@/lib/api'
import { getErrorMessage } from '@/lib/apiError'
import { cn } from '@/lib/cn'
import type { Paged, Project, Supplier } from '@/types/master'
import type { ContractTemplate } from '@/types/forms'
import { ContractTypeLabel } from '@/types/forms'
import {
  ContractPhase,
  type ContractDetail,
  type ContractListItem,
} from '@/types/contracts'
// [W5 S187 vế (88)] Nhãn 8 nhóm duyệt KHKK — IMPORT single-source (`types/khkk.ts:140-149`),
// KHÔNG chép chuỗi.
import { KHKK_APPROVAL_GROUP_LABELS } from '@/types/khkk'

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

export function ContractCreatePage() {
  const qc = useQueryClient()
  const [searchParams, setSearchParams] = useSearchParams()
  const typeFilter = searchParams.get('type') ? Number(searchParams.get('type')) : 2
  const selectedId = searchParams.get('id')
  const isNewMode = searchParams.get('mode') === 'new'
  const search = searchParams.get('q') ?? ''

  const list = useQuery({
    queryKey: ['my-contracts', typeFilter],
    queryFn: async () =>
      (await api.get<Paged<ContractListItem>>('/contracts', { params: { page: 1, pageSize: 100 } })).data,
  })

  const deleteContract = useMutation({
    mutationFn: async (id: string) => {
      await api.delete(`/contracts/${id}`)
    },
    onSuccess: (_, deletedId) => {
      toast.success('Đã xóa HĐ')
      qc.invalidateQueries({ queryKey: ['my-contracts'] })
      // Nếu đang edit HĐ vừa xóa → clear selection
      if (selectedId === deletedId) {
        const next = new URLSearchParams(searchParams)
        next.delete('id')
        setSearchParams(next, { replace: true })
      }
    },
    onError: err => toast.error(getErrorMessage(err)),
  })

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

  const rows = useMemo(() => {
    let items = list.data?.items ?? []
    items = items.filter(c => c.type === typeFilter)
    if (search.trim()) {
      const q = search.toLowerCase()
      items = items.filter(c =>
        (c.maHopDong ?? '').toLowerCase().includes(q) ||
        (c.tenHopDong ?? '').toLowerCase().includes(q) ||
        (c.supplierName ?? '').toLowerCase().includes(q),
      )
    }
    return items
  }, [list.data, typeFilter, search])

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

  function selectContract(id: string) {
    const next = new URLSearchParams(searchParams)
    next.set('id', id)
    next.delete('mode')
    setSearchParams(next, { replace: false })
  }

  function startNew() {
    const next = new URLSearchParams(searchParams)
    next.set('mode', 'new')
    next.delete('id')
    setSearchParams(next, { replace: false })
  }

  const typeLabel = ContractTypeLabel[typeFilter] ?? 'HĐ'

  return (
    <div className="flex h-[calc(100vh-4rem)] flex-col">
      <header className="flex shrink-0 flex-wrap items-center justify-between gap-3 border-b border-slate-200 bg-white px-6 py-3">
        <div className="flex items-center gap-2">
          <FileText className="h-5 w-5 text-slate-500" />
          <h1 className="text-base font-semibold tracking-tight text-slate-900">
            Thao tác · {typeLabel}
          </h1>
          <span className="ml-2 rounded-full bg-slate-100 px-2 py-0.5 text-[11px] font-medium text-slate-600">
            {rows.length}
          </span>
        </div>
      </header>

      <div className="grid flex-1 grid-cols-1 overflow-hidden lg:grid-cols-[320px_1fr]">
        {/* Panel 1 — List + Thêm mới button cuối */}
        <aside className="flex flex-col overflow-hidden border-r border-slate-200 bg-white">
          <div className="border-b border-slate-200 p-3">
            <div className="relative">
              <Search className="pointer-events-none absolute left-2.5 top-2.5 h-4 w-4 text-slate-400" />
              <Input
                value={search}
                onChange={e => setParam('q', e.target.value)}
                placeholder="Tìm theo mã / tên / NCC…"
                className="pl-8"
              />
            </div>
          </div>
          <div className="flex-1 overflow-y-auto">
            {list.isLoading && (
              <div className="space-y-2 p-3">
                {Array.from({ length: 4 }).map((_, i) => (
                  <div key={i} className="h-16 animate-pulse rounded-md bg-slate-100" />
                ))}
              </div>
            )}
            {!list.isLoading && rows.length === 0 && (
              <div className="p-6">
                <EmptyState
                  icon={FileText}
                  title="Chưa có HĐ"
                  description="Bấm + Thêm mới phía dưới để tạo HĐ đầu tiên."
                />
              </div>
            )}
            <ul className="divide-y divide-slate-100">
              {rows.map(c => (
                <li key={c.id} className="group relative">
                  <button
                    onClick={() => selectContract(c.id)}
                    className={cn(
                      'block w-full px-3 py-2.5 pr-16 text-left transition hover:bg-slate-50',
                      selectedId === c.id && 'bg-brand-50 ring-1 ring-inset ring-brand-200',
                    )}
                  >
                    <div className="flex items-start justify-between gap-2">
                      <div className="min-w-0 flex-1">
                        <div className="truncate text-[13px] font-medium text-slate-900">
                          {c.tenHopDong ?? '(chưa đặt tên)'}
                        </div>
                        <div className="mt-0.5 flex items-center gap-1.5 text-[11px] text-slate-500">
                          <span className="font-mono">{c.maHopDong ?? '—'}</span>
                          <span>·</span>
                          <span className="truncate">{c.supplierName}</span>
                        </div>
                      </div>
                      <PhaseBadge phase={c.phase} className="shrink-0 text-[10px]" />
                    </div>
                    <div className="mt-1 flex items-center justify-between text-[11px] text-slate-500">
                      <span>{fmtMoney(c.giaTri)}</span>
                      <SlaTimer deadline={c.slaDeadline} createdAt={c.createdAt} />
                    </div>
                  </button>

                  {/* Action buttons — Edit + Xóa luôn hiển thị; mờ + disabled khi
                      Phase != DangSoanThao (BE chỉ cho update/delete khi draft).
                      Sibling không nested để click không trigger row select. */}
                  {(() => {
                    const canMutate = c.phase === ContractPhase.DangSoanThao
                    return (
                      <div className="absolute right-2 top-2 z-10 flex gap-0.5 opacity-60 transition group-hover:opacity-100">
                        <button
                          onClick={() => canMutate && selectContract(c.id)}
                          disabled={!canMutate}
                          title={canMutate ? 'Chỉnh sửa HĐ' : 'Chỉ sửa được khi Phase = Đang soạn thảo'}
                          className={cn(
                            'rounded p-1 transition',
                            canMutate
                              ? 'text-slate-500 hover:bg-white hover:text-brand-600 hover:shadow-sm'
                              : 'cursor-not-allowed text-slate-300',
                          )}
                        >
                          <Pencil className="h-3.5 w-3.5" />
                        </button>
                        <button
                          onClick={() => {
                            if (!canMutate) return
                            if (confirm(`Xóa HĐ "${c.tenHopDong ?? c.maHopDong ?? 'này'}"?`)) {
                              deleteContract.mutate(c.id)
                            }
                          }}
                          disabled={!canMutate || deleteContract.isPending}
                          title={canMutate ? 'Xóa HĐ' : 'Chỉ xóa được khi Phase = Đang soạn thảo'}
                          className={cn(
                            'rounded p-1 transition',
                            canMutate
                              ? 'text-slate-500 hover:bg-white hover:text-red-600 hover:shadow-sm'
                              : 'cursor-not-allowed text-slate-300',
                          )}
                        >
                          <Trash2 className="h-3.5 w-3.5" />
                        </button>
                      </div>
                    )
                  })()}
                </li>
              ))}
            </ul>
          </div>

          {/* + Thêm mới button — sticky cuối Panel 1 */}
          <div className="shrink-0 border-t border-slate-200 bg-white p-3">
            <Button
              onClick={startNew}
              className={cn('w-full justify-center', isNewMode && 'ring-2 ring-brand-300')}
            >
              <Plus className="h-4 w-4" />
              Thêm mới
            </Button>
          </div>
        </aside>

        {/* Panel 2 — Form (new/edit) hoặc empty state */}
        <main className="hidden overflow-y-auto bg-slate-50 lg:block">
          {!isNewMode && !selectedId && (
            <div className="p-6">
              <EmptyState
                icon={FileText}
                title="Chọn 1 HĐ ở danh sách bên trái"
                description="Hoặc bấm + Thêm mới phía dưới list để tạo HĐ mới."
              />
            </div>
          )}
          {isNewMode && (
            <ContractHeaderForm
              key="new"
              defaultType={typeFilter}
              onCreated={(newId) => {
                // Sau khi tạo: refresh list + chuyển sang edit mode để user nhập Chi tiết
                const next = new URLSearchParams(searchParams)
                next.delete('mode')
                next.set('id', newId)
                setSearchParams(next, { replace: true })
              }}
            />
          )}
          {!isNewMode && selectedId && detail.data && (
            <ContractEditForm
              key={selectedId}
              contract={detail.data}
              onSaved={() => {
                /* mutation tự invalidate */
              }}
            />
          )}
          {!isNewMode && selectedId && detail.isLoading && (
            <div className="p-6 text-sm text-slate-500">Đang tải HĐ…</div>
          )}
        </main>
      </div>
    </div>
  )
}

// ===== Form components =====

function ContractHeaderForm({
  defaultType,
  onCreated,
}: {
  defaultType: number
  onCreated: (newId: string) => void
}) {
  const [type, setType] = useState(defaultType)
  const [supplierId, setSupplierId] = useState('')
  const [projectId, setProjectId] = useState('')
  const [templateId, setTemplateId] = useState('')
  const [giaTri, setGiaTri] = useState('')
  const [tenHopDong, setTenHopDong] = useState('')
  const [noiDung, setNoiDung] = useState('')
  const [bypass, setBypass] = useState(false)
  // [S61 Mig 50] Module Budget cũ XÓA — HĐ GIỮ ngân sách nhập tay (Tên + Số tiền),
  // chỉ bỏ chế độ link Budget entity.
  const [budgetManualName, setBudgetManualName] = useState('')
  const [budgetManualAmount, setBudgetManualAmount] = useState(0)
  // [Plan B S29 Chunk D 2026-05-22 Mig 32] V2 workflow pin lúc create — mirror
  // PE PeWorkspaceCreateView pattern. Drafter pick V2 workflow IsUserSelectable
  // filter ApplicableType=Contract(3). Nếu blank → BE fallback V1 auto pick
  // (7 prod contract giữ behavior cũ).
  const [approvalWorkflowId, setApprovalWorkflowId] = useState('')

  // Reset type về default khi typeFilter (parent prop) thay đổi
  useEffect(() => { setType(defaultType) }, [defaultType])

  const suppliers = useQuery({
    queryKey: ['suppliers-all'],
    queryFn: async () => (await api.get<Paged<Supplier>>('/suppliers', { params: { page: 1, pageSize: 200, published: true } })).data.items, // S113 R4: chỉ NCC đã công bố (ẩn nháp → mã HĐ không dính Code rỗng)
  })
  const projects = useQuery({
    queryKey: ['projects-all'],
    queryFn: async () => (await api.get<Paged<Project>>('/projects', { params: { page: 1, pageSize: 200 } })).data.items,
  })
  const templates = useQuery({
    queryKey: ['templates-by-type', type],
    queryFn: async () => (await api.get<ContractTemplate[]>('/forms/templates', { params: { type } })).data,
  })
  // [Plan B S29 Chunk D Mig 32] V2 workflows ApplicableType=Contract(3) filter
  // IsUserSelectable=true (admin ghim cho user pick). Mirror PE Mig 25 pattern.
  const approvalWorkflows = useQuery({
    queryKey: ['approval-workflows-v2-contract'],
    queryFn: async () => {
      const res = await api.get<{ types: { applicableType: number; history: { id: string; code: string; version: number; name: string; isActive: boolean; isUserSelectable: boolean }[] }[] }>(
        '/approval-workflows-v2',
        { params: { applicableType: 3 } },
      )
      const typeBucket = res.data.types.find(t => t.applicableType === 3)
      return (typeBucket?.history ?? []).filter(w => w.isUserSelectable)
    },
  })
  const qc = useQueryClient()
  // [S61 Mig 50] HĐ chỉ còn ngân sách nhập tay (link Budget entity đã bỏ).
  const budgetPayload = {
    budgetManualName: budgetManualName || null,
    budgetManualAmount: budgetManualAmount > 0 ? budgetManualAmount : null,
  }

  const create = useMutation({
    mutationFn: async () => {
      const res = await api.post<{ id: string }>('/contracts', {
        type: Number(type),
        supplierId,
        projectId,
        departmentId: null,
        templateId: templateId || null,
        giaTri: giaTri ? Number(giaTri) : 0,
        tenHopDong: tenHopDong || null,
        noiDung: noiDung || null,
        bypassProcurementAndCCM: bypass,
        draftData: null,
        ...budgetPayload,
        // [Plan B S29 Chunk D Mig 32] Pin V2 workflow nếu user chọn; null →
        // BE fallback V1 auto pick.
        approvalWorkflowId: approvalWorkflowId || null,
      })
      return res.data.id
    },
    onSuccess: id => {
      toast.success('Đã tạo HĐ draft')
      qc.invalidateQueries({ queryKey: ['my-contracts'] })
      onCreated(id)
    },
    onError: err => toast.error(getErrorMessage(err)),
  })

  function submit(e: FormEvent) {
    e.preventDefault()
    if (!supplierId || !projectId) {
      toast.error('Chọn NCC và dự án')
      return
    }
    create.mutate()
  }

  return (
    <form onSubmit={submit} className="space-y-4 p-6">
      <div className="rounded-lg border border-slate-200 bg-white p-5">
        <h2 className="mb-4 text-sm font-semibold text-slate-700">Tạo HĐ mới — Header</h2>
        <FormFields
          type={type} setType={setType}
          templateId={templateId} setTemplateId={setTemplateId}
          supplierId={supplierId} setSupplierId={setSupplierId}
          projectId={projectId} setProjectId={setProjectId}
          tenHopDong={tenHopDong} setTenHopDong={setTenHopDong}
          giaTri={giaTri} setGiaTri={setGiaTri}
          bypass={bypass} setBypass={setBypass}
          noiDung={noiDung} setNoiDung={setNoiDung}
          suppliers={suppliers.data ?? []}
          projects={projects.data ?? []}
          templates={templates.data ?? []}
          typeReadonly={false}
        />
        {/* [Plan B S29 Chunk D Mig 32] V2 workflow picker — mutually exclusive
            với V1. Blank → BE fallback V1 auto pick (7 prod contract behavior).
            Mirror PE PeWorkspaceCreateView pattern. */}
        <div className="mt-4 space-y-1.5">
          <Label>Quy trình duyệt V2 <span className="text-[10px] font-normal text-slate-400">(tùy chọn — bỏ trống = dùng V1 mặc định)</span></Label>
          <Select
            value={approvalWorkflowId}
            onChange={e => setApprovalWorkflowId(e.target.value)}
          >
            <option value="">— V1 mặc định (auto pick) —</option>
            {approvalWorkflows.data?.map(w => (
              <option key={w.id} value={w.id}>
                {w.code} v{String(w.version).padStart(2, '0')} — {w.name}
                {w.isActive ? ' (đang áp dụng)' : ''}
              </option>
            ))}
          </Select>
          {approvalWorkflows.data && approvalWorkflows.data.length === 0 && (
            <p className="text-[11px] text-slate-500">
              Chưa có quy trình duyệt V2 nào được admin ghim cho HĐ — HĐ sẽ chạy theo V1 mặc định.
            </p>
          )}
        </div>
        <div className="mt-4 space-y-1.5">
          {/* [S61 Mig 50] HĐ giữ ngân sách NHẬP TAY (Tên + Số tiền) — chế độ link
              Budget entity đã bỏ (module Budget cũ xóa hẳn). */}
          <Label className="mb-0">Ngân sách (đối chiếu chi phí — nhập tay)</Label>
          <div className="grid grid-cols-1 gap-2 md:grid-cols-2">
            <div>
              <Label className="text-[11px]">Tên ngân sách (tham chiếu)</Label>
              <Input
                value={budgetManualName}
                onChange={e => setBudgetManualName(e.target.value)}
                placeholder="vd Tạm tính dự toán T11/2025"
                maxLength={200}
              />
            </div>
            <div>
              <Label className="text-[11px]">Số tiền (đ)</Label>
              <Input
                type="number"
                min={0}
                value={budgetManualAmount || ''}
                onChange={e => setBudgetManualAmount(Number(e.target.value))}
                placeholder="1000000000"
              />
              {budgetManualAmount > 0 && (
                <p className="mt-1 text-[11px] text-slate-500">
                  ≈ {budgetManualAmount.toLocaleString('vi-VN')} đ
                </p>
              )}
            </div>
          </div>
        </div>
        <div className="mt-4 flex justify-end gap-2">
          <Button type="submit" disabled={create.isPending}>
            <Save className="h-4 w-4" />
            {create.isPending ? 'Đang tạo…' : 'Tạo HĐ draft'}
          </Button>
        </div>
      </div>
      <ContractDetailsPreview type={type} />
    </form>
  )
}

// Preview section cho create mode — render structure thật của Chi tiết
// (table headers + add button) nhưng disabled, để user thấy trước phần
// nhập liệu sẽ unlock sau khi tạo Header xong.
function ContractDetailsPreview({ type }: { type: number }) {
  const headers = HEADERS_BY_TYPE[type] ?? []
  const typeLabel = ContractTypeLabel[type] ?? '—'

  return (
    <div className="rounded-lg border border-slate-200 bg-white p-5">
      <h2 className="mb-3 flex items-center gap-2 text-sm font-semibold text-slate-700">
        <FileText className="h-4 w-4" />
        Chi tiết ({typeLabel})
        <span className="ml-2 rounded-full bg-amber-100 px-2 py-0.5 text-[10px] font-medium text-amber-700">
          🔒 Cần tạo Header trước
        </span>
      </h2>

      <div className="overflow-x-auto rounded-lg border border-slate-200 opacity-60">
        <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>
            <tr>
              <td colSpan={headers.length + 2} className="px-3 py-12 text-center">
                <div className="flex flex-col items-center gap-2 text-slate-400">
                  <Lock className="h-5 w-5" />
                  <span className="text-sm">Tạo Header xong sẽ thêm được hạng mục chi tiết</span>
                </div>
              </td>
            </tr>
          </tbody>
        </table>
      </div>

      <button
        type="button"
        disabled
        className="mt-3 flex w-full cursor-not-allowed items-center justify-center gap-2 rounded-lg border border-slate-200 bg-slate-50 px-3 py-2 text-sm text-slate-400"
        title="Tạo Header trước"
      >
        <Plus className="h-4 w-4" />
        Thêm dòng
      </button>
    </div>
  )
}

// Headers per ContractType — sync với ContractDetailsTab.tsx để preview
// trùng với Chi tiết thật khi unlock.
const HEADERS_BY_TYPE: Record<number, string[]> = {
  1: ['Hạng mục', 'ĐVT', 'Khối lượng', 'Đơn giá', 'Thành tiền', 'Hoàn thành', 'Ghi chú'],
  2: ['Mã CV', 'Tên công việc', 'ĐVT', 'KL', 'Đơn giá', 'Thành tiền', 'Hoàn thành'],
  3: ['Mã SP', 'Tên SP', 'ĐVT', 'SL', 'Đơn giá', 'Thành tiền', 'Giao hàng'],
  4: ['Mã DV', 'Tên DV', 'ĐVT', 'Thời gian', 'Đơn giá', 'Thành tiền'],
  5: ['Mã SP', 'Tên SP', 'ĐVT', 'SL', 'Đơn giá', 'VAT (%)', 'Thành tiền'],
  6: ['Nhóm SP', 'Tên SP', 'ĐVT', 'Giá min', 'Giá max', 'Điều kiện thanh toán'],
  7: ['Loại DV', 'Tên DV', 'ĐVT', 'Giá min', 'Giá max', 'SLA'],
}

function ContractEditForm({
  contract,
  onSaved,
}: {
  contract: ContractDetail
  onSaved: () => void
}) {
  const isDraft = contract.phase === ContractPhase.DangSoanThao
  // ===== [W5 S187 vế (88)] Ruột pre-fill: HĐ sinh từ cầu KHKK→HĐ mang sẵn 15 field do BE gán
  // (`CreateContractFromSigningPlanFeatures.cs:186-207`). Màn sửa Nháp này TRƯỚC W5 chỉ hiện
  // 11/15; 4 field còn lại (Phòng ban · Người soạn · SLA · nguồn KHKK) có ĐỦ trong `ContractDetail`
  // đang tải sẵn nhưng KHÔNG được vẽ ⇒ người sửa Nháp không thấy HĐ này đẻ từ đâu. Dải chỉ-đọc
  // dưới đây bù đúng 4 field đó, 0 request mới, 0 field bịa. (Nợ còn lại → §5 sub-file W5.)
  const src = contract.source
  const srcGroup = src?.approvalGroup ?? null
  const srcGroupLabel = srcGroup != null ? KHKK_APPROVAL_GROUP_LABELS[srcGroup] : undefined
  const [templateId, setTemplateId] = useState(contract.templateId ?? '')
  const [giaTri, setGiaTri] = useState(String(contract.giaTri ?? 0))
  const [tenHopDong, setTenHopDong] = useState(contract.tenHopDong ?? '')
  const [noiDung, setNoiDung] = useState(contract.noiDung ?? '')
  // [S61 Mig 50] HĐ giữ ngân sách nhập tay — link Budget entity đã bỏ.
  const [budgetManualName, setBudgetManualName] = useState(contract.budgetManualName ?? '')
  const [budgetManualAmount, setBudgetManualAmount] = useState(contract.budgetManualAmount ?? 0)

  const templates = useQuery({
    queryKey: ['templates-by-type', contract.type],
    queryFn: async () => (await api.get<ContractTemplate[]>('/forms/templates', { params: { type: contract.type } })).data,
  })

  const qc = useQueryClient()
  const budgetPayload = {
    budgetManualName: budgetManualName || null,
    budgetManualAmount: budgetManualAmount > 0 ? budgetManualAmount : null,
  }

  const update = useMutation({
    mutationFn: async () => {
      await api.put(`/contracts/${contract.id}`, {
        id: contract.id,
        giaTri: giaTri ? Number(giaTri) : 0,
        tenHopDong: tenHopDong || null,
        noiDung: noiDung || null,
        templateId: templateId || null,
        draftData: null,
        ...budgetPayload,
      })
    },
    onSuccess: () => {
      toast.success('Đã lưu thay đổi')
      qc.invalidateQueries({ queryKey: ['contract', contract.id] })
      qc.invalidateQueries({ queryKey: ['my-contracts'] })
      qc.invalidateQueries({ queryKey: ['contract-changelogs', contract.id] })
      onSaved()
    },
    onError: err => toast.error(getErrorMessage(err)),
  })

  return (
    <div className="space-y-4 p-6">
      <div className="rounded-lg border border-slate-200 bg-white p-5">
        <div className="mb-4 flex items-start justify-between gap-3">
          <div>
            <h2 className="text-sm font-semibold text-slate-700">Chỉnh sửa HĐ — Header</h2>
            <div className="mt-1 flex items-center gap-2 text-xs text-slate-500">
              <span className="font-mono">{contract.maHopDong ?? '(chưa có mã)'}</span>
              <PhaseBadge phase={contract.phase} className="text-[10px]" />
            </div>
          </div>
          {isDraft && (
            <Button
              onClick={() => update.mutate()}
              disabled={update.isPending}
            >
              <Save className="h-4 w-4" />
              {update.isPending ? 'Đang lưu…' : 'Lưu thay đổi'}
            </Button>
          )}
        </div>

        {!isDraft && (
          <div className="mb-4 rounded-md border border-amber-200 bg-amber-50 px-3 py-2 text-xs text-amber-700">
            ⚠ HĐ đã chuyển khỏi phase Đang soạn thảo → Header read-only. Bạn vẫn có thể xem Chi tiết phía dưới.
          </div>
        )}

        {/* [W5 S187 vế (88)] Dải CHỈ-ĐỌC — dữ liệu HĐ mang sẵn mà form không có ô nhập.
            🔴 Đặt NGOÀI `grid grid-cols-2` bên dưới CÓ CHỦ ĐÍCH: nhét thêm ô con vào grid đó
            làm sibling auto-place trượt cột (bài S182) — dải này là 1 khối phẳng, 0 rủi ro.
            Dòng 1 chỉ hiện khi HĐ có nguồn KHKK (`source != null`, loose — bắt cả `undefined`
            của cache cũ); dòng 2 hiện LUÔN vì cả 3 field đều do BE gán ở MỌI đường tạo HĐ. */}
        <div className="mb-4 space-y-1.5 rounded-md border border-violet-100 bg-violet-50/60 px-3 py-2 text-xs">
          {src != null && (
            <div className="flex flex-wrap items-center gap-x-2 gap-y-1 text-slate-700">
              <span className="font-medium text-violet-700">Kế thừa từ Kế hoạch ký kết:</span>
              {/* Chỉ link khi phiếu cha còn đọc được — `maKeHoach === null` ⇔ phiếu đã xoá mềm,
                  mà `/khkk/:id` không `IgnoreQueryFilters` ⇒ 404 (đo ở §1 sub-file W5). */}
              {src.maKeHoach != null ? (
                <Link
                  to={`/khkk/${src.planId}${srcGroup != null ? `?group=${srcGroup}` : ''}`}
                  className="font-mono font-medium text-violet-600 underline underline-offset-2 hover:text-violet-700"
                >
                  {src.maKeHoach}
                </Link>
              ) : (
                <span className="font-mono text-slate-500">(phiếu đã xoá — không mở được phiếu gốc)</span>
              )}
              {srcGroup != null && (
                <span className="rounded bg-violet-100 px-1.5 py-0.5 font-medium text-violet-700">
                  N{srcGroup} · {srcGroupLabel ? srcGroupLabel : 'chưa có trong danh mục'}
                </span>
              )}
              <span>· {src.tenHangMucs.length} hạng mục</span>
              {src.approvedAmountTotal != null && (
                <span>
                  · Σ giá duyệt chốt <strong className="text-slate-900">{fmtMoney(src.approvedAmountTotal)} đ</strong>
                </span>
              )}
            </div>
          )}
          <div className="flex flex-wrap items-center gap-x-4 gap-y-1 text-slate-600">
            <span>Phòng ban: <strong className="text-slate-800">{contract.departmentName ?? '—'}</strong></span>
            <span>Người soạn: <strong className="text-slate-800">{contract.drafterName ?? '—'}</strong></span>
            <span className="flex items-center gap-1">
              SLA: <SlaTimer deadline={contract.slaDeadline} createdAt={contract.createdAt} />
            </span>
          </div>
        </div>

        <div className="grid grid-cols-2 gap-4">
          <div className="space-y-1.5">
            <Label>Loại HĐ</Label>
            <Input value={ContractTypeLabel[contract.type] ?? '—'} disabled className="bg-slate-50" />
          </div>
          <div className="space-y-1.5">
            <Label>Template</Label>
            <Select
              value={templateId}
              onChange={e => setTemplateId(e.target.value)}
              disabled={!isDraft}
            >
              <option value="">— Chưa chọn —</option>
              {templates.data?.filter(t => t.isActive).map(t => (
                <option key={t.id} value={t.id}>{t.formCode} — {t.name}</option>
              ))}
            </Select>
          </div>
          <div className="space-y-1.5">
            <Label>NCC</Label>
            <Input value={contract.supplierName} disabled className="bg-slate-50" />
          </div>
          <div className="space-y-1.5">
            <Label>Dự án</Label>
            <Input value={contract.projectName} disabled className="bg-slate-50" />
          </div>
          <div className="col-span-2 space-y-1.5">
            <Label>Tên HĐ</Label>
            <Input value={tenHopDong} onChange={e => setTenHopDong(e.target.value)} disabled={!isDraft} />
          </div>
          <div className="space-y-1.5">
            <Label>Giá trị (VND)</Label>
            <Input type="number" value={giaTri} onChange={e => setGiaTri(e.target.value)} disabled={!isDraft} />
          </div>
          <div className="flex items-end gap-2 pb-2">
            <input
              type="checkbox"
              checked={contract.bypassProcurementAndCCM}
              disabled
              className="h-4 w-4 accent-brand-600"
            />
            <Label className="text-slate-500">HĐ với Chủ đầu tư (bypass CCM) — không đổi sau khi tạo</Label>
          </div>
          <div className="col-span-2 space-y-1.5">
            <Label>Nội dung / ghi chú</Label>
            <Textarea rows={4} value={noiDung} onChange={e => setNoiDung(e.target.value)} disabled={!isDraft} />
          </div>
          <div className="col-span-2 space-y-1.5">
            {/* [S61 Mig 50] HĐ giữ ngân sách NHẬP TAY — link Budget entity đã bỏ
                (module Budget cũ xóa hẳn). */}
            <Label className="mb-0">Ngân sách (đối chiếu chi phí — nhập tay)</Label>
            {isDraft ? (
              <div className="grid grid-cols-1 gap-2 md:grid-cols-2">
                <div>
                  <Label className="text-[11px]">Tên ngân sách (tham chiếu)</Label>
                  <Input
                    value={budgetManualName}
                    onChange={e => setBudgetManualName(e.target.value)}
                    placeholder="vd Tạm tính dự toán T11/2025"
                    maxLength={200}
                  />
                </div>
                <div>
                  <Label className="text-[11px]">Số tiền (đ)</Label>
                  <Input
                    type="number"
                    min={0}
                    value={budgetManualAmount || ''}
                    onChange={e => setBudgetManualAmount(Number(e.target.value))}
                    placeholder="1000000000"
                  />
                  {budgetManualAmount > 0 && (
                    <p className="mt-1 text-[11px] text-slate-500">
                      ≈ {budgetManualAmount.toLocaleString('vi-VN')} đ
                    </p>
                  )}
                </div>
              </div>
            ) : contract.budgetManualAmount != null || contract.budgetManualName ? (
              // Mig 17 — read-only display khi !isDraft + có manual data
              <div className="block rounded border border-slate-200 bg-slate-50 px-3 py-2 text-sm text-slate-700">
                {contract.budgetManualName && <span>{contract.budgetManualName}</span>}
                {contract.budgetManualName && contract.budgetManualAmount != null && ' · '}
                {contract.budgetManualAmount != null && (
                  <span className="font-semibold text-slate-900">{contract.budgetManualAmount.toLocaleString('vi-VN')} đ</span>
                )}
                <span className="ml-2 rounded bg-slate-100 px-1.5 py-0.5 text-[10px] text-slate-500">nhập tay</span>
              </div>
            ) : (
              <Input value="(không link)" disabled className="bg-slate-50" />
            )}
          </div>
        </div>
      </div>

      {/* Chi tiết section — luôn hiển thị cho user thao tác */}
      <div className="rounded-lg border border-slate-200 bg-white p-5">
        <h2 className="mb-3 flex items-center gap-2 text-sm font-semibold text-slate-700">
          <FileText className="h-4 w-4" />
          Chi tiết ({ContractTypeLabel[contract.type] ?? '—'})
        </h2>
        <ContractDetailsTab contract={contract} />
      </div>
    </div>
  )
}

function FormFields({
  type, setType,
  templateId, setTemplateId,
  supplierId, setSupplierId,
  projectId, setProjectId,
  tenHopDong, setTenHopDong,
  giaTri, setGiaTri,
  bypass, setBypass,
  noiDung, setNoiDung,
  suppliers, projects, templates,
  typeReadonly,
}: {
  type: number
  setType: (n: number) => void
  templateId: string
  setTemplateId: (s: string) => void
  supplierId: string
  setSupplierId: (s: string) => void
  projectId: string
  setProjectId: (s: string) => void
  tenHopDong: string
  setTenHopDong: (s: string) => void
  giaTri: string
  setGiaTri: (s: string) => void
  bypass: boolean
  setBypass: (b: boolean) => void
  noiDung: string
  setNoiDung: (s: string) => void
  suppliers: Supplier[]
  projects: Project[]
  templates: ContractTemplate[]
  typeReadonly: boolean
}) {
  return (
    <div className="grid grid-cols-2 gap-4">
      <div className="space-y-1.5">
        <Label>Loại HĐ *</Label>
        <Select value={type} onChange={e => setType(Number(e.target.value))} disabled={typeReadonly}>
          {Object.entries(ContractTypeLabel).map(([v, l]) => (
            <option key={v} value={v}>{l}</option>
          ))}
        </Select>
      </div>
      <div className="space-y-1.5">
        <Label>Template (optional)</Label>
        <Select value={templateId} onChange={e => setTemplateId(e.target.value)}>
          <option value="">— Chưa chọn —</option>
          {templates.filter(t => t.isActive).map(t => (
            <option key={t.id} value={t.id}>{t.formCode} — {t.name}</option>
          ))}
        </Select>
      </div>
      <div className="space-y-1.5">
        <Label>NCC *</Label>
        <Select value={supplierId} onChange={e => setSupplierId(e.target.value)} required>
          <option value="">— Chọn —</option>
          {suppliers.map(s => (
            <option key={s.id} value={s.id}>{s.code} — {s.name}</option>
          ))}
        </Select>
      </div>
      <div className="space-y-1.5">
        <Label>Dự án *</Label>
        <Select value={projectId} onChange={e => setProjectId(e.target.value)} required>
          <option value="">— Chọn —</option>
          {projects.map(p => (
            <option key={p.id} value={p.id}>{p.code} — {p.name}</option>
          ))}
        </Select>
      </div>
      <div className="col-span-2 space-y-1.5">
        <Label>Tên HĐ</Label>
        <Input value={tenHopDong} onChange={e => setTenHopDong(e.target.value)} placeholder="vd: HĐ giao khoán nhân công dự án FLOCK 01" />
      </div>
      <div className="space-y-1.5">
        <Label>Giá trị (VND)</Label>
        <Input type="number" value={giaTri} onChange={e => setGiaTri(e.target.value)} />
      </div>
      <div className="flex items-end gap-2 pb-2">
        <input
          type="checkbox"
          id="bypass"
          checked={bypass}
          onChange={e => setBypass(e.target.checked)}
          className="h-4 w-4 accent-brand-600"
        />
        <Label htmlFor="bypass" className="cursor-pointer">HĐ với Chủ đầu tư (bypass CCM)</Label>
      </div>
      <div className="col-span-2 space-y-1.5">
        <Label>Nội dung / ghi chú</Label>
        <Textarea rows={4} value={noiDung} onChange={e => setNoiDung(e.target.value)} />
      </div>
    </div>
  )
}
