using SolutionErp.Domain.Common;

namespace SolutionErp.Domain.PurchaseEvaluations;

// Aggregate root cho phiếu Duyệt NCC — module tiền-HĐ.
// Sau khi phê duyệt xong (Phase=DaDuyet) user click "Tạo HĐ từ phiếu" →
// kế thừa Details/Quotes sang Contract + ContractDetails.
public class PurchaseEvaluation : AuditableEntity
{
    public string? MaPhieu { get; set; }                            // Auto-gen khi create (format tính sau)
    public PurchaseEvaluationType Type { get; set; }
    public PurchaseEvaluationPhase Phase { get; set; } = PurchaseEvaluationPhase.DangSoanThao;

    public string TenGoiThau { get; set; } = string.Empty;          // "Cung cấp bê tông"
    public Guid ProjectId { get; set; }                              // Dự án (FK Projects)
    public Guid? WorkItemId { get; set; }                            // [Mig 49 S57bis] Hạng mục công việc — scalar loose-Guid (KHÔNG navigation, KHÔNG FK vật lý — convention PE giống ProjectId/SelectedSupplierId). DB nullable cho 4 phiếu cũ; flow create mới validator NotEmpty.
    public Guid? DepartmentId { get; set; }
    public Guid? DrafterUserId { get; set; }                         // QS/NV.PB soạn
    public string? DiaDiem { get; set; }                             // Lô K, KCN Lộc An...
    public string? MoTa { get; set; }
    public string? HoSoLink { get; set; }                            // [HoSoLink] 1 hyperlink tới thư mục hồ sơ trên NAS công ty (anh Kiệt) — paste link thư mục, FE render hyperlink bấm-mở. Nullable, max 1000. KHÔNG entity con / bảng mới.

    public Guid? WorkflowDefinitionId { get; set; }                  // [LEGACY Mig 21] Pinned at create — config y như HĐ
    public Guid? ApprovalWorkflowId { get; set; }                    // [Mig 23 Session 17] Pin schema mới ApprovalWorkflowsV2
    public DateTime? SlaDeadline { get; set; }
    public bool SlaWarningSent { get; set; }

    public Guid? SelectedSupplierId { get; set; }                    // NCC thắng — null tới khi DaDuyet
    public string? PaymentTerms { get; set; }                        // JSON {tamUng, thanhToanTam, quyetToan, baoHanh, hanMucCongNo, danhGia}

    public Guid? ContractId { get; set; }                            // FK Contracts — set khi user gen HĐ từ phiếu

    // [S61 Mig 50] Ngân sách PE theo Excel anh Kiệt — thay BudgetId/BudgetManual*
    // cũ (drop cùng Mig 50, data BudgetManualAmount migrate → BudgetPeriodAmount).
    // - BudgetPeriodAmount: "Ngân sách - kỳ này" (row 3) — NGƯỜI SOẠN nhập khi
    //   soạn phiếu. Submit guard yêu cầu > 0.
    // - ExpectedRemainingAmount: "Giá trị thực hiện dự kiến còn lại" (row 8) —
    //   tự nhập; null = FE default theo NS còn lại (row 7).
    // Ngân sách FULL gói thầu nằm ở PeWorkItemBudget (per cặp Project × WorkItem).
    public decimal? BudgetPeriodAmount { get; set; }
    public decimal? ExpectedRemainingAmount { get; set; }

    // [Mig 59 2026-06-24 — anh Kiệt FDC / CCM] "NS kỳ này" của CỘT CCM (Section B
    // THỰC HIỆN tách 3 cột Dự án|PRO|CCM). PRO dùng BudgetPeriodAmount sẵn có; CCM
    // nhập cột riêng độc-lập, đối chiếu full-CCM = (InitialAmount+AdjustmentAmount)
    // ở PeWorkItemBudget. Nhập qua endpoint riêng role-gate Admin|CostControl,
    // absolute-set (null=clear). Budget=0 hợp lệ. KHÔNG submit-guard (guard chỉ trên
    // BudgetPeriodAmount của PRO).
    public decimal? CcmBudgetPeriodAmount { get; set; }

    // Smart reject (Phase 9 — Migration 16): Phase nguồn khi reject. Drafter
    // sửa lại + trình lại → quay về RejectedFromPhase thay vì đi tuần tự.
    public PurchaseEvaluationPhase? RejectedFromPhase { get; set; }

    // Flat workflow tracking (Session 16 — Migration 21):
    // - CurrentWorkflowStepIndex: 0-based index của step đang chờ approver
    //   (khi Phase=ChoDuyet). Null khi DangSoanThao/DaDuyet/TuChoi/TraLai.
    // - RejectedAtStepIndex: [DEPRECATED Session 17] snapshot index tại Trả lại.
    //   Field giữ DB column cho data cũ — Service không set value mới.
    public int? CurrentWorkflowStepIndex { get; set; }
    public int? RejectedAtStepIndex { get; set; }

    // V2 schema tracking (Session 17 — Migration 24):
    // - CurrentApprovalLevelOrder: Cấp đang chờ duyệt (1/2/3) trong Step
    //   hiện tại khi pin ApprovalWorkflowId. Null khi V1 legacy hoặc terminal.
    public int? CurrentApprovalLevelOrder { get; set; }

    // [S69 2026-06-17] Cờ gấp (urgent) — anh Kiệt FDC: PRO (role Procurement) bật cờ
    // ĐỎ, CCM (role CostControl) bật cờ XANH — 2 cờ độc lập per-vai. Gói gấp → notify
    // CEO (Director) biết gấp + xử lý sớm. VISIBILITY-ONLY: KHÔNG đổi luồng duyệt (ai
    // duyệt vẫn theo ngưỡng giá trị) — chỉ badge + thông báo + ưu tiên list. Toggle qua
    // endpoint theo role actor (PRO ↔ IsUrgentByPro, CCM ↔ IsUrgentByCcm).
    public bool IsUrgentByPro { get; set; }
    public bool IsUrgentByCcm { get; set; }

    // [Mig 54 2026-06-18 — anh Kiệt FDC] Giá đề xuất tại mục "c. Giá chào thầu" — NGOÀI
    // giá NCC báo lên (WinnerQuoteTotal = SUM báo giá của NCC được chọn, computed). PRO
    // (role Procurement) nhập dải Min/Max — nếu chỉ 1 trong 2 → hiểu là giá chốt đó. CCM
    // (role CostControl) nhập 1 giá đề xuất để CEO nhìn + duyệt theo. Role-gate qua
    // UpdatePeSuggestedPrice{Pro,Ccm}Command (mirror ngân sách PRO/CCM Mig 50).
    public decimal? ProSuggestedMinPrice { get; set; }
    public decimal? ProSuggestedMaxPrice { get; set; }
    public decimal? CcmSuggestedPrice { get; set; }

    // [Mig 57 2026-06-19 — anh Kiệt FDC + Tra Sol] Ghi chú GIẢI THÍCH giá đề xuất — vì
    // dải Min/Max của PRO (và 1 giá CCM) cần ghi rõ LÝ DO chọn min vs max để CEO duyệt
    // có ngữ cảnh. Mirror ProSuggestedPriceNote ↔ PRO, CcmSuggestedPriceNote ↔ CCM. Set
    // absolute (null=clear) trong cùng handler nhập giá, role-gate y như giá. Nullable,
    // max 1000. KHÔNG entity con / bảng mới (mirror HoSoLink + CcmNote pattern).
    public string? ProSuggestedPriceNote { get; set; }
    public string? CcmSuggestedPriceNote { get; set; }

    // [Mig 54] Giá CHỐT người duyệt cấp cuối chọn khi duyệt (① "duyệt theo giá đề xuất").
    // Set tại MỌI nhánh DaDuyet của ApproveV2Async (terminal + CCM-delegation-finalize).
    // ApprovedPriceSource ∈ {Ncc, ProMin, ProMax, Ccm, ProMinMax} = nguồn giá đã chọn; Amount =
    // snapshot giá trị lúc duyệt. Null cho phiếu duyệt trước Mig 54 hoặc luồng V1 legacy.
    public decimal? ApprovedPriceAmount { get; set; }
    public string? ApprovedPriceSource { get; set; }

    // [S117 2026-07-14 — anh Kiệt FDC] "Duyệt theo KHOẢNG": khi PRO có cả Min & Max, người duyệt
    // chọn CẢ HAI (source="ProMinMax") → ApprovedPriceAmount = Min, ApprovedPriceMaxAmount = Max.
    // Bất-biến: ApprovedPriceMaxAmount != null ⟺ ApprovedPriceSource == "ProMinMax". Source đơn → null
    // (giữ nguyên Mig 54). Range thuần record-of-decision hiển thị — HĐ-gen KHÔNG đọc (GiaTri = SUM
    // báo giá NCC được chọn). Mig 66 AddColumn nullable, no backfill (phiếu cũ nguyên vẹn).
    public decimal? ApprovedPriceMaxAmount { get; set; }

    // [S97 2026-07-01 — anh Kiệt FDC] RUNTIME fact: phiếu này ĐÃ kết thúc sớm bằng level-finalize
    // ("Duyệt thay CEO", short-circuit TRƯỚC cấp cuối/CEO)? Set true DUY NHẤT ở nhánh finalize của
    // ApproveV2Async. Default false = phiếu đi HẾT quy trình (qua CEO). Phân biệt CONFIG "workflow
    // CÓ cấp finalize" vs RUNTIME "phiếu NÀY finalize sớm" — EndsBeforeCeo (display) đọc field này
    // cho phiếu DaDuyet để phiếu-đã-lên-CEO KHÔNG còn hiện sai "không qua CEO" (bug anh Kiệt S97).
    public bool EndedByLevelFinalize { get; set; }

    // [S133 2026-07-17 — anh Kiệt FDC] BẤT BIẾN ngân sách phiếu ĐÃ DUYỆT: snapshot bộ số
    // NS-gói-thầu (matrix PRO/CCM từ PeWorkItemBudgets + 4 số lũy kế phiếu-trước) vào 11 cột
    // này TẠI thời điểm chuyển DaDuyet (ApplyBudgetSnapshotOnFinalizeAsync gọi ở MỌI nhánh
    // finalize). Phiếu DaDuyet serve từ snapshot (display-gate `frozen` — GetPurchaseEvaluationQuery),
    // phiếu chưa duyệt đọc LIVE record PeWorkItemBudgets. PeWorkItemBudgets + cơ chế nhập PRO/CCM
    // GIỮ NGUYÊN (record dùng chung mọi phiếu cùng cặp — sửa được tự do khi phiếu chưa duyệt).
    // SnapshotAt != null (trên phiếu DaDuyet) = cờ "đã chốt". Backfill Mig 67 cho DaDuyet cũ = live.
    // NAMING: Ccm* = cột CCM (PeWorkItemBudget.InitialAmount/AdjustmentAmount); Pro* = cột PRO.
    public decimal? ApprovedBudgetProInitialAmount { get; set; }
    public decimal? ApprovedBudgetProAdjustmentAmount { get; set; }
    public string? ApprovedBudgetProNote { get; set; }
    public decimal? ApprovedBudgetCcmInitialAmount { get; set; }
    public decimal? ApprovedBudgetCcmAdjustmentAmount { get; set; }
    public string? ApprovedBudgetCcmNote { get; set; }
    public decimal? ApprovedBudgetPrevSubmittedTotal { get; set; }
    public int? ApprovedBudgetPrevSubmittedCount { get; set; }
    public decimal? ApprovedBudgetPrevSelectedTotal { get; set; }
    public int? ApprovedBudgetPrevSelectedCount { get; set; }
    public DateTime? ApprovedBudgetSnapshotAt { get; set; }

    public List<PurchaseEvaluationSupplier> Suppliers { get; set; } = new();
    public List<PurchaseEvaluationDetail> Details { get; set; } = new();
    public List<PurchaseEvaluationQuote> Quotes { get; set; } = new();
    public List<PurchaseEvaluationApproval> Approvals { get; set; } = new();
    public List<PurchaseEvaluationChangelog> Changelogs { get; set; } = new();
    public List<PurchaseEvaluationAttachment> Attachments { get; set; } = new();
    public List<PurchaseEvaluationDepartmentOpinion> DepartmentOpinions { get; set; } = new();
    public List<PurchaseEvaluationDepartmentApproval> DepartmentApprovals { get; set; } = new();

    // Mig 26 (Session 19) — Ý kiến cấp duyệt V2 dynamic. UPSERT auto từ
    // ApproveV2Async theo Cấp hiện tại. Section 5 FE render dynamic theo
    // flow.steps[].levels[]. Phiếu V1 (WorkflowDefinitionId) KHÔNG dùng.
    public List<PurchaseEvaluationLevelOpinion> LevelOpinions { get; set; } = new();
}
