// [S174 owner] PANEL 1 (danh sách) của màn "Kế hoạch ký kết HĐ — Thao tác" — 1 cột, 2 TẦNG:
//   · tầng TRÊN  = phiếu Duyệt NCC ĐÃ DUYỆT (có NCC trúng thầu) mà CHƯA lập kế hoạch ký kết,
//                  gom theo DỰ ÁN — "việc còn phải làm"; bấm = nạp thẳng vào form tạo;
//   · tầng DƯỚI  = kế hoạch ký kết ĐÃ TẠO — "việc đã làm rồi"; bấm = XEM tại chỗ (read-only).
// File MIRROR SHA256 identical với fe-user counterpart.
//
// 🔴 LỊCH SỬ ĐẶT SAI CHỖ — ghi để không tái phạm: bản đầu S174 gắn panel này thành cột 3 của
// màn *Duyệt NCC — Thao tác* (`PurchaseEvaluationWorkspacePage`). Anh bác: **"chỗ duyệt NCC
// đã golive và đã tốt rồi"** — ý anh từ đầu là làm màn Thao tác của KHKK **GIỐNG GIAO DIỆN**
// Thao tác của Duyệt NCC, chứ không phải chèn thêm thứ vào màn Duyệt NCC. Đã revert
// `PurchaseEvaluationWorkspacePage` về đúng byte của `1b3bcaa`. Bài: "làm giống màn X" ≠
// "sửa màn X".
//
// 🔴 0 ENDPOINT MỚI — dùng lại đúng 2 cửa đã sống:
//   · `GET /contract-signing-plans/approved-pe-awaiting-plan` (chính cửa `KhkkCreatePage`
//     đang gọi) → `KhkkPeCandidateDto[]`; "chưa có kế hoạch" = `existingGroups` RỖNG.
//     🔸 Từ K2 S164 cửa này KHÔNG còn loại PE đã có kế hoạch (nó trả cả PE đã dùng vài
//     nhóm, kèm `existingGroups`) ⇒ lọc rỗng là việc của FE, đừng tưởng BE lọc hộ.
//   · `GET /contract-signing-plans` → `PagedResult<KhkkListItemDto>`.
//
// 🔴 GATE QUYỀN (gotcha #85 — mặt đã cắn thật ở S162): màn đang đứng là *Duyệt NCC*, nhưng
// CẢ HAI cửa trên gác bằng policy `KeHoachKyKet.Read` (`ContractSigningPlansController.cs:36`
// + `MenuPermissionHandler.cs:40` so khớp CHÍNH XÁC 1 key — KHÔNG kế thừa cha, KHÔNG OR key
// con). Người chỉ có quyền PE mà không có KHKK sẽ ăn 403 rải khắp cột. ⇒ gate bằng ĐÚNG key
// của endpoint, và khi thiếu quyền thì NÓI RA thay vì để cột trắng trông như "chưa có gì".
import { useQuery } from '@tanstack/react-query'
import { FileSignature, FolderTree, Lock, Pencil } from 'lucide-react'
import { usePermission } from '@/hooks/usePermission'
import { PipelineTreePanel } from '@/components/pipeline/PipelineTreePanel'
import { api } from '@/lib/api'
import { cn } from '@/lib/cn'
import {
  KHKK_PHASE_BADGE,
  KHKK_PHASE_LABELS,
  KhkkPhase,
  type KhkkListItemDto,
  type PagedResult,
} from '@/types/khkk'

const KHKK_TIER_PAGE_SIZE = 30


/** Vỏ 1 tầng — `min-h-0 flex-1` ở CẢ HAI tầng là thứ tạo ra tỉ lệ 50/50 thật; thiếu
 *  `min-h-0` thì con cuộn được sẽ đẩy tầng phình theo nội dung, hỏng tỉ lệ. */
function Tier({
  title, count, icon, accent, children,
}: {
  title: string
  count: number | null
  icon: React.ReactNode
  accent: string
  children: React.ReactNode
}) {
  return (
    <div className="flex min-h-0 flex-1 flex-col">
      <div className="flex shrink-0 items-center gap-2 border-b border-slate-200 bg-slate-50/80 px-3 py-2">
        <span className={cn('inline-flex h-5 w-5 items-center justify-center rounded', accent)} aria-hidden>
          {icon}
        </span>
        <span className="min-w-0 flex-1 truncate text-[11px] font-bold uppercase tracking-wide text-slate-600">
          {title}
        </span>
        {count !== null && (
          <span className="shrink-0 rounded-full bg-slate-100 px-2 py-0.5 text-[10px] font-medium text-slate-600">
            {count}
          </span>
        )}
      </div>
      <div className="min-h-0 flex-1 overflow-y-auto">{children}</div>
    </div>
  )
}

export function KhkkWorkListPanel({
  onPickPe,
  onPickPlan,
  selectedPlanId,
  onEditPlan,
  group,
}: {
  /** Bấm PE ở tầng trên → host nạp phiếu đó vào form tạo (Ở LẠI màn, không điều hướng). */
  onPickPe: (peId: string) => void
  /** Bấm KHKK ở tầng dưới → host mở phiếu đó ở panel 2, CHỈ XEM. Anh chốt: "click vào phiếu
   *  nào thì cho hiện phiếu đó luôn, chỉ view là đc, ko re-direct về phiếu gốc". */
  onPickPlan: (planId: string) => void
  selectedPlanId?: string | null
  /** [S175 · O7] Bấm bút chì trên card KHKK → host mở phiếu ở chế-độ SỬA. Không truyền ⇒
   *  không vẽ bút chì (cột giữ đúng hình cũ). */
  onEditPlan?: (planId: string) => void
  /** [S175 - anh: "Loc theo quy trinh luon"] Nhom duyet cua leaf menu dang dung.
   *  Tang duoi CHI hien ke hoach thuoc dung nhom nay - dung o leaf N2 ma thay phieu
   *  N1/N7 la doc nham "nhom nay dang co viec". `null` = khong loc. */
  group?: number | null
}) {
  const { can } = usePermission()
  // 🔴 ĐÚNG key policy của endpoint — KHÔNG dùng `Khkk_*` (đó là key MENU, tầng hiển thị).
  const canKhkk = can('KeHoachKyKet', 'Read')

  // 🧊 [S175] Query `khkk-pe-candidates` ĐÃ GỠ khỏi panel này — tầng trên nay là
  // `PipelineTreePanel`, nó TỰ nạp cây từ index PE của riêng nó. Giữ query cũ = gọi mạng
  // cho một danh sách không còn ai vẽ.
  // 🔸 `KhkkCreatePage` VẪN dùng key này cho ô chọn PE của form tạo — cache dùng chung,
  //    nên gỡ ở đây không làm form tạo mất dữ-liệu.

  const plans = useQuery({
    queryKey: ['khkk-list', { side: true, page: 1, pageSize: KHKK_TIER_PAGE_SIZE }],
    queryFn: async () =>
      (await api.get<PagedResult<KhkkListItemDto>>('/contract-signing-plans', {
        params: { page: 1, pageSize: KHKK_TIER_PAGE_SIZE },
      })).data,
    enabled: canKhkk,
  })



  // [S174 owner] "chỗ thao tác chỉ hiển trả lại và nháp, từ chối thôi nhé" ⇒ DANH-SÁCH-TRẮNG
  // 3 trạng thái, KHÔNG phải loại-trừ. 🔴 Đổi từ loại-trừ sang danh-sách-trắng là CÓ CHỦ ĐÍCH:
  // loại-trừ (`!== DaDuyet`) sẽ tự động NHẬN mọi phase mới thêm về sau; danh-sách-trắng thì
  // phase mới phải được khai TƯỜNG MINH mới hiện. Ở màn Thao tác — nơi chỉ nên có việc CÒN
  // SỬA ĐƯỢC — im lặng nhận thêm là hỏng, nên chọn vế chặt.
  // 🔸 `ChoDuyet` CŨNG bị loại (khác lượt trước chỉ bỏ `DaDuyet`): phiếu đang trình duyệt thì
  //    người soạn không thao tác gì được nữa.
  // 🔴 KHAI GIỚI-HẠN (lọc ở FE): endpoint chỉ nhận `phase` ĐƠN, không nhận nhiều ⇒ (1) KHÔNG
  //    dùng `plans.data.total` làm số hiển thị (nó đếm MỌI phase) — đếm từ mảng đã lọc;
  //    (2) cửa-sổ 30 phiếu mới nhất có thể toàn phiếu đã duyệt ⇒ tầng dưới rỗng dù còn nháp
  //    cũ hơn. Chấp nhận ở UAT; muốn chuẩn thì BE nhận `phases[]` rồi lọc SERVER-SIDE.
  const OPEN_PHASES: number[] = [KhkkPhase.DangSoanThao, KhkkPhase.TraLai, KhkkPhase.TuChoi]
  const planItems = (plans.data?.items ?? [])
    .filter((k) => OPEN_PHASES.includes(k.phase))
    // [S175] +loc NHOM. `group == null` => khong loc (giu duong cu cho host khong truyen).
    .filter((k) => group == null || k.approvalGroup === group)

  return (
    <aside className="flex min-h-0 flex-col overflow-hidden border-r border-slate-200 bg-white">
      {!canKhkk ? (
        // Cột trắng đọc thành "chưa có gì" — phải nói ĐÚNG lý do là thiếu quyền.
        <div className="flex flex-1 flex-col items-center justify-center gap-2 px-4 text-center">
          <Lock className="h-5 w-5 text-slate-300" />
          <p className="text-[11px] text-slate-500">
            Bạn chưa có quyền xem Kế hoạch ký kết HĐ nên cột này không dựng được. Việc duyệt NCC
            ở hai panel bên trái không bị ảnh hưởng.
          </p>
        </div>
      ) : (
        <>
          {/* [S175 — anh: "cho hiển thị nó giống thế này nhé" + "Hiển thị theo ngày tháng dự
              án hạng mục phiếu duyệt ncc và phiếu KHKK tương ứng"] Tầng trên nay DÙNG LẠI
              CHÍNH `PipelineTreePanel` — cây 📅 Năm › 📁 Dự án › 🧱 Hạng mục › 4 giai đoạn,
              đúng cây anh chỉ sang ở màn Danh sách.
              🔴 DÙNG LẠI thay vì dựng bản thứ hai: cây đó đã có sẵn tầng NĂM + gom hạng mục +
              4 folder giai đoạn; chép lại là đẻ 2 sự-thật, sửa 1 chỗ quên chỗ kia.
              🔴 2 callback đã có sẵn từ đợt trước: `onOpenPe` (O6) → nạp PE thẳng vào form tạo ·
              `onOpenKhkk` → mở phiếu KHKK ở panel 2. Không truyền thì cây tự `navigate` rời màn
              — đúng thứ anh cấm ("ko re-direct").
              🔸 `bodyMaxHClass="max-h-none"`: `Tier` đã tự cuộn rồi, để trần mặc-định của cây
              thì thành 2 thanh cuộn lồng nhau. */}
          <Tier
            title="Cây toàn trình — bấm phiếu để lập kế hoạch"
            count={null}
            accent="bg-amber-50 text-amber-600"
            icon={<FolderTree className="h-3 w-3" />}
          >
            {/* [S175 — anh: "chỗ này chỉ cần NCC đã duyệt là đc rồi nhé, còn lại bỏ hết đi"]
                · `approvedPeOnly` ⇒ chỉ phiếu PE phase `DaDuyet`. Màn này để CHỌN PE mà lập
                  kế hoạch; phiếu chưa duyệt xong thì lập không được, hiện ra là mời bấm nhầm.
                · `stagesOnly={[1]}` ⇒ chỉ folder **Duyệt NCC**; 3 giai-đoạn kia (Kế hoạch HĐ
                  + 8 ngăn nhóm · Duyệt HĐ · HĐ cứng) là nhiễu ở màn này.
                🔴 CẢ HAI đều OPT-IN — 5 host cây còn lại không truyền nên giữ nguyên hành vi. */}
            <PipelineTreePanel
              currentStage={2}
              hideHeader
              hideSearch
              approvedPeOnly
              stagesOnly={[1]}
              bodyMaxHClass="max-h-none"
              stage2Options={{ onOpenPe: onPickPe, onOpenKhkk: onPickPlan }}
            />
          </Tier>

          <div className="shrink-0 border-t-2 border-slate-200" />

          <Tier
            // Tên nói ĐÚNG tập đang hiện, không nói chung chung — người đọc phải biết ngay
            // vì sao phiếu họ vừa gửi duyệt "biến mất" khỏi đây.
            title="KHKK · nháp / trả lại / từ chối"
            // Đếm từ mảng ĐÃ LỌC, KHÔNG lấy `total` của server (xem khối lọc phía trên).
            count={plans.data ? planItems.length : null}
            accent="bg-violet-50 text-violet-600"
            icon={<FileSignature className="h-3 w-3" />}
          >
            {plans.isLoading && <div className="p-3 text-[11px] text-slate-500">Đang tải…</div>}
            {plans.isError && (
              <div className="space-y-1.5 p-3">
                <p className="text-[11px] text-slate-500">Không tải được danh sách.</p>
                <button
                  type="button"
                  onClick={() => plans.refetch()}
                  className="rounded-md border border-slate-300 px-2 py-1 text-[10px] font-semibold text-slate-600 hover:border-brand-300 hover:bg-brand-50"
                >
                  Thử lại
                </button>
              </div>
            )}
            {!plans.isLoading && !plans.isError && planItems.length === 0 && (
              <p className="p-3 text-[11px] italic text-slate-500">
                Không còn kế hoạch nào đang xử lý. Phiếu đã duyệt không hiện ở đây — xem tại
                menu Kế hoạch ký kết HĐ.
              </p>
            )}
            <ul className="divide-y divide-slate-100">
              {planItems.map((k) => (
                <li key={k.id} className="relative">
                  <button
                    type="button"
                    // 🔴 CHỈ XEM tại chỗ — KHÔNG `navigate('/khkk/:id')`. Anh chốt: "cho hiện
                    // phiếu đó luôn, chỉ view là đc, ko re-direct về phiếu gốc".
                    onClick={() => onPickPlan(k.id)}
                    title="Xem kế hoạch ký kết này (chỉ xem)"
                    className={cn(
                      'block w-full px-3 py-2 text-left transition hover:bg-violet-50/60',
                      selectedPlanId === k.id && 'bg-violet-50 ring-1 ring-inset ring-violet-300',
                      // [S175 · O7] Chừa chỗ cho bút chì để tên gói thầu dài không chui xuống dưới nó.
                      onEditPlan && 'pr-9',
                    )}
                  >
                    <div className="flex items-center gap-1.5">
                      <span className="font-mono text-[10px] text-violet-700">{k.maKeHoach ?? '(chưa cấp mã)'}</span>
                      {k.approvalGroup != null && (
                        <span className="rounded border border-violet-200 bg-violet-50 px-1 text-[9px] font-semibold text-violet-700">
                          N{k.approvalGroup}
                        </span>
                      )}
                      <span
                        className={cn(
                          'ml-auto shrink-0 rounded border px-1.5 py-0.5 text-[9px] font-medium',
                          KHKK_PHASE_BADGE[k.phase],
                        )}
                      >
                        {KHKK_PHASE_LABELS[k.phase]}
                      </span>
                    </div>
                    <div className="truncate text-[12px] font-medium text-slate-800">
                      {k.peTenGoiThau ?? '(chưa có tên gói thầu)'}
                    </div>
                  </button>
                  {/* [S175 · O7] Bút chì — khuôn `PeListPanel.tsx:208-232`. LUÔN hiện (không
                      chỉ khi hover) rồi MỜ ĐI khi không sửa được: nút chỉ-hiện-khi-hover thì
                      trên máy cảm-ứng không ai tìm ra, còn ẩn hẳn khi phiếu khoá thì người
                      dùng tưởng chức năng không tồn tại thay vì hiểu là phiếu đã đi duyệt.
                      🔴 Nút NGOÀI thẻ <button> của card — lồng button trong button là HTML
                      không hợp lệ, React sẽ cảnh báo và bấm sẽ kích cả hai. */}
                  {onEditPlan && (() => {
                    const editable = k.phase === KhkkPhase.DangSoanThao || k.phase === KhkkPhase.TraLai
                    return (
                      <button
                        type="button"
                        onClick={() => editable && onEditPlan(k.id)}
                        disabled={!editable}
                        title={editable
                          ? 'Sửa kế hoạch này'
                          : 'Kế hoạch đã gửi duyệt / đã duyệt — không sửa được'}
                        aria-label={editable ? `Sửa kế hoạch ${k.maKeHoach ?? ''}` : undefined}
                        className={cn(
                          'absolute right-2 top-2 rounded p-1.5 transition',
                          editable
                            ? 'cursor-pointer text-violet-600 hover:bg-violet-100 hover:shadow-sm'
                            : 'cursor-not-allowed text-slate-300',
                        )}
                      >
                        <Pencil className="h-3.5 w-3.5" />
                      </button>
                    )
                  })()}
                </li>
              ))}
            </ul>
            {/* 🔴 KHÔNG in "x/total" nữa: `total` gồm cả phiếu đã duyệt vừa bị lọc ⇒ tỉ số đó
                sẽ đọc thành "đang cắt bớt" trong khi thật ra là "đang lọc bỏ". Nói đúng việc
                đang làm, và chỉ nói khi thật sự có cái bị giấu. */}
            {/* 🧊 [S175 — anh: "Bỏ hết mấy chữ thừa này đi"] Dòng "Đã ẩn kế hoạch ở trạng
                thái Đã duyệt…" ĐÃ GỠ. Nó giải-thích CƠ-CHẾ lọc bên trong; người dùng chỉ cần
                thấy đúng phiếu, không cần biết cái gì bị ẩn vì sao. */}
          </Tier>
        </>
      )}

      {/* 🧊 [S174] KHÔNG có nút "+ Thêm mới" ở đáy — anh chốt bỏ. Lý do đứng vững: màn này
          KHÔNG có đường "tạo từ số 0". Một kế hoạch LUÔN sinh ra từ một phiếu Duyệt NCC, mà
          các phiếu đủ điều kiện đã nằm nguyên ở tầng trên ⇒ nút chỉ xoá form chứ không tạo
          thêm được gì. Đây là chỗ khác CÓ CHỦ ĐÍCH với `PeListPanel` (bên đó tạo phiếu PE
          mới là việc có thật). Ai định thêm lại: phải trả lời được "thêm mới CÁI GÌ". */}
    </aside>
  )
}
