using SolutionErp.Domain.Common;

namespace SolutionErp.Domain.ApprovalWorkflowsV2;

// Quy trình duyệt mới (Mig 22 — Session 17, 2026-05-08).
// Schema riêng để UAT, KHÔNG đụng WorkflowDefinition cũ (Mig 21 flat). Sau UAT
// OK → migrate data PE/HĐ pin sang ApprovalWorkflowId + drop bảng cũ.
//
// Cấu trúc:
//   Quy trình (Code + Name + ApplicableType)
//     Bước 1 - Phòng A (DepartmentId optional hint)
//       Cấp 1 - NV X (ApproverUserId specific)
//       Cấp 2 - NV Y
//     Bước 2 - Phòng B
//       Cấp 1 - NV Z
//       ...
//
// Service (sau khi UAT chốt): iterate Steps OrderBy Order. Mỗi step iterate
// Levels OrderBy Order. Mỗi level = 1 NV cụ thể duyệt. Hết level → next step.
// Hết step → DaDuyet.
public class ApprovalWorkflow : BaseEntity
{
    public string Code { get; set; } = string.Empty;            // Mã quy trình "QT-DN-V2-001"
    public int Version { get; set; }                            // monotonically increases per Code
    public ApprovalWorkflowApplicableType ApplicableType { get; set; }  // module áp dụng
    public string Name { get; set; } = string.Empty;
    public string? Description { get; set; }
    public bool IsActive { get; set; }
    public DateTime? ActivatedAt { get; set; }

    // Mig 25 — admin toggle "cho user pick lúc create phiếu". Workspace dropdown
    // chỉ hiện workflow IsUserSelectable=true. Independent với IsActive: cho phép
    // multiple version cùng selectable (vd v02+v03 cùng pickable). Default true
    // khi tạo version mới (mirror IsActive default), admin có thể unstick.
    public bool IsUserSelectable { get; set; }

    // [S69 2026-06-17] Ngưỡng giá trị "gói CEO" — anh Kiệt FDC: CCM (role CostControl)
    // được duyệt-final KHÔNG cần lên CEO khi giá trị gói (tổng giá NCC được chọn,
    // winnerQuoteTotal) < ngưỡng này; ≥ ngưỡng → vẫn đẩy lên CEO (Director) như luồng
    // tuyến tính cũ. NULL = KHÔNG áp ngưỡng (giữ luồng cũ 100% — backward compat,
    // rollout an toàn cho tới khi admin set). Admin nhập trong Workflow Designer. So
    // sánh ở ApproveV2Async khi actor có role CostControl. decimal(18,2).
    public decimal? CeoApprovalThreshold { get; set; }

    // Mig 28 cũ 6 column workflow-level Allow* đã DROP trong Mig 29 (S21 t5).
    // Refactor sang per-NV (per ApprovalWorkflowLevel slot + Users F2). Backfill
    // bulk SQL copy workflow → all Levels của workflow trước khi DROP — preserve
    // admin config từ S21 t4.

    public List<ApprovalWorkflowStep> Steps { get; set; } = new();
}

public enum ApprovalWorkflowApplicableType
{
    DuyetNcc = 1,                   // PE module — Duyệt NCC (default test target)
    DuyetNccPhuongAn = 2,           // PE — Duyệt NCC + Giải pháp
    Contract = 3,                   // HĐ general (any ContractType)

    // Phase 10.3 Workflow Apps (S37 — Mig 37 enum extend). Cookie-cutter Mig 22 V2 pattern.
    // Mỗi module có 1 workflow per ApplicableType, admin Designer config + pin per draft.
    ProposalGeneral = 4,            // G-O3 — Đề xuất (Proposal)
    LeaveRequest = 5,               // G-O4 — Đơn nghỉ phép
    OtRequest = 6,                  // G-O4 — Đơn OT
    VehicleBooking = 7,             // G-O5 — Đặt xe công
    ItTicket = 8,                   // G-O6 — Ticket CNTT
    TravelRequest = 9,              // G-O4 — Đơn công tác (Travel) — Phase 11 P11-A

    // [W1 Mig 69 — S161 2026-07-29] GĐ2 "Kế hoạch ký kết HĐ" (ContractSigningPlan).
    // Append-only: slot 10 re-verify TRỐNG ngay trước khi viết (enum trước dừng ở 9).
    ContractSigningPlan = 10,       // GĐ2 — Kế hoạch ký kết HĐ (NCC/Thầu phụ)
}

// Bước = Phòng. 1 quy trình có nhiều bước theo Order.
public class ApprovalWorkflowStep : BaseEntity
{
    public Guid ApprovalWorkflowId { get; set; }
    public int Order { get; set; }                              // 1-based
    public string Name { get; set; } = string.Empty;            // "Phòng A", "Phòng B" — display
    public Guid? DepartmentId { get; set; }                     // hint phòng (optional, không strict match)

    public ApprovalWorkflow? ApprovalWorkflow { get; set; }
    public List<ApprovalWorkflowLevel> Levels { get; set; } = new();
}

// Cấp = tập các row CÙNG Order trong 1 Bước. MỖI ROW = 1 NV cụ thể
// (ApproverUserId), nhưng 1 Cấp có thể có N row ⇒ N người duyệt **OR-of-N**:
// bất kỳ ai trong Cấp duyệt là Cấp đó xong. Sequential giữa các Cấp trong cùng
// bước: cấp 1 → cấp 2 → ...
//
// [F-10 S155 2026-07-27] Comment cũ ghi "Cấp = 1 NV cụ thể ... (KHÔNG OR-of-many)"
// — SAI, ngược với mã lẫn tài liệu. Bằng chứng: service group Levels theo Order
// rồi cho phép BẤT KỲ ai trong nhóm duyệt
// (`PurchaseEvaluationWorkflowService.cs:689` `GroupBy(l => l.Order)` + `:702`
// `allowedUserIds.Contains(actorUserId)`); validator chỉ cấm TRÙNG cặp
// {Order, ApproverUserId} chứ không cấm nhiều row cùng Order
// (`ApprovalWorkflowV2AdminFeatures.cs:309-314`); CLAUDE.md + skill
// contract-workflow đều ghi "N NV cụ thể (OR-of-N cùng cấp)". Ảnh UAT prod:
// Cấp 2 Phòng Cung ứng có 3 người.
public class ApprovalWorkflowLevel : BaseEntity
{
    public Guid ApprovalWorkflowStepId { get; set; }
    public int Order { get; set; }                              // 1-based trong cùng step
    public string? Name { get; set; }                            // "Cấp 1" — display optional
    public Guid ApproverUserId { get; set; }                    // 1 NV cụ thể duyệt cấp này

    // ===== Mig 29 (Session 21 turn 5) — 5 advanced options per slot =====
    // Cấu hình quyền duyệt riêng cho TỪNG NV trong slot này. Admin Designer
    // tick stick per Level row (KHÔNG còn workflow-level cũ Mig 28).
    //
    // F1 (4 mode Trả lại) + F3 (Edit Section 2) = quyền của Approver Level.
    // F2 đã move xuống Level slot này (Mig 31 — xem prop AllowApproverSkipToFinal).
    // Semantic mới: Approver during ChoDuyet skip thẳng Cấp cuối (admin opt-in
    // per slot, KHÔNG còn per-Drafter user scope cũ).
    //
    // Backfill Mig 29: copy từ workflow-level Allow* cũ → all Levels của workflow.
    // Default backward compat: AllowReturnToDrafter=true (S17 fallback). 4 flag
    // còn lại default false (admin opt-in per Level).

    /// F1 mode 1 — Lùi 1 Cấp trong cùng Bước. Phase giữ ChoDuyet (peer review).
    public bool AllowReturnOneLevel { get; set; }

    /// F1 mode 2 — Lùi sang Bước trước Cấp cuối. Phase giữ ChoDuyet.
    public bool AllowReturnOneStep { get; set; }

    /// F1 mode 3 — Pick runtime từ NV đã ký (PeLevelOpinions). Phase giữ ChoDuyet.
    public bool AllowReturnToAssignee { get; set; }

    /// F1 mode 4 — Phase=TraLai, clear pointer (S17 fallback). Default TRUE.
    public bool AllowReturnToDrafter { get; set; } = true;

    /// F3 — Cho phép NV này edit Section 2 (Hạng mục + NCC + Báo giá) lúc đang
    /// duyệt. KHÔNG đụng PE Header, KHÔNG reset workflow.
    public bool AllowApproverEditDetails { get; set; }

    /// F4 (Mig 30 — S22+5) — Cho phép NV này edit Section "Điều chỉnh ngân sách"
    /// (BudgetId / BudgetManualName / BudgetManualAmount) lúc đang duyệt. Default
    /// false (admin opt-in per slot). Logic edit ngân sách giữ nguyên Drafter
    /// Nháp/Trả lại — flag này CHỈ mở thêm scope cho Approver ChoDuyet.
    public bool AllowApproverEditBudget { get; set; }

    /// F2 (Mig 31 — S23 t1 Plan K) — REFACTOR semantic + storage từ per-Drafter
    /// (cũ Mig 29 ở Users table, đã DROP) sang per-Approver slot. Cho phép NV slot
    /// này (khi đang duyệt ChoDuyet) Approve skip thẳng Cấp cuối, bỏ qua mọi
    /// Bước/Cấp trung gian còn lại. Default false (admin opt-in per slot).
    /// Mirror F3+F4 admin opt-in per-Approver pattern (Mig 29 + Mig 30)
    /// reinforced 3× cumulative. NO BACKFILL — 4 prod user lose value cũ per bro Option A.
    public bool AllowApproverSkipToFinal { get; set; }

    /// F5 (Mig 58 2026-06-24 — CCM/anh Kiệt FDC) — Cho phép NV slot này, khi duyệt
    /// ở cấp của mình, KẾT THÚC quy trình luôn (Phase=DaDuyet) KHÔNG cần trình CEO/
    /// các Bước-Cấp sau. Admin opt-in per slot trong Workflow Designer ("Duyệt là
    /// kết thúc (không trình CEO)"). Default false. KHÁC AllowApproverSkipToFinal
    /// (skip = advance pointer tới Cấp cuối, CEO vẫn ký thật): F5 = chính NV này
    /// approve = terminal NGAY. Service ApproveV2Async TỰ finalize khi
    /// matchingLevel.AllowApproverFinalize=true (AUTO theo cấu hình quy trình, anh Kiệt
    /// chốt 2026-06-24 — KHÔNG ô-tích runtime; admin per-level designation = cổng duy
    /// nhất, KHÔNG threshold/role check). Mirror F2/F3/F4 admin opt-in per-slot pattern.
    public bool AllowApproverFinalize { get; set; }

    /// F6 (Mig 68 2026-07-27 — S155, UAT Tra Sol/anh Kiệt) — Cho phép NV slot này,
    /// khi đang tới lượt duyệt của mình, XÓA MỀM phiếu đang treo ở ChoDuyet. Sinh ra
    /// vì phiếu bấm sai gói thầu đang **ăn lũy kế** ngân sách hạng mục sai mà không
    /// có cửa nào dừng: "Trả lại" chỉ DỜI số sang dòng khác chứ không triệt tiêu
    /// (`PeBudgetAccumulator.cs:104-126`), còn xóa thì allow-list chỉ nhận
    /// {DangSoanThao, TuChoi} (`PurchaseEvaluationFeatures.cs:1404-1406`).
    /// Default false (admin opt-in per slot). Đọc **PER-ROW** `matchingLevel.
    /// AllowApproverDelete` (khuôn F5 `PurchaseEvaluationWorkflowService.cs:859`),
    /// KHÔNG đọc per-Cấp `g.Any(...)` — 1 Cấp có N người (OR-of-N), đọc `Any` sẽ
    /// phát quyền huỷ chứng-từ cho CẢ Cấp thay vì đúng 1 người admin chỉ đích danh
    /// (owner chốt 2026-07-27). Mirror F2/F3/F4/F5 admin opt-in per-slot pattern.
    /// ⚠️ Cờ này chỉ là 1 trong 3 rào: policy `PurchaseEvaluations.Delete` ∧ đúng
    /// lượt ∧ F6 — xem hạng mục B spec S155 (đợt 2).
    public bool AllowApproverDelete { get; set; }

    public ApprovalWorkflowStep? Step { get; set; }
}
