using SolutionErp.Domain.Contracts;

namespace SolutionErp.Domain.Identity;

// Nguồn duy nhất (single source of truth) cho menu key — dùng ở cả BE (policy) và seed.
// FE có `src/lib/menuKeys.ts` đồng bộ tay.
public static class MenuKeys
{
    public const string Dashboard = "Dashboard";
    public const string Master = "Master";
    public const string Suppliers = "Suppliers";
    public const string Projects = "Projects";
    public const string Departments = "Departments";
    public const string Contracts = "Contracts";
    public const string Forms = "Forms";
    public const string Reports = "Reports";
    public const string System = "System";
    public const string Users = "Users";
    public const string Roles = "Roles";
    public const string Permissions = "Permissions";
    public const string MenuVisibility = "MenuVisibility";    // [Mig 27] admin Ẩn/Hiện + Đổi tên menu fe-user
    public const string Workflows = "Workflows";

    // 4 master catalogs cho Details add form (autocomplete) — admin CRUD
    public const string Catalogs = "Catalogs";              // group
    public const string CatalogUnits = "CatalogUnits";
    public const string CatalogMaterials = "CatalogMaterials";
    public const string CatalogServices = "CatalogServices";
    public const string CatalogWorkItems = "CatalogWorkItems";
    // [K1 — S164, Mig 70] Danh mục Hợp đồng SOL-CCM-SP-002 (86 dòng × 8 nhóm duyệt).
    // 🔴 VÀO `All` (lệnh lead S164) ⇒ sinh 4 policy ContractCatalog.{Read,Create,Update,Delete}
    // ⇒ 2 số canonical `docs/STATUS.md` đổi: Menu keys +1 · Policies +4 (DERIVED |All|×|Actions|).
    public const string ContractCatalog = "ContractCatalog";

    // Per-contract-type menu groups + 3 action leaves each.
    // Key format: Ct_<TypeCode>[_<Action>] — prefix `Ct_` distinguishes from
    // top-level. Menu tree endpoint (GetMyMenuTreeQuery) treats descendants of
    // `Contracts` as inheriting the parent permission so we don't need per-
    // child permission rows for all roles.
    public static readonly string[] ContractTypeCodes =
        ["ThauPhu", "GiaoKhoan", "NhaCungCap", "DichVu", "MuaBan", "NguyenTacNcc", "NguyenTacDv"];

    // [S159 2026-07-29] 2 root PLACEHOLDER giai đoạn 2/4 (owner: menu hiển thị đúng
    // 4 giai đoạn như tab strip). [S161 W1 — reviewer F-3] TÁCH TRẠNG THÁI 2 key:
    //   - `KeHoachKyKet` ĐÃ VÀO `All` @S161 (W1 KHKK) ⇒ 4 policy KeHoachKyKet.* sinh runtime.
    //   - `HopDongCung` VẪN NGOÀI `All` — chưa có module ⇒ không sinh policy (GĐ4 = 1-mốc
    //     upload trên Contract, có thể không bao giờ cần policy riêng).
    public const string KeHoachKyKet = "KeHoachKyKet";
    public const string HopDongCung = "HopDongCung";

    // ============================================================
    // [K4a — S166] Sidebar KHKK 8 NHÓM DUYỆT × 6 leaf. Danh mục SOL-CCM-SP-002
    // (Mig 70) chia 86 dòng thành 8 nhóm duyệt; mỗi nhóm 1 workflow `KHKK-N{n}`
    // type-10 (K3) ⇒ sidebar cũng tách 8 nhóm.
    //   - NHÓM 1 GIỮ NGUYÊN 7 key CŨ KHÔNG-infix (`Khkk_G1` + `Khkk_WfView` …
    //     `Khkk_Deleted`, seed từ S159 — xem SeedMenuTreeAsync). Đổi tên key =
    //     mồ côi permission-row đã cấp (bài S155) ⇒ CẤM đổi.
    //   - NHÓM 2..8 dùng khuôn CÓ infix: `Khkk_G{n}` + `Khkk_G{n}_{action}`.
    // 🔴 49 key (7 group + 42 leaf) VÀO `All` ⇒ sinh thêm 196 policy
    //    `Khkk_G*.{Read,Create,Update,Delete}` (registered-unused: endpoint KHKK
    //    vẫn CHỈ dùng `KeHoachKyKet.*` — gotcha #85, đừng OR key con vào gate)
    //    ⇒ 2 số canonical `docs/STATUS.md` đổi: Menu keys +49 · Policies +196
    //    (Policies = |All| × |Actions|, DERIVED — khai DELTA, không neo mốc tuyệt đối).
    // 🔴 Vào `All` thì BẮT BUỘC có menu-row tương ứng trong `SeedMenuTreeAsync`
    //    (thiếu row = Permission FK nổ ngay lần boot đầu — invariant T6 K1).
    //    `KhkkGroupMenuKeys` dưới là NGUỒN CHUNG cho cả `All` LẪN vòng seed
    //    menu-row + vòng grant site-2 ⇒ 3 phía khớp by-construction, KHÔNG mirror tay.
    // ⚠️ 2 KHUÔN menu-key cùng sống trong file này (đọc 1 khuôn đừng tưởng khuôn kia sai):
    //    (a) `Ct_*` / `Pe_*` leaf CỐ Ý NGOÀI `All` — sinh động qua factory, Admin
    //        grant qua seeder riêng (xem chú thích tại PurchaseEvaluationApproved).
    //    (b) catalog / `AwV2_*` / `Khkk_G*` TRONG `All` — Admin tự có row qua
    //        loop `MenuKeys.All` ở SeedAdminPermissionsAsync. K4a đi khuôn (b).
    // ============================================================
    public static readonly int[] KhkkGroupNumbers = [2, 3, 4, 5, 6, 7, 8];
    public static readonly string[] KhkkLeafActions =
        ["WfView", "List", "Create", "Pending", "Approved", "Deleted"];

    public static string KhkkGroup(int n) => $"Khkk_G{n}";
    public static string KhkkLeaf(int n, string action) => $"Khkk_G{n}_{action}";

    // 49 key theo thứ tự: group n → 6 leaf của n → group n+1 → …
    // (khai báo TRƯỚC `All` vì static field initializer chạy theo thứ tự văn bản).
    public static readonly string[] KhkkGroupMenuKeys = KhkkGroupNumbers
        .SelectMany(n => new[] { KhkkGroup(n) }
            .Concat(KhkkLeafActions.Select(a => KhkkLeaf(n, a))))
        .ToArray();

    public static string ContractTypeGroup(string typeCode) => $"Ct_{typeCode}";
    public static string ContractTypeList(string typeCode) => $"Ct_{typeCode}_List";
    public static string ContractTypeCreate(string typeCode) => $"Ct_{typeCode}_Create";
    public static string ContractTypePending(string typeCode) => $"Ct_{typeCode}_Pending";

    // Workflow admin per ContractType — sub-menu dưới `Workflows`, click leaf
    // → mở /system/workflows/{typeCode} (filter theo type thay vì tab).
    public static string WorkflowTypeLeaf(string typeCode) => $"Wf_{typeCode}";

    // ============================================================
    // Module Duyệt NCC (tiền-HĐ) — Pe_* prefix. 2 EvaluationType:
    //   DuyetNcc (A, NccOnly 3-step) + DuyetNccPhuongAn (B, NccWithPlan 5-step).
    // Mỗi type có 3 action leaf (Danh sách / Thao tác / Duyệt) + 1 group.
    // Workflow admin cho PE ở /system/pe-workflows/:typeCode.
    // ============================================================
    public const string PurchaseEvaluations = "PurchaseEvaluations";          // root group
    public const string PeWorkflows = "PeWorkflows";                           // workflow admin root

    // ============================================================
    // Quy trình duyệt MỚI (Mig 22 — Session 17, 2026-05-08):
    // Schema riêng `ApprovalWorkflow` để UAT trước khi migrate hoàn toàn.
    // Cấu trúc: Quy trình > Bước (Phòng) > Cấp (NV cụ thể).
    //   Mã + Tên Quy trình
    //   Bước 1 - Phòng A
    //     Cấp 1 - NV X
    //     Cấp 2 - NV Y
    //   Bước 2 - Phòng B
    //     ...
    // ============================================================
    public const string ApprovalWorkflowsV2 = "ApprovalWorkflowsV2";          // root admin (mới)
    public const string ApprovalWorkflowDuyetNccV2 = "AwV2_DuyetNcc";          // leaf cho Duyệt NCC mới
    public const string ApprovalWorkflowDuyetNccPhuongAnV2 = "AwV2_DuyetNccPhuongAn";  // leaf cho Duyệt NCC và Giải pháp mới

    // [K3 nhịp-1 — S164/S165] 8 leaf Designer cho 8 quy trình duyệt KHKK theo NHÓM
    // DUYỆT N1..N8 (danh mục SOL-CCM-SP-002 Mig 70 chia 86 dòng thành 8 nhóm; phiếu
    // KHKK chốt nhóm lúc tạo — Mig 71). Mỗi nhóm 1 workflow `KHKK-N{n}` type-10 do
    // `DbInitializer.SeedKhkkGroupWorkflowsAsync` seed.
    // 🔴 8 key này VÀO `All` (lệnh lead K3-N1) ⇒ sinh 32 policy AwV2_KhkkN{1..8}.{R,C,U,D}
    //    ⇒ 2 số canonical `docs/STATUS.md` đổi: Menu keys +8 · Policies +32 (DERIVED |All|×|Actions|).
    // 🔴 Vào `All` thì BẮT BUỘC có menu-row tương ứng trong `SeedMenuTreeAsync` —
    //    thiếu row = Permission FK nổ ngay lần boot đầu (invariant test T6 K1).
    public const string ApprovalWorkflowKhkkN1 = "AwV2_KhkkN1";
    public const string ApprovalWorkflowKhkkN2 = "AwV2_KhkkN2";
    public const string ApprovalWorkflowKhkkN3 = "AwV2_KhkkN3";
    public const string ApprovalWorkflowKhkkN4 = "AwV2_KhkkN4";
    public const string ApprovalWorkflowKhkkN5 = "AwV2_KhkkN5";
    public const string ApprovalWorkflowKhkkN6 = "AwV2_KhkkN6";
    public const string ApprovalWorkflowKhkkN7 = "AwV2_KhkkN7";
    public const string ApprovalWorkflowKhkkN8 = "AwV2_KhkkN8";

    // [S187 W3 — YC-023/YC-024] 7 leaf Designer cho 7 QUY TRÌNH DUYỆT HỢP ĐỒNG theo LOẠI HĐ
    // (owner @S188: (80) trục 7-loại · (81) PA-A mỗi loại 1 mã). Workflow `HD-{TOKEN}` type-3
    // do `DbInitializer.SeedContractTypeWorkflowsAsync` seed; mã + tên loại ở NHÀ DUY NHẤT
    // `ContractApprovalWorkflowFamily` (Domain/Contracts).
    // 🔴 7 key này VÀO `All` (T3 — quyết mức-lead, tiền lệ K3-N1 `:123`) ⇒ sinh 28 policy
    //    AwV2_Hd*.{Read,Create,Update,Delete} ⇒ 2 số canonical `docs/STATUS.md` đổi:
    //    Menu keys +7 · Policies +28 (DERIVED |All|×|Actions| — khai DELTA, không neo mốc tuyệt đối).
    //    Như 8 key KHKK: registered-unused ở tầng endpoint (controller AwV2 vẫn gác bằng
    //    `ApprovalWorkflowsV2.*`) — đừng OR key con vào gate, gotcha #85.
    // 🔴 Vào `All` thì BẮT BUỘC có menu-row trong `SeedMenuTreeAsync` — thiếu row = Permission
    //    FK nổ ngay lần boot đầu (invariant T6; test `ContractCatalogTests` `:445` bắt đúng ca này).
    //    Mảng dưới là NGUỒN CHUNG cho cả `All` LẪN vòng seed menu-row ⇒ 2 phía khớp
    //    by-construction, KHÔNG mirror tay (khuôn K4a `KhkkGroupMenuKeys`).
    public static string ApprovalWorkflowContractLeaf(string keyToken) => $"AwV2_Hd{keyToken}";

    // Khai báo TRƯỚC `All` — static field initializer chạy theo THỨ TỰ VĂN BẢN
    // (đặt sau `All` thì `All` nhận mảng null, hỏng câm lúc boot).
    public static readonly string[] ContractWorkflowMenuKeys = ContractApprovalWorkflowFamily.Members
        .Select(m => ApprovalWorkflowContractLeaf(ContractApprovalWorkflowFamily.KeyToken(m.Code)))
        .ToArray();

    // [S61 Mig 50] Module Ngân sách cũ (Budgets + Bg_List/Bg_Create/Bg_Pending)
    // đã XÓA — thay bằng "Ngân sách gói thầu" nhúng trong phiếu PE
    // (PeWorkItemBudgets per cặp Dự án × Hạng mục). Menu/Permission rows cũ
    // cleanup qua SQL trong migration ReplaceBudgetModuleWithPeWorkItemBudgets.

    // ============================================================
    // Module Nhân sự (Phase 10.1 G-H1 — Mig 34 S33 2026-05-26).
    // Port từ NamGroup CT_NHANSU 1675 NV. 1 root group + 1 leaf Hồ sơ NS.
    // Phase 1 minimal scope — satellite CRUD endpoint defer Phase 1.5.
    // Future Phase 10.4 add: Hrm_Dashboard (G-H3) + Hrm_Config* (G-H2).
    // ============================================================
    public const string Hrm = "Hrm";                                // root group
    public const string HrmHoSo = "Hrm_HoSo";                       // Hồ sơ Nhân sự (list + detail + edit)
    // Phase 10.2 G-H2 (Mig 35 — S34) — Cấu hình HRM 4 catalog lookup.
    public const string HrmConfig = "Hrm_Config";                          // sub-group cấu hình
    public const string HrmConfigLeaveTypes = "Hrm_Config_LeaveTypes";     // Loại phép
    public const string HrmConfigHolidays = "Hrm_Config_Holidays";         // Ngày lễ
    public const string HrmConfigShifts = "Hrm_Config_Shifts";             // Ca làm việc
    public const string HrmConfigOtPolicies = "Hrm_Config_OtPolicies";     // Chính sách OT
    // Phase 11 P11-C (Mig 44 — S51) — Danh mục xe công + tài xế (reference VehicleBooking).
    public const string HrmConfigVehicles = "Hrm_Config_Vehicles";         // Xe công
    public const string HrmConfigDrivers = "Hrm_Config_Drivers";           // Tài xế

    // ============================================================
    // Module Văn phòng số (Phase 10.2 G-O1+ S34 2026-05-27).
    // 1 root group `Off` + leaf con: Off_DanhBa (G-O1 Danh bạ nội bộ).
    // Future Phase 10.2+ add: Off_PhongHop (G-O2 booking) +
    // workflow apps Off_DeXuat / Off_DonTu / Off_DatXe / Off_ItTicket.
    // ============================================================
    public const string Off = "Off";                                // root group văn phòng số
    public const string OffDashboard = "Off_Dashboard";            // Bảng điều khiển Văn phòng số (landing, S? — admin auto via All)
    public const string OffDanhBa = "Off_DanhBa";                   // Danh bạ nội bộ (card grid)
    // Phase 10.2 G-O2 (Mig 36 — S36 2026-05-28) — Phòng họp + Booking calendar.
    public const string OffPhongHop = "Off_PhongHop";                          // sub-group phòng họp
    public const string OffPhongHopView = "Off_PhongHop_View";                 // Xem lịch (FullCalendar)
    public const string OffPhongHopManage = "Off_PhongHop_Manage";             // Quản lý phòng (Admin CRUD MeetingRoom)
    public const string OffPhongHopBook = "Off_PhongHop_Book";                 // Đặt phòng (Create/Update/Cancel Booking)

    // Phase 10.3 G-O3 (Mig 38 — S37 2026-05-28) — Đề xuất (Proposal) workflow V2.
    public const string OffDeXuat = "Off_DeXuat";                              // sub-group Đề xuất
    public const string OffDeXuatList = "Off_DeXuat_List";                     // Danh sách đề xuất
    public const string OffDeXuatCreate = "Off_DeXuat_Create";                 // Tạo đề xuất mới
    public const string OffDeXuatInbox = "Off_DeXuat_Inbox";                   // Inbox phê duyệt

    // Phase 10.3-10.4 G-O4+G-O5+G-O6+G-P1 (Mig 39+40 — S38 2026-05-28) — Skeleton Workflow Apps.
    public const string OffDonTu = "Off_DonTu";                                // sub-group Đơn từ
    public const string OffDonTuLeave = "Off_DonTu_Leave";                     // Đơn nghỉ phép
    public const string OffDonTuOt = "Off_DonTu_Ot";                           // Đơn OT
    public const string OffDonTuTravel = "Off_DonTu_Travel";                   // Đơn công tác
    public const string OffDatXe = "Off_DatXe";                                // Đặt xe công
    public const string OffItTicket = "Off_ItTicket";                          // Ticket CNTT helpdesk
    public const string OffChamCong = "Off_ChamCong";                          // Chấm công GPS (G-P1) — [S57] re-parent Off → Personal
    public const string OffAttendanceReport = "Off_AttendanceReport";          // Báo cáo chấm công (P11-E, admin)
    public const string HrmDashboard = "Hrm_Dashboard";                        // Dashboard HRM (G-H3)

    // ============================================================
    // [S57] Nhóm "Cá nhân" — mirror layout Puro (NAMGROUP). Root group cho mục
    // cá nhân nhân viên. "Chấm công" (Off_ChamCong) re-parent Off → Personal.
    // ============================================================
    public const string Personal = "Personal";                                 // root group "Cá nhân"

    public static readonly string[] PurchaseEvaluationTypeCodes =
        ["DuyetNcc", "DuyetNccPhuongAn"];

    public static string PurchaseEvaluationGroup(string typeCode) => $"Pe_{typeCode}";
    public static string PurchaseEvaluationList(string typeCode) => $"Pe_{typeCode}_List";
    public static string PurchaseEvaluationCreate(string typeCode) => $"Pe_{typeCode}_Create";
    public static string PurchaseEvaluationPending(string typeCode) => $"Pe_{typeCode}_Pending";
    // [S155 đợt 2 — owner restructure menu 2026-07-27] `Duyệt` đổi nhãn thành "Đang duyệt"
    // (qua `labelBackfill`, KHÔNG đổi key) + 2 mục MỚI:
    //   `_Approved` → "Đã duyệt"  → FE `/purchase-evaluations?type={N}&phase=7` (0 route mới)
    //   `_Deleted`  → "Đã xóa"    → FE `/purchase-evaluations?type={N}&deleted=1`
    // 🔴 KHÔNG thêm vào `MenuKeys.All`: `Pe_*` là leaf sinh động qua factory (giống 5 key PE
    // hiện có), `All` chỉ chứa root `PurchaseEvaluations`. Thêm vào `All` sẽ đổi 2 số canonical
    // `Menu keys` / `Policies` ở `docs/STATUS.md` (Policies = |All| × |Actions|, DERIVED).
    public static string PurchaseEvaluationApproved(string typeCode) => $"Pe_{typeCode}_Approved";
    public static string PurchaseEvaluationDeleted(string typeCode) => $"Pe_{typeCode}_Deleted";
    // [Plan AA S24 t1] User read-only view ma trận phân quyền của workflow V2
    // admin Designer đã ghim (IsUserSelectable=true). Suffix `_WfView` distinct
    // với admin `PeWf_*` (Designer write).
    public static string PurchaseEvaluationWorkflowView(string typeCode) => $"Pe_{typeCode}_WfView";

    // Workflow admin leaf per PE type — dưới PeWorkflows, click leaf mở
    // /system/pe-workflows/{typeCode}
    public static string PeWorkflowTypeLeaf(string typeCode) => $"PeWf_{typeCode}";

    public static readonly string[] All =
    [
        Dashboard,
        Master, Suppliers, Projects, Departments,
        Catalogs, CatalogUnits, CatalogMaterials, CatalogServices, CatalogWorkItems,
        ContractCatalog,                                                                         // [K1 Mig 70 — S164] Danh mục Hợp đồng SP-002
        Contracts, Forms, Reports,
        PurchaseEvaluations,
        Hrm, HrmHoSo,                                                                            // Mig 34 — Phase 10.1
        HrmConfig, HrmConfigLeaveTypes, HrmConfigHolidays, HrmConfigShifts, HrmConfigOtPolicies, // Mig 35 — Phase 10.2 G-H2
        HrmConfigVehicles, HrmConfigDrivers,                                                     // Mig 44 — Phase 11 P11-C
        Off, OffDashboard, OffDanhBa,                                                            // Phase 10.2 G-O1 — Văn phòng số (+Off_Dashboard landing)
        OffPhongHop, OffPhongHopView, OffPhongHopManage, OffPhongHopBook,                        // Phase 10.2 G-O2 — Phòng họp
        OffDeXuat, OffDeXuatList, OffDeXuatCreate, OffDeXuatInbox,                               // Phase 10.3 G-O3 — Đề xuất
        OffDonTu, OffDonTuLeave, OffDonTuOt, OffDonTuTravel,                                      // Phase 10.3 G-O4 — Đơn từ
        OffDatXe, OffItTicket, OffChamCong, OffAttendanceReport, HrmDashboard,                    // Phase 10.3-10.4 — G-O5/G-O6/G-P1/G-H3 + P11-E report
        Personal,                                                                                // [S57] Cá nhân (Puro grouping — Chấm công re-parent)
        KeHoachKyKet,                                                                            // [W1 Mig 69 — S161] GĐ2 KHKK: const :41 vào All ⇒ sinh policy KeHoachKyKet.{Read,Create,Update,Delete}
        // [K4a — S166] 49 key sidebar KHKK nhóm 2..8 (7 group + 42 leaf) — nguồn sinh
        // `KhkkGroupMenuKeys` (dùng chung với seed menu-row + grant site-2). 7 key nhóm 1
        // KHÔNG-infix (`Khkk_G1`/`Khkk_WfView`…) CỐ Ý ngoài `All` như từ S159 — giữ nguyên
        // trạng thái cũ, quyền của chúng do site-2/site-3 phát.
        .. KhkkGroupMenuKeys,
        System, Users, Roles, Permissions, MenuVisibility, Workflows, PeWorkflows,
        ApprovalWorkflowsV2, ApprovalWorkflowDuyetNccV2, ApprovalWorkflowDuyetNccPhuongAnV2,    // Mig 22
        // [K3 nhịp-1 — S164/S165] 8 leaf Designer cho 8 nhóm duyệt KHKK (+8 key ⇒ +32 policy).
        ApprovalWorkflowKhkkN1, ApprovalWorkflowKhkkN2, ApprovalWorkflowKhkkN3, ApprovalWorkflowKhkkN4,
        ApprovalWorkflowKhkkN5, ApprovalWorkflowKhkkN6, ApprovalWorkflowKhkkN7, ApprovalWorkflowKhkkN8,
        // [S187 W3] 7 leaf Designer cho 7 quy trình duyệt HĐ theo LOẠI (+7 key ⇒ +28 policy).
        // Bộ-sinh từ `ContractApprovalWorkflowFamily` — dùng CHUNG với vòng seed menu-row.
        .. ContractWorkflowMenuKeys,
    ];

    public static readonly string[] Actions = ["Read", "Create", "Update", "Delete"];
}
