// [W2 KHKK — S161 · dựng lại S171] Trang chi tiết "Kế hoạch ký kết HĐ" (GĐ2), route
// `/khkk/:id` GIỮ NGUYÊN (deep-link · bookmark · fallback `<lg` của màn 3-panel).
// File MIRROR SHA256 identical với fe-admin counterpart.
//
// [S171] Ruột trang nay là ĐÚNG 2 component dùng chung với host 3-panel `/khkk/list`:
//   `components/khkk/KhkkDetailContent`  (nội dung phiếu, 5 Section đánh số)
//   `components/khkk/KhkkWorkflowPanel`  (quy trình duyệt + lịch sử)
// xếp DỌC — khuôn `PurchaseEvaluationDetailPage` (`:798-805`). Không còn bản sao thứ hai
// của các Section ở đây: sửa 1 chỗ là cả 2 màn đổi theo.
import { useState } from 'react'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { useNavigate, useParams, useSearchParams } from 'react-router-dom'
import { ArrowLeft, FileCheck, FileSignature } from 'lucide-react'
import { toast } from 'sonner'
import { PageHeader } from '@/components/ui/PageHeader'
import { Button } from '@/components/ui/Button'
import { Dialog } from '@/components/ui/Dialog'
import { Input } from '@/components/ui/Input'
import { Label } from '@/components/ui/Label'
import { Select } from '@/components/ui/Select'
import { KhkkDetailContent } from '@/components/khkk/KhkkDetailContent'
import { KhkkWorkflowPanel } from '@/components/khkk/KhkkWorkflowPanel'
import { useAuth } from '@/contexts/AuthContext'
import { usePermission } from '@/hooks/usePermission'
import { api } from '@/lib/api'
import { getErrorMessage } from '@/lib/apiError'
import { cn } from '@/lib/cn'
import { ContractTypeLabel } from '@/types/forms'
import {
  KHKK_APPROVAL_GROUP_LABELS, KHKK_PHASE_BADGE, KHKK_PHASE_LABELS, KhkkPhase,
  type CreateContractFromKhkkInput, type CreateContractFromKhkkResult,
  type KhkkDetailDto, type KhkkLineDto, type KhkkPhaseValue,
} from '@/types/khkk'

function formatVnd(n: number | null): string {
  if (n === null || n === undefined) return '—'
  return n.toLocaleString('vi-VN') + ' đ'
}

export function KhkkDetailPage() {
  const { id } = useParams<{ id: string }>()
  const navigate = useNavigate()
  const qc = useQueryClient()
  const { user } = useAuth()
  const [searchParams] = useSearchParams()
  const [bridgeOpen, setBridgeOpen] = useState(false)

  // [M-10] Xóa/quay lại KHÔNG được rụng `?group=` — ném người dùng về "tất cả nhóm" là
  // mất chỗ họ đang đứng. `?group=n` là ĐÚNG URL leaf của nhóm n nên sidebar vẫn sáng đúng.
  const groupParam = searchParams.get('group')
  const group = groupParam !== null && /^[1-8]$/.test(groupParam) ? Number(groupParam) : null
  const backToList = group !== null ? `/khkk/list?group=${group}` : '/khkk/list'

  // [K7 S167 — vá-1 vế FE] HỘI 2 KHÓA, đúng bằng server, KHÔNG lỏng hơn:
  //   · `KeHoachKyKet.Read`  — cửa đọc chính phiếu này (`ContractSigningPlansController.cs:36`,
  //     `MenuPermissionHandler.cs:40` so khớp CHÍNH XÁC 1 key ⇒ KHÔNG OR `Khkk_*`, gotcha #85);
  //   · `Contracts.Create`   — cửa của endpoint bắc cầu: tài nguyên SINH RA là Contract nên key
  //     phải là của endpoint đích, không phải của màn đang đứng.
  const { can } = usePermission()
  const canReadPlan = can('KeHoachKyKet', 'Read')
  const canCreateContract = can('Contracts', 'Create')

  const plan = useQuery({
    queryKey: ['khkk-detail', id],
    queryFn: async () => (await api.get<KhkkDetailDto>(`/contract-signing-plans/${id}`)).data,
    enabled: !!id,
  })

  const invalidate = () => {
    qc.invalidateQueries({ queryKey: ['khkk-detail', id] })
    qc.invalidateQueries({ queryKey: ['khkk-list'] })
  }

  if (plan.isLoading) {
    return (
      <div className="space-y-5">
        <PageHeader eyebrow="Giai đoạn 2" title="Đang tải..." icon={<FileCheck className="h-5 w-5" />} />
      </div>
    )
  }

  if (plan.isError || !plan.data) {
    return (
      <div className="space-y-5">
        <PageHeader
          eyebrow="Giai đoạn 2"
          title="Lỗi"
          icon={<FileCheck className="h-5 w-5" />}
          actions={
            <Button variant="outline" onClick={() => navigate(backToList)}>
              <ArrowLeft className="mr-2 h-4 w-4" />
              Quay lại
            </Button>
          }
        />
        <div className="rounded-lg border bg-red-50 p-4 text-sm text-red-800">
          Không tải được dữ liệu kế hoạch ký kết.
        </div>
      </div>
    )
  }

  const k = plan.data
  const phase = k.phase as KhkkPhaseValue
  // [P2-7] `readOnly` là quyết-định của HOST (trang này cũng là một host).
  const readOnly =
    !(phase === KhkkPhase.DangSoanThao || phase === KhkkPhase.TraLai)
    || (!!user?.id && k.drafterUserId !== user.id)

  // [K7 S167] Dòng bắc cầu được = CHƯA có HĐ ∧ ĐÃ có giá duyệt chốt — đúng 2 guard BE.
  const bridgeableLines = k.lines.filter(l => l.contractId == null && l.approvedAmount != null)
  const showBridge = phase === KhkkPhase.DaDuyet && canReadPlan
  // Thiếu vế nào thì NÓI RA vế đó thay vì ẩn nút (khuôn nút-khoá-kèm-title PE `:547-561`).
  const bridgeBlockReason = !canCreateContract
    ? 'Bạn chưa có quyền "Tạo hợp đồng" (Contracts.Create) — nhờ quản trị cấp quyền rồi thử lại.'
    : k.lines.length === 0
      ? 'Phiếu chưa có dòng nhà cung cấp nào.'
      : bridgeableLines.length === 0
        ? (k.lines.every((l) => l.contractId != null)
            ? 'Mọi dòng của phiếu đã được đưa vào hợp đồng.'
            : 'Chưa dòng nào có giá duyệt chốt — phiếu phải qua bước chốt giá trước khi đưa vào HĐ.')
        : null

  return (
    <div className="space-y-5">
      <PageHeader
        eyebrow={k.maKeHoach ?? 'Kế hoạch ký kết'}
        title={k.peTenGoiThau ?? 'Kế hoạch ký kết HĐ'}
        icon={<FileCheck className="h-5 w-5" />}
        accent="brand"
        actions={
          <>
            {k.approvalGroup != null && (
              <span
                className="inline-flex items-center rounded-md border border-violet-300 bg-violet-100 px-2.5 py-1 text-xs font-semibold text-violet-800"
                title={KHKK_APPROVAL_GROUP_LABELS[k.approvalGroup] ?? `Nhóm ${k.approvalGroup}`}
              >
                N{k.approvalGroup}
              </span>
            )}
            <span className={cn('inline-flex items-center rounded-md border px-2.5 py-1 text-xs font-medium', KHKK_PHASE_BADGE[phase])}>
              {KHKK_PHASE_LABELS[phase]}
            </span>
            {/* `<span title>` bọc ngoài vì `Button` có `disabled:pointer-events-none`
                (Button.tsx:12) ⇒ title đặt thẳng trên nút đã khoá sẽ không hiện. */}
            {showBridge && (
              <span title={bridgeBlockReason ?? 'Tạo hợp đồng từ một dòng của kế hoạch này'}>
                <Button variant="outline" disabled={bridgeBlockReason != null} onClick={() => setBridgeOpen(true)}>
                  <FileSignature className="mr-2 h-4 w-4" />
                  Đưa vào HĐ
                </Button>
              </span>
            )}
            <Button variant="outline" onClick={() => navigate(backToList)}>
              <ArrowLeft className="mr-2 h-4 w-4" />
              Danh sách
            </Button>
          </>
        }
      />

      {/* [S174 owner] Khối "Quy trình duyệt" GỠ khỏi bản DESKTOP của trang này — anh chốt
          "bỏ hết, nó sẽ hiển thị ở Menu duyệt". Nhà của nó ở desktop là Panel-3 màn danh sách
          (`KhkkListPage.tsx:196`), nên gỡ = bỏ BẢN SAO THỨ HAI, không phải bỏ tính năng.
          🔴 [A3] NHƯNG `<lg` KHÔNG có 3 panel: `selectPlan` điều hướng thẳng vào trang này
          (`KhkkListPage.tsx:107`) ⇒ gỡ trắng thì mobile MẤT HẲN đường Gửi duyệt / Xóa phiếu.
          ⇒ giữ lại ĐÚNG ở `lg:hidden`: desktop vẫn sạch (panel-3 lo), mobile vẫn thao tác được.
          Đây là nợ lead đã khai với owner ở vòng trước, nay trả. */}
      <div className="lg:hidden">
        <KhkkWorkflowPanel plan={k} onChanged={invalidate} onDeleted={() => navigate(backToList)} />
      </div>

      <KhkkDetailContent plan={k} readOnly={readOnly} onChanged={invalidate} onDeleted={() => navigate("/khkk/list")} />

      {bridgeOpen && <CreateContractFromKhkkDialog plan={k} onClose={() => setBridgeOpen(false)} />}
    </div>
  )
}

// ===================== K7 S167 — cầu KHKK → Hợp đồng =================================
// [vá-16] 0 KHUÔN MỚI — ghép 2 khuôn đang sống:
//   · vỏ dialog + khối "nói thẳng hệ quả" = nút Xóa-phiếu S155 (`PeWorkflowPanel.tsx:879-918`);
//   · ô chọn Quy trình duyệt = picker `ContractCreatePage.tsx:333-343`.
// [OG-1 "máy rộng, UI hẹp"] Máy BE nhận `lineIds[]` (gộp được N dòng vào 1 HĐ); ô chọn ở
// đây CỐ Ý 1-1 — mỗi lần bấm đúng 1 dòng. Mở gộp sau = đổi radio thành checkbox, KHÔNG
// đụng hợp-đồng API.
type BridgeWorkflowOption = {
  id: string
  code: string
  version: number
  name: string
  isActive: boolean
  isUserSelectable: boolean
}

function CreateContractFromKhkkDialog({ plan, onClose }: { plan: KhkkDetailDto; onClose: () => void }) {
  const navigate = useNavigate()
  const qc = useQueryClient()

  const bridgeable = plan.lines.filter((l) => l.contractId == null && l.approvedAmount != null)
  const [lineId, setLineId] = useState(() => bridgeable[0]?.id ?? '')
  const [contractType, setContractType] = useState(1)
  const [workflowId, setWorkflowId] = useState('')
  // null = "đang dùng tên mặc định theo dòng đang chọn". Giữ null thay vì đồng bộ bằng
  // useEffect: đổi dòng thì tên gợi ý đổi theo NGAY trong render, không có nhịp lệch.
  const [tenHopDongOverride, setTenHopDongOverride] = useState<string | null>(null)

  const selected: KhkkLineDto | null = plan.lines.find((l) => l.id === lineId) ?? null
  const defaultName = selected
    ? `${plan.peTenGoiThau ?? 'Kế hoạch ký kết'} — ${selected.tenHangMuc ?? selected.supplierName ?? ''}`.trim()
    : ''
  const tenHopDong = tenHopDongOverride ?? defaultName

  const workflows = useQuery({
    // Query key RIÊNG (không dùng lại `approval-workflows-v2-contract`): cùng URL nhưng LỌC
    // KHÁC ⇒ dùng chung ô cache là để trang này ăn dữ liệu trang kia một cách câm (bài S159).
    queryKey: ['khkk-bridge-contract-workflows'],
    queryFn: async () => {
      const res = await api.get<{ types: { applicableType: number; history: BridgeWorkflowOption[] }[] }>(
        '/approval-workflows-v2',
        { params: { applicableType: 3 } },
      )
      const bucket = res.data.types.find((t) => t.applicableType === 3)
      // 🔴 LỌC ĐỦ 2 CỜ: `isUserSelectable` (admin ghim cho user chọn) ∧ `isActive` (bản còn
      // hiệu lực). Picker cũ chỉ lọc 1 cờ ⇒ mời chọn bản đã retire rồi ăn 409 từ guard BE.
      return (bucket?.history ?? []).filter((w) => w.isUserSelectable && w.isActive)
    },
  })

  const create = useMutation({
    mutationFn: async () => {
      const body: CreateContractFromKhkkInput = {
        lineIds: [lineId],
        contractType,
        approvalWorkflowId: workflowId,
        tenHopDong: tenHopDong.trim() || null,
      }
      return (await api.post<CreateContractFromKhkkResult>(
        `/contract-signing-plans/${plan.id}/create-contract`, body,
      )).data
    },
    onSuccess: (data) => {
      toast.success(data.maHopDong ? `Đã tạo hợp đồng ${data.maHopDong}` : 'Đã tạo hợp đồng từ kế hoạch')
      qc.invalidateQueries({ queryKey: ['khkk-detail', plan.id] })
      qc.invalidateQueries({ queryKey: ['khkk-list'] })
      // Cây 4 folder đọc 2 index riêng với `staleTime` 60s — không gọi 2 dòng này thì HĐ vừa
      // tạo cả phút sau mới hiện trên cây.
      qc.invalidateQueries({ queryKey: ['pipeline-khkk-index'] })
      qc.invalidateQueries({ queryKey: ['pipeline-contract-index'] })
      onClose()
      navigate(`/contracts/${data.contractId}`)
    },
    onError: (e) => toast.error(getErrorMessage(e)),
  })

  const noWorkflow = !workflows.isLoading && (workflows.data?.length ?? 0) === 0

  return (
    <Dialog
      open
      size="lg"
      onClose={onClose}
      title="Đưa dòng kế hoạch vào Hợp đồng"
      footer={
        <>
          <Button variant="ghost" onClick={onClose}>Huỷ</Button>
          <Button onClick={() => create.mutate()} disabled={create.isPending || !lineId || !workflowId}>
            {create.isPending ? 'Đang tạo...' : 'Tạo hợp đồng'}
          </Button>
        </>
      }
    >
      <div className="mb-3 rounded border border-amber-200 bg-amber-50 px-3 py-2 text-[12px] text-amber-900">
        <div className="font-semibold">Tạo hợp đồng từ kế hoạch &ldquo;{plan.maKeHoach ?? 'chưa cấp mã'}&rdquo;</div>
        <ul className="mt-1.5 list-disc space-y-1 pl-4 text-[11px]">
          <li>Mỗi lần bấm tạo <strong>1 hợp đồng cho 1 dòng</strong> (1 nhà cung cấp). Liên danh nhiều NCC thì làm lần lượt.</li>
          <li>Giá trị HĐ lấy đúng <strong>giá duyệt đã chốt</strong> của dòng — không lấy giá đề xuất.</li>
          <li>HĐ mới ở trạng thái <strong>Nháp</strong> và đi theo quy trình duyệt bạn chọn dưới đây.</li>
          <li>Dòng đã đưa vào HĐ thì <strong>không đưa lần hai</strong> — cần sửa thì xử lý ở chính hợp đồng đó.</li>
        </ul>
      </div>

      <div className="space-y-3">
        <div>
          <Label>Chọn dòng đưa vào hợp đồng</Label>
          {plan.lines.length === 0 ? (
            <div className="text-sm text-muted-foreground">Phiếu chưa có dòng nhà cung cấp nào.</div>
          ) : (
            <ul className="mt-1 space-y-1.5">
              {plan.lines.map((l) => {
                const done = l.contractId != null
                const noPrice = l.approvedAmount == null
                const disabled = done || noPrice
                return (
                  <li key={l.id}>
                    <label
                      className={cn(
                        'flex cursor-pointer items-center gap-2 rounded-lg border px-3 py-2 text-sm',
                        disabled && 'cursor-not-allowed border-slate-200 bg-slate-50 text-slate-400',
                        !disabled && lineId === l.id && 'border-brand-400 bg-brand-50',
                        !disabled && lineId !== l.id && 'border-slate-200 hover:bg-slate-50',
                      )}
                      title={
                        done ? 'Dòng này đã có hợp đồng.'
                          : noPrice ? 'Dòng chưa có giá duyệt chốt — phiếu phải qua bước chốt giá.'
                            : undefined
                      }
                    >
                      <input
                        type="radio"
                        name="khkk-bridge-line"
                        checked={lineId === l.id}
                        disabled={disabled}
                        onChange={() => { setLineId(l.id); setTenHopDongOverride(null) }}
                      />
                      <span className="min-w-0 flex-1">
                        <span className="font-medium">{l.tenHangMuc ?? '(chưa gán hạng mục)'}</span>
                        <span className="text-slate-500"> · {l.supplierName ?? '—'}</span>
                      </span>
                      <span className="shrink-0 tabular-nums">{formatVnd(l.approvedAmount)}</span>
                      {done && (
                        <a href={`/contracts/${l.contractId}`} className="shrink-0 text-[11px] font-medium text-brand-600 hover:underline">
                          Đã có HĐ
                        </a>
                      )}
                      {!done && noPrice && <span className="shrink-0 text-[11px]">Chưa có giá chốt</span>}
                    </label>
                  </li>
                )
              })}
            </ul>
          )}
        </div>

        <div>
          <Label htmlFor="bridge-type">Loại hợp đồng</Label>
          <Select id="bridge-type" value={contractType} onChange={(e) => setContractType(Number(e.target.value))}>
            {Object.entries(ContractTypeLabel).map(([v, label]) => (
              <option key={v} value={v}>{label}</option>
            ))}
          </Select>
        </div>

        <div>
          <Label htmlFor="bridge-workflow">Quy trình duyệt hợp đồng</Label>
          <Select
            id="bridge-workflow"
            value={workflowId}
            onChange={(e) => setWorkflowId(e.target.value)}
            disabled={workflows.isLoading || noWorkflow}
          >
            <option value="">— Chọn quy trình —</option>
            {(workflows.data ?? []).map((w) => (
              <option key={w.id} value={w.id}>{w.code} v{w.version} — {w.name}</option>
            ))}
          </Select>
          {noWorkflow && (
            // Rỗng-vì-chưa-cấu-hình phải khác câu với rỗng-vì-đang-tải: người dùng cần biết
            // đây là việc của quản trị, không phải chờ thêm.
            <p className="mt-1 text-[11px] text-red-700">
              Chưa có quy trình duyệt hợp đồng nào được ghim cho người dùng chọn (cần đang hiệu lực
              và được ghim). Nhờ quản trị mở trong màn Quy trình duyệt rồi quay lại.
            </p>
          )}
        </div>

        <div>
          <Label htmlFor="bridge-name">Tên hợp đồng</Label>
          <Input id="bridge-name" value={tenHopDong} onChange={(e) => setTenHopDongOverride(e.target.value)} maxLength={500} />
          <p className="mt-1 text-[11px] text-slate-500">
            Bỏ trống thì hệ thống tự đặt theo tên gói thầu và hạng mục của dòng.
          </p>
        </div>
      </div>
    </Dialog>
  )
}
