// [S171] HOST 3-PANEL của màn "Kế hoạch ký kết HĐ" (GĐ2) — đưa GĐ2 về CÙNG bố-cục với
// Duyệt NCC (GĐ1, `pages/pe/PurchaseEvaluationsListPage.tsx:381,397`) và Hợp đồng
// (GĐ3, `pages/contracts/ContractsListPage.tsx:106,125`). Trước S171 trang này là
// `space-y-5` cuộn-body 2 panel ⇒ mắt-xích lệch DUY NHẤT trong 4 giai-đoạn.
// File MIRROR SHA256 identical với fe-admin counterpart.
//
// Khuôn code lấy từ `ContractsListPage.tsx` (255 dòng, gọn) — CỐ Ý KHÔNG chép
// `PurchaseEvaluationsListPage.tsx` (807 dòng: kéo theo `deleted`/`pendingMe`/`awId`/overlay).
// Số đo panel lấy của PE (400px) vì hiến-pháp owner là "giống nhất với Duyệt NCC".
//
// URL vào từ menu (Layout.tsx — staticMap nhóm 1, regex `Khkk_G{n}_*` nhóm 2..8):
//   Khkk_List / Khkk_G{n}_List         → /khkk/list?group={n}
//   Khkk_Pending / Khkk_G{n}_Pending   → /khkk/list?group={n}&filter=ChoDuyet
//   Khkk_Approved / Khkk_G{n}_Approved → /khkk/list?group={n}&filter=DaDuyet
//   Khkk_Deleted / Khkk_G{n}_Deleted   → /khkk/list?group={n}&view=deleted
//
// 🔴 [M-4] KHOÁ URL ĐƯỢC PHÉP GHI = `id` (∈ `TRANSIENT_QUERY_KEYS`, `Layout.tsx:350`).
// TUYỆT ĐỐI KHÔNG ghi `filter` / `view` / `group` vào `setSearchParams`: đứng ở leaf
// `?group=1` mà ghi thêm `filter=DaDuyet` là URL khớp CHÍNH XÁC leaf "Đã duyệt" của nhóm ⇒
// sidebar sáng nhầm mục — đúng bug UAT S155. Bộ lọc người dùng bấm sống ở LỚP OVERRIDE
// (state) như bản cũ, không ghi ngược URL.
//
// 🔴 [K4b S166 · R-5] 8 nhóm dùng CHUNG một route ⇒ mọi thứ lấy từ URL phải ĐỌC LẠI MỖI
// RENDER. Khối reset dưới đây là SET-STATE-TRONG-RENDER **CÓ CHỦ ĐÍCH** (khuôn React
// "reset state khi input đổi") — ai refactor thành `useEffect` sẽ tái-hiện vá-5 (đi từ
// leaf nhóm 2 sang leaf nhóm 5 phải F5 mới đúng). ĐỪNG ĐỘNG.
import { useState } from 'react'
import { useQuery } from '@tanstack/react-query'
import { useNavigate, useSearchParams } from 'react-router-dom'
import { FileCheck, X } from 'lucide-react'
import { EmptyState } from '@/components/EmptyState'
import { KhkkListPanel } from '@/components/khkk/KhkkListPanel'
import { KhkkDetailContent } from '@/components/khkk/KhkkDetailContent'
import { KhkkWorkflowPanel } from '@/components/khkk/KhkkWorkflowPanel'
// [S175 · O6] Xem phiếu Duyệt NCC tại chỗ — dùng LẠI đúng renderer của màn PE thay vì dựng
// bản rút gọn thứ hai (2 bản = 2 sự thật, sửa 1 chỗ quên chỗ kia).
import { PeDetailTabs } from '@/components/pe/PeDetailTabs'
import { type PeDetailBundle } from '@/types/purchaseEvaluation'
import { useAuth } from '@/contexts/AuthContext'
import { api } from '@/lib/api'
import { isNotFound } from '@/lib/apiError'
import {
  KhkkPhase,
  type KhkkDetailDto,
  type KhkkPhaseValue,
} from '@/types/khkk'

// Tên phase trong query `?filter=` → int (URL đọc được, không dính số ma thuật).
const FILTER_TO_PHASE: Record<string, KhkkPhaseValue> = {
  DangSoanThao: KhkkPhase.DangSoanThao,
  ChoDuyet: KhkkPhase.ChoDuyet,
  DaDuyet: KhkkPhase.DaDuyet,
  TraLai: KhkkPhase.TraLai,
  TuChoi: KhkkPhase.TuChoi,
}

export function KhkkListPage() {
  const navigate = useNavigate()
  const [searchParams, setSearchParams] = useSearchParams()
  const { user } = useAuth()

  // ---- 3 trục DANH TÍNH đọc thẳng từ URL (chỉ ĐỌC — không bao giờ ghi lại, xem M-4) ----
  const urlFilter = searchParams.get('filter')
  const urlPhase: KhkkPhaseValue | null = urlFilter ? (FILTER_TO_PHASE[urlFilter] ?? null) : null
  const deletedView = searchParams.get('view') === 'deleted'
  const groupParam = searchParams.get('group')
  const urlGroup = groupParam !== null && /^[1-8]$/.test(groupParam) ? Number(groupParam) : null
  const selectedId = searchParams.get('id')

  // ---- Lớp override do NGƯỜI DÙNG bấm, đè lên bộ lọc của URL ----
  // 🔴 3 trạng thái, KHÔNG gộp được: `undefined` = chưa chạm ⇒ nghe theo URL; `null` = user
  // chủ động chọn "Tất cả"; số = user chọn một giá trị. Gộp `undefined` với `null` thì chọn
  // "Tất cả" sẽ bị URL kéo ngược về bộ lọc cũ.
  const [chipPhase, setChipPhase] = useState<KhkkPhaseValue | null | undefined>(undefined)
  const [groupOverride, setGroupOverride] = useState<number | null | undefined>(undefined)
  const [search, setSearch] = useState('')
  const [page, setPage] = useState(1)

  // Đổi leaf ⇒ trả bộ lọc về cho URL và về trang 1. `search` CỐ Ý giữ lại: đang tìm một mã
  // rồi đổi nhóm để dò tiếp là thao tác có thật.
  const navKey = `${urlGroup ?? ''}|${urlFilter ?? ''}|${deletedView ? 'del' : ''}`
  const [lastNavKey, setLastNavKey] = useState(navKey)
  if (navKey !== lastNavKey) {
    setLastNavKey(navKey)
    setChipPhase(undefined)
    setGroupOverride(undefined)
    setPage(1)
  }
  const phase: KhkkPhaseValue | null = chipPhase !== undefined ? chipPhase : urlPhase
  const group: number | null = groupOverride !== undefined ? groupOverride : urlGroup

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

  // [S175 · O6] Phiếu Duyệt NCC đang XEM TẠI CHỖ. Anh chốt: bấm card PE trên cây thì
  // GIỮ NGUYÊN màn KHKK, chỉ xem, KHÔNG re-direct về phiếu gốc.
  // 🔴 `pe` và `id` LOẠI TRỪ NHAU: panel 2 chỉ vẽ được một thứ, để cả hai thì lần chọn sau
  // không xoá được lần trước và người dùng kẹt ở phiếu cũ.
  const selectedPeId = searchParams.get('pe')
  const peDetail = useQuery({
    queryKey: ['pe-detail', selectedPeId],
    queryFn: async () => (await api.get<PeDetailBundle>(`/purchase-evaluations/${selectedPeId}`)).data,
    enabled: !!selectedPeId,
  })

  function setId(id: string | null) {
    const next = new URLSearchParams(searchParams)
    if (id == null) next.delete('id')
    else next.set('id', id)
    next.delete('pe')
    setSearchParams(next)
  }

  function setPeId(id: string | null) {
    const next = new URLSearchParams(searchParams)
    if (id == null) next.delete('pe')
    else next.set('pe', id)
    next.delete('id')
    setSearchParams(next)
  }

  function selectPlan(id: string) {
    // `<lg` không có 3 panel ⇒ mở trang chi tiết đầy đủ (route `/khkk/:id` GIỮ NGUYÊN).
    if (typeof window !== 'undefined' && window.matchMedia('(min-width: 1024px)').matches) {
      setId(id)
    } else {
      navigate(group !== null ? `/khkk/${id}?group=${group}` : `/khkk/${id}`)
    }
  }

  function selectPe(id: string) {
    // Cùng luật breakpoint với `selectPlan`: `<lg` KHÔNG có panel 2 nên xem tại chỗ là bất
    // khả — rơi về đúng đường cũ (trang Duyệt NCC + overlay) thay vì bấm mà không thấy gì.
    if (typeof window !== 'undefined' && window.matchMedia('(min-width: 1024px)').matches) {
      setPeId(id)
    } else {
      navigate(`/purchase-evaluations?id=${id}&expand=1`)
    }
  }

  const plan = detail.data
  // [P2-7] `readOnly` do HOST quyết — KHÔNG cần dựng workspace riêng để có bản chỉ-xem.
  const readOnly =
    !plan
    || !(plan.phase === KhkkPhase.DangSoanThao || plan.phase === KhkkPhase.TraLai)
    || (!!user?.id && plan.drafterUserId !== user.id)

  const headerTitle = deletedView
    ? (group !== null ? `Kế hoạch ký kết HĐ — N${group} · đã xóa` : 'Kế hoạch ký kết HĐ — đã xóa')
    : group !== null ? `Kế hoạch ký kết HĐ — N${group}` : 'Kế hoạch ký kết 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 min-w-0 items-center gap-2">
          <FileCheck className="h-5 w-5 text-slate-500" />
          <h1 className="truncate text-base font-semibold tracking-tight text-slate-900">{headerTitle}</h1>
          {/* 🧊 [S175] Chip "Giai đoạn 2 · <tên nhóm dài>" ĐÃ GỠ — anh: "Bỏ mấy dòng này đi".
              Tên nhóm đã có trong `headerTitle` ngay bên trái (dạng ngắn "— N2"), và dải 4 giai
              đoạn ở panel giữa đã chỉ rõ đang đứng ở GĐ2 ⇒ chip này là lần kể thứ ba. */}
        </div>
        {/* [S175 - anh: "Bo het di"] Nut "+ Lap ke hoach" o header DA GO. Duong lap ke
            hoach di tu man Thao tac (bam phieu PE o cot trai = nap thang vao form tao) —
            do moi la duong dung nghiep-vu; nut o day de nguoi dung mo form TRONG khong
            gan PE nao. */}
      </header>

      <div className="grid flex-1 grid-cols-1 overflow-hidden lg:grid-cols-[400px_1fr_360px]">
        {/* Panel 1 — cây toàn trình (owner QĐ-1) + 4 mitigation, xem KhkkListPanel.tsx */}
        <KhkkListPanel
          selectedId={selectedId}
          onSelect={selectPlan}
          search={search}
          onSearchChange={(v) => { setSearch(v); setPage(1) }}
          phase={phase}
          onPhaseChange={(v) => { setChipPhase(v); setPage(1) }}
          group={group}
          deletedView={deletedView}
          page={page}
          onPageChange={setPage}
          selectedFinalize={
            plan
              ? { endedByLevelFinalize: plan.endedByLevelFinalize, finalizeStepName: plan.finalizeStepName }
              : undefined
          }
          onOpenPe={selectPe}
        />

        {/* Panel 2 — nội dung phiếu. [F-1] EmptyState là trạng-thái ĐẦU TIÊN người dùng thấy;
            thiếu nó thì host 3-panel mở ra là một mảng trắng ở giữa. */}
        <main className="hidden overflow-y-auto bg-slate-50 p-6 lg:block">
          {!selectedId && !selectedPeId && (
            <EmptyState
              icon={FileCheck}
              title={deletedView ? 'Phiếu đã xóa — chỉ xem danh sách' : 'Chọn phiếu ở danh sách'}
              description={deletedView
                ? 'Mục này chỉ liệt kê phiếu đã xóa để đối chiếu. Không mở chi tiết, không thao tác.'
                : 'Nội dung kế hoạch + dòng giá NCC + căn cứ hồ sơ + ý kiến cấp duyệt sẽ hiển thị ở đây.'}
            />
          )}

          {/* [S175 · O6] Xem phiếu Duyệt NCC TẠI CHỖ — `readOnly` + `mode="workspace"` để
              chắc chắn không có đường sửa/duyệt nào lọt ra ở màn KHKK (anh chốt "chỉ view").
              Băng chỉ-đường ở trên vì panel 2 lúc này KHÔNG còn nói về kế hoạch ký kết nữa —
              không nói rõ thì người dùng tưởng mình đang xem KHKK. */}
          {selectedPeId && (
            <div className="mb-4 flex flex-wrap items-center justify-between gap-2 rounded-md border border-brand-200 bg-brand-50 px-3 py-2 text-[12px] text-brand-800">
              <span>Đang xem <strong>phiếu Duyệt NCC</strong> (giai đoạn 1) — chỉ xem, không thao tác.</span>
              <button
                type="button"
                onClick={() => setPeId(null)}
                className="shrink-0 rounded border border-brand-300 bg-white px-2 py-0.5 font-semibold text-brand-700 transition hover:bg-brand-100"
              >
                ← Về kế hoạch ký kết
              </button>
            </div>
          )}
          {selectedPeId && peDetail.isLoading && <div className="text-sm text-slate-500">Đang tải phiếu Duyệt NCC…</div>}
          {selectedPeId && peDetail.isError && (
            <div className="text-sm text-red-600">Không tải được phiếu Duyệt NCC (có thể bạn chưa có quyền xem).</div>
          )}
          {selectedPeId && peDetail.data && (
            <PeDetailTabs
              evaluation={peDetail.data}
              readOnly
              mode="workspace"
              onBack={() => setPeId(null)}
              onDelete={() => setPeId(null)}
            />
          )}

          {selectedId && detail.isLoading && <div className="text-sm text-slate-500">Đang tải…</div>}
          {/* [S189 · YC-028(5)] 404 thật ⟂ lỗi hệ thống — mirror PurchaseEvaluationsListPage. */}
          {selectedId && !detail.isLoading && !plan && (
            detail.isError && !isNotFound(detail.error) ? (
              <div className="text-sm text-red-600">
                Hệ thống đang chậm hoặc lỗi khi tải phiếu —{' '}
                <button type="button" className="font-medium underline" onClick={() => detail.refetch()}>thử lại</button>.
              </div>
            ) : (
              <div className="text-sm text-red-600">Không tìm thấy phiếu.</div>
            )
          )}
          {selectedId && plan && (
            <KhkkDetailContent plan={plan} readOnly={readOnly} onChanged={() => detail.refetch()} onDeleted={() => setId(null)} />
          )}
        </main>

        {/* Panel 3 — quy trình duyệt + lịch sử.
            🔴 OWNER CHỐT (QĐ-2): chưa chọn phiếu ⇒ CHỈ hộp dashed y hệt Duyệt NCC
            (`PurchaseEvaluationsListPage.tsx:669-676`). KHÔNG nhét `PipelineTreePanel` vào
            đây — cây đã sống ở panel 1 theo QĐ-1, nhét lần hai là trùng. Khác GĐ3 ở điểm
            này là CÓ CHỦ ĐÍCH. */}
        <aside className="hidden overflow-y-auto border-l border-slate-200 bg-white p-4 lg:block">
          {!selectedId && (
            <div className="rounded-lg border border-dashed border-slate-200 p-6 text-center text-sm text-slate-500">
              <X className="mx-auto mb-2 h-5 w-5" />
              {/* [S175 · O6] Đang xem PE ⇒ NÓI RÕ quy trình duyệt của nó nằm ở màn khác,
                  thay vì để nguyên câu "sẽ hiện khi chọn phiếu" (sai: phiếu ĐÃ chọn rồi). */}
              {selectedPeId
                ? 'Đang xem phiếu Duyệt NCC — quy trình duyệt của phiếu này nằm ở màn Duyệt NCC.'
                : deletedView
                  ? 'Phiếu đã xóa không còn quy trình duyệt.'
                  : 'Quy trình duyệt sẽ hiện khi chọn phiếu.'}
            </div>
          )}
          {selectedId && plan && (
            <KhkkWorkflowPanel
              plan={plan}
              onChanged={() => detail.refetch()}
              onDeleted={() => setId(null)}
            />
          )}
        </aside>
      </div>
    </div>
  )
}
