using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using SolutionErp.Application.Common.Models;
using SolutionErp.Application.PurchaseEvaluations;
using SolutionErp.Application.PurchaseEvaluations.Dtos;
using SolutionErp.Application.PurchaseEvaluations.Services;  // WorkflowReturnMode (Plan P S23 t6)
using SolutionErp.Domain.Contracts;
using SolutionErp.Domain.PurchaseEvaluations;

namespace SolutionErp.Api.Controllers;

[ApiController]
[Route("api/purchase-evaluations")]
[Authorize]
public class PurchaseEvaluationsController(IMediator mediator) : ControllerBase
{
    [HttpGet]
    public async Task<ActionResult<PagedResult<PurchaseEvaluationListItemDto>>> List(
        [FromQuery] int page = 1, [FromQuery] int pageSize = 20,
        [FromQuery] string? search = null, [FromQuery] bool sortDesc = true,
        [FromQuery] PurchaseEvaluationType? type = null,
        [FromQuery] PurchaseEvaluationPhase? phase = null,
        [FromQuery] Guid? projectId = null,
        [FromQuery] Guid? approvalWorkflowId = null,
        CancellationToken ct = default)
        => Ok(await mediator.Send(new ListPurchaseEvaluationsQuery(type, phase, projectId, approvalWorkflowId)
        { Page = page, PageSize = pageSize, Search = search, SortDesc = sortDesc }, ct));

    [HttpGet("inbox")]
    public async Task<ActionResult<List<PurchaseEvaluationListItemDto>>> Inbox(
        [FromQuery] PurchaseEvaluationType? type = null,
        [FromQuery] Guid? approvalWorkflowId = null,
        CancellationToken ct = default)
        => Ok(await mediator.Send(new GetMyPurchaseEvaluationInboxQuery(type, approvalWorkflowId), ct));

    [HttpGet("{id:guid}")]
    public async Task<ActionResult<PurchaseEvaluationDetailBundleDto>> Get(Guid id, CancellationToken ct)
        => Ok(await mediator.Send(new GetPurchaseEvaluationQuery(id), ct));

    [HttpPost]
    public async Task<ActionResult<object>> Create([FromBody] CreatePurchaseEvaluationCommand cmd, CancellationToken ct)
    {
        var id = await mediator.Send(cmd, ct);
        return CreatedAtAction(nameof(Get), new { id }, new { id });
    }

    [HttpPut("{id:guid}")]
    public async Task<IActionResult> Update(Guid id, [FromBody] UpdatePurchaseEvaluationDraftCommand cmd, CancellationToken ct)
    {
        if (id != cmd.Id) return BadRequest(new { detail = "ID không khớp" });
        await mediator.Send(cmd, ct);
        return NoContent();
    }

    // S22+4 — Feature 2: Section "Điều chỉnh ngân sách" tách endpoint riêng.
    // Cho phép Drafter (DangSoanThao/TraLai) OR Approver currentLevel (ChoDuyet)
    // OR Admin. [S61 Mig 50] Body đổi sang 2 field mới (NS kỳ này + dự kiến còn
    // lại) — BudgetId/BudgetManual* cũ DROP cùng module Budget. Absolute-set.
    [HttpPatch("{id:guid}/budget-adjust")]
    public async Task<IActionResult> AdjustBudget(Guid id, [FromBody] AdjustBudgetBody body, CancellationToken ct)
    {
        await mediator.Send(new AdjustPurchaseEvaluationBudgetCommand(
            id, body.BudgetPeriodAmount, body.ExpectedRemainingAmount), ct);
        return NoContent();
    }
    public record AdjustBudgetBody(decimal? BudgetPeriodAmount, decimal? ExpectedRemainingAmount);

    // [S61 Mig 50] Ngân sách gói thầu per cặp (Dự án, Hạng mục) — nhập theo ROLE.
    // Class [Authorize] any-auth; handler fine-gained Forbidden (PRO=Procurement,
    // CCM=CostControl, Admin cả 2 — pattern AssignItTicketHandler S54).
    [HttpPut("{id:guid}/budget/pro")]
    public async Task<IActionResult> UpdateBudgetPro(Guid id, [FromBody] BudgetProBody body, CancellationToken ct)
    {
        await mediator.Send(new UpdatePeBudgetProCommand(id, body.ProInitialAmount, body.ProAdjustmentAmount, body.ProNote), ct);
        return NoContent();
    }
    public record BudgetProBody(decimal? ProInitialAmount, decimal? ProAdjustmentAmount, string? ProNote);

    [HttpPut("{id:guid}/budget/ccm")]
    public async Task<IActionResult> UpdateBudgetCcm(Guid id, [FromBody] BudgetCcmBody body, CancellationToken ct)
    {
        await mediator.Send(new UpdatePeBudgetCcmCommand(id, body.InitialAmount, body.AdjustmentAmount, body.CcmNote), ct);
        return NoContent();
    }
    public record BudgetCcmBody(decimal? InitialAmount, decimal? AdjustmentAmount, string? CcmNote);

    // [S69 2026-06-17] Cờ gấp (urgent) — anh Kiệt FDC. Class [Authorize] any-auth;
    // handler fine-grained Forbidden theo role (PRO=Procurement set cờ đỏ, CCM=
    // CostControl set cờ xanh, Admin cả 2). Bật → notify CEO (Director). Visibility-only.
    [HttpPut("{id:guid}/urgent")]
    public async Task<IActionResult> SetUrgent(Guid id, [FromBody] SetUrgentBody body, CancellationToken ct)
    {
        await mediator.Send(new SetPurchaseEvaluationUrgentCommand(id, body.IsUrgent), ct);
        return NoContent();
    }
    public record SetUrgentBody(bool IsUrgent);

    // [Mig 54 2026-06-18 — anh Kiệt FDC] Nhập GIÁ ĐỀ XUẤT tại "c. Giá chào thầu" theo
    // role. Class [Authorize] any-auth; handler fine-grained Forbidden (PRO=Procurement
    // Min/Max, CCM=CostControl 1 giá, Admin cả 2). Set per-phiếu. Absolute-set (null=clear).
    [HttpPut("{id:guid}/suggested-price/pro")]
    public async Task<IActionResult> SetSuggestedPricePro(Guid id, [FromBody] SuggestedPriceProBody body, CancellationToken ct)
    {
        await mediator.Send(new UpdatePeSuggestedPriceProCommand(id, body.MinPrice, body.MaxPrice, body.Note), ct);
        return NoContent();
    }
    public record SuggestedPriceProBody(decimal? MinPrice, decimal? MaxPrice, string? Note);

    [HttpPut("{id:guid}/suggested-price/ccm")]
    public async Task<IActionResult> SetSuggestedPriceCcm(Guid id, [FromBody] SuggestedPriceCcmBody body, CancellationToken ct)
    {
        await mediator.Send(new UpdatePeSuggestedPriceCcmCommand(id, body.CcmPrice, body.Note), ct);
        return NoContent();
    }
    public record SuggestedPriceCcmBody(decimal? CcmPrice, string? Note);

    // [Mig 59 2026-06-24 — anh Kiệt FDC / CCM] "NS kỳ này" cột CCM (Section B THỰC HIỆN
    // tách 3 cột Dự án|PRO|CCM). PRO dùng /budget-adjust sẵn có; CCM nhập cột riêng.
    // Class [Authorize] any-auth; handler fine-grained Forbidden (CCM=CostControl | Admin).
    // Absolute-set (null=clear). Budget=0 hợp lệ.
    [HttpPatch("{id:guid}/budget/ccm-period")]
    public async Task<IActionResult> SetCcmBudgetPeriod(Guid id, [FromBody] CcmBudgetPeriodBody body, CancellationToken ct)
    {
        await mediator.Send(new SetPeCcmBudgetPeriodCommand(id, body.CcmBudgetPeriodAmount), ct);
        return NoContent();
    }
    public record CcmBudgetPeriodBody(decimal? CcmBudgetPeriodAmount);

    [HttpPost("{id:guid}/transitions")]
    public async Task<IActionResult> Transition(Guid id, [FromBody] TransitionPeBody body, CancellationToken ct)
    {
        // Plan P S23 t6 (2026-05-15) — Pass 7 fields (incl 3 new F1+F2 fields).
        // Pre-fix bug: body record + Send call drop ReturnMode/ReturnTargetUserId/
        // SkipToFinal → handler nhận default Drafter mode + skipToFinal=false →
        // F1 Assignee/OneLevel/OneStep + F2 skip thẳng KHÔNG hoạt động từ FE.
        // Root cause bro UAT 2026-05-15 "Trả lại Người chỉ định fail".
        await mediator.Send(new TransitionPurchaseEvaluationCommand(
            id, body.TargetPhase, body.Decision, body.Comment,
            body.ReturnMode, body.ReturnTargetUserId, body.SkipToFinal,
            body.FinalizeByCcmDelegation, body.ApprovedPriceAmount, body.ApprovedPriceSource,
            body.ApprovedPriceMaxAmount, body.ApplyLevelFinalize), ct);
        return NoContent();
    }

    // 🔴 [S155 đợt 2 — 7a] ĐƯỜNG XÓA NHÁP: GIỮ NGUYÊN, KHÔNG gắn policy.
    // Gắn `[Authorize(Policy="PurchaseEvaluations.Delete")]` vào đây = role `Drafter` MẤT
    // quyền xóa nháp của chính mình (đo thật DB Dev: 11/13 role `CanDelete=0`;
    // `DbInitializer.cs:2515` chỉ cấp DeptManager) ⇒ regression trên chức năng đang sống.
    // Rào của đường này vẫn là PHASE (`{DangSoanThao, TuChoi}`).
    [HttpDelete("{id:guid}")]
    public async Task<IActionResult> Delete(Guid id, CancellationToken ct)
    {
        await mediator.Send(new DeletePurchaseEvaluationCommand(id), ct);
        return NoContent();
    }

    // [S155 đợt 2 — 7b] ĐƯỜNG XÓA KHI ĐANG DUYỆT (mới). Endpoint RIÊNG để giữ đường xóa
    // nháp ở trên nguyên vẹn.
    //
    // 🔴 CỐ Ý KHÔNG có `[Authorize(Policy=...)]` — owner chốt 2026-07-27 sau khi reviewer
    // ĐO trên DB: mọi vai đang thật sự làm người duyệt (`Procurement`, `CostControl`, …)
    // đều `CanDelete = 0`, và 2 seeder KHÔNG BAO GIỜ nâng cờ đó (`DbInitializer.cs:2139-2140`
    // chỉ nâng Read/Create; `:2538` bỏ qua hàng đã tồn tại) ⇒ gắn policy vào là **403 với
    // đúng người cần dùng**, mà FE gate cùng quyền nên **không thấy nút, không thấy lỗi**
    // (gotcha #44 — 403 im lặng).
    //
    // Nguồn quyền THẬT của đường này = **3 rào nghiệp vụ trong handler** (`PeSoftDeleteFeatures.cs`):
    //   (i) phase == ChoDuyet · (ii) ĐÚNG LƯỢT actor · (iii) `matchingLevel.AllowApproverDelete`
    // Rào (iii) là cờ F6 **per-NGƯỜI** — admin tick đích danh từng NV trong Designer quy trình.
    // Đó CHẶT HƠN permission theo vai (vai gộp nhiều người; cờ chỉ đúng một người, đúng một Cấp).
    // Đây KHÔNG phải "bỏ authz": handler có `ICurrentUser` và ném Forbidden — đúng khuôn cả
    // controller này vẫn dùng ("class [Authorize] any-auth; handler fine-grained Forbidden",
    // xem chú thích `:69-71`, `:88-90`, `:120`).
    // ⚠️ Hệ quả phải nhớ: FE **KHÔNG** được gate nút này bằng `can(..., 'Delete')` nữa —
    // gate đó sẽ ẩn nút với đúng người có quyền. Đã gỡ ở `PeWorkflowPanel.tsx`.
    [HttpDelete("{id:guid}/by-approver")]
    public async Task<IActionResult> DeleteByApprover(Guid id, [FromBody] DeleteByApproverBody? body, CancellationToken ct)
    {
        await mediator.Send(new DeletePurchaseEvaluationByApproverCommand(id, body?.Reason), ct);
        return NoContent();
    }
    public record DeleteByApproverBody(string? Reason);

    // [S155 đợt 2 — mục 8] List phiếu ĐÃ XÓA (màn "Đã xóa", chỉ-xem). Handler RIÊNG là chỗ
    // DUY NHẤT dùng `IgnoreQueryFilters()` trong toàn `src/Backend` (D3).
    [HttpGet("deleted")]
    [Authorize(Policy = "PurchaseEvaluations.Read")]
    public async Task<ActionResult<PagedResult<PurchaseEvaluationListItemDto>>> ListDeleted(
        [FromQuery] PurchaseEvaluationType? type = null,
        [FromQuery] int page = 1, [FromQuery] int pageSize = 20,
        [FromQuery] string? search = null, [FromQuery] bool sortDesc = true,
        CancellationToken ct = default)
        => Ok(await mediator.Send(new ListDeletedPurchaseEvaluationsQuery(type)
        { Page = page, PageSize = pageSize, Search = search, SortDesc = sortDesc }, ct));

    // ========== Suppliers (N:M) ==========

    [HttpPost("{id:guid}/suppliers")]
    public async Task<ActionResult<object>> AddSupplier(Guid id, [FromBody] AddSupplierBody body, CancellationToken ct)
    {
        var newId = await mediator.Send(new AddPurchaseEvaluationSupplierCommand(
            id, body.SupplierId, body.DisplayName, body.ContactName, body.ContactEmail,
            body.ContactPhone, body.PaymentTermText, body.Note), ct);
        return Ok(new { id = newId });
    }

    [HttpPut("{id:guid}/suppliers/{supplierRowId:guid}")]
    public async Task<IActionResult> UpdateSupplier(Guid id, Guid supplierRowId, [FromBody] AddSupplierBody body, CancellationToken ct)
    {
        await mediator.Send(new UpdatePurchaseEvaluationSupplierCommand(
            id, supplierRowId, body.DisplayName, body.ContactName, body.ContactEmail,
            body.ContactPhone, body.PaymentTermText, body.Note), ct);
        return NoContent();
    }

    [HttpDelete("{id:guid}/suppliers/{supplierRowId:guid}")]
    public async Task<IActionResult> RemoveSupplier(Guid id, Guid supplierRowId, CancellationToken ct)
    {
        await mediator.Send(new RemovePurchaseEvaluationSupplierCommand(id, supplierRowId), ct);
        return NoContent();
    }

    [HttpPost("{id:guid}/select-winner")]
    public async Task<IActionResult> SelectWinner(Guid id, [FromBody] SelectWinnerBody body, CancellationToken ct)
    {
        await mediator.Send(new SelectPurchaseEvaluationWinnerCommand(
            id, body.DetailId, body.SupplierIds ?? Array.Empty<Guid>()), ct);
        return NoContent();
    }

    // ========== Details (hạng mục + ngân sách) ==========

    [HttpPost("{id:guid}/details")]
    public async Task<ActionResult<object>> AddDetail(Guid id, [FromBody] DetailBody body, CancellationToken ct)
    {
        var newId = await mediator.Send(new AddPurchaseEvaluationDetailCommand(
            id, body.GroupCode, body.GroupName, body.ItemCode, body.NoiDung, body.DonViTinh,
            body.KhoiLuongNganSach, body.KhoiLuongThiCong, body.DonGiaNganSach,
            body.ThanhTienNganSach, body.GhiChu), ct);
        return Ok(new { id = newId });
    }

    [HttpPut("{id:guid}/details/{detailId:guid}")]
    public async Task<IActionResult> UpdateDetail(Guid id, Guid detailId, [FromBody] DetailBody body, CancellationToken ct)
    {
        await mediator.Send(new UpdatePurchaseEvaluationDetailCommand(
            id, detailId, body.GroupCode, body.GroupName, body.ItemCode, body.NoiDung, body.DonViTinh,
            body.KhoiLuongNganSach, body.KhoiLuongThiCong, body.DonGiaNganSach,
            body.ThanhTienNganSach, body.GhiChu), ct);
        return NoContent();
    }

    [HttpDelete("{id:guid}/details/{detailId:guid}")]
    public async Task<IActionResult> DeleteDetail(Guid id, Guid detailId, CancellationToken ct)
    {
        await mediator.Send(new DeletePurchaseEvaluationDetailCommand(id, detailId), ct);
        return NoContent();
    }

    // ========== Quotes (báo giá per NCC per Detail) ==========

    [HttpPost("{id:guid}/quotes")]
    public async Task<ActionResult<object>> UpsertQuote(Guid id, [FromBody] QuoteBody body, CancellationToken ct)
    {
        var qid = await mediator.Send(new UpsertPurchaseEvaluationQuoteCommand(
            id, body.PurchaseEvaluationDetailId, body.PurchaseEvaluationSupplierId,
            body.BgVat, body.ChuaVat, body.ThanhTien, body.IsSelected, body.Note), ct);
        return Ok(new { id = qid });
    }

    [HttpDelete("{id:guid}/quotes/{quoteId:guid}")]
    public async Task<IActionResult> DeleteQuote(Guid id, Guid quoteId, CancellationToken ct)
    {
        await mediator.Send(new DeletePurchaseEvaluationQuoteCommand(id, quoteId), ct);
        return NoContent();
    }

    // ========== Changelogs ==========

    [HttpGet("{id:guid}/changelogs")]
    public async Task<List<PurchaseEvaluationChangelogDto>> GetChangelogs(Guid id, CancellationToken ct)
        => await mediator.Send(new ListPurchaseEvaluationChangelogsQuery(id), ct);

    // ========== Attachments (per-supplier hoặc general) ==========

    // Upload file đính kèm — gắn với NCC cụ thể (supplierRowId) hoặc phiếu tổng.
    [HttpPost("{id:guid}/attachments")]
    [RequestSizeLimit(25_000_000)]
    public async Task<ActionResult<PurchaseEvaluationAttachmentDto>> UploadAttachment(
        Guid id,
        IFormFile file,
        [FromForm] Guid? supplierRowId = null,
        [FromForm] PurchaseEvaluationAttachmentPurpose purpose = PurchaseEvaluationAttachmentPurpose.QuoteDocument,
        [FromForm] string? note = null,
        CancellationToken ct = default)
    {
        if (file is null || file.Length == 0)
            return BadRequest(new { detail = "Chưa chọn file." });

        await using var stream = file.OpenReadStream();
        var dto = await mediator.Send(new UploadPurchaseEvaluationAttachmentCommand(
            id, supplierRowId, file.FileName, file.ContentType, file.Length, stream, purpose, note), ct);
        return Ok(dto);
    }

    [HttpGet("{id:guid}/attachments/{attId:guid}/download")]
    public async Task<IActionResult> DownloadAttachment(Guid id, Guid attId, CancellationToken ct)
    {
        var f = await mediator.Send(new DownloadPurchaseEvaluationAttachmentQuery(id, attId), ct);
        return File(f.Content, f.ContentType, f.FileName);
    }

    // S22+4 — Inline view endpoint cho FE preview modal (PDF iframe, image <img>).
    // Cùng handler download, khác Content-Disposition (inline vs attachment).
    // Permission: same actor scope như GET phiếu (Plan E V2 strict).
    [HttpGet("{id:guid}/attachments/{attId:guid}/view")]
    public async Task<IActionResult> ViewAttachment(Guid id, Guid attId, CancellationToken ct)
    {
        var f = await mediator.Send(new DownloadPurchaseEvaluationAttachmentQuery(id, attId), ct);
        Response.Headers["Content-Disposition"] = $"inline; filename=\"{f.FileName}\"";
        return File(f.Content, f.ContentType);
    }

    [HttpDelete("{id:guid}/attachments/{attId:guid}")]
    public async Task<IActionResult> DeleteAttachment(Guid id, Guid attId, CancellationToken ct)
    {
        await mediator.Send(new DeletePurchaseEvaluationAttachmentCommand(id, attId), ct);
        return NoContent();
    }

    // ========== Kế thừa HĐ ==========

    // List phiếu đã DaDuyet chưa gen HĐ — dùng cho modal "Tạo HĐ từ phiếu"
    [HttpGet("approved-pending-contract")]
    public async Task<List<PurchaseEvaluationListItemDto>> ListApproved(CancellationToken ct)
        => await mediator.Send(new ListApprovedPurchaseEvaluationsQuery(), ct);

    [HttpPost("{id:guid}/create-contract")]
    public async Task<ActionResult<object>> CreateContractFromEvaluation(
        Guid id, [FromBody] CreateContractFromEvaluationBody body, CancellationToken ct)
    {
        var contractIds = await mediator.Send(new CreateContractFromEvaluationCommand(
            id, body.ContractType, body.TenHopDong, body.BypassProcurementAndCCM), ct);
        return Ok(new { contractIds });   // [Mig 58 multi-winner] 1 HĐ / NCC trúng → list ids
    }

    // ========== Ý kiến 4 phòng ban ==========

    // Upsert opinion (Add nếu chưa có, Update text + optional sign).
    [HttpPost("{id:guid}/opinions")]
    public async Task<ActionResult<object>> UpsertOpinion(
        Guid id, [FromBody] OpinionBody body, CancellationToken ct)
    {
        var resultId = await mediator.Send(new UpsertPeDepartmentOpinionCommand(
            id, body.Kind, body.Opinion, body.Sign), ct);
        return Ok(new { id = resultId });
    }

    [HttpDelete("{id:guid}/opinions/{kind}")]
    public async Task<IActionResult> DeleteOpinion(Guid id, PeDepartmentKind kind, CancellationToken ct)
    {
        await mediator.Send(new DeletePeDepartmentOpinionCommand(id, kind), ct);
        return NoContent();
    }

    // ========== 2-stage department approvals (Phase 9 — Migration 16) ==========

    // List approvals progress per phase × dept × stage. FE Workflow Panel
    // hiển thị timeline: phase nào đã review/confirm, ai duyệt khi nào.
    [HttpGet("{id:guid}/department-approvals")]
    public async Task<ActionResult<List<PeDepartmentApprovalDto>>> ListDepartmentApprovals(
        Guid id, CancellationToken ct)
        => Ok(await mediator.Send(new ListPeDepartmentApprovalsQuery(id), ct));
}

public record OpinionBody(PeDepartmentKind Kind, string? Opinion, bool Sign);

public record CreateContractFromEvaluationBody(
    Domain.Contracts.ContractType ContractType,
    string? TenHopDong,
    bool BypassProcurementAndCCM = false);

// Plan P S23 t6 — Mig 28 + Mig 31 (S21 t4 + S23 t1) extended Command record với
// 3 fields F1+F2 (ReturnMode/ReturnTargetUserId/SkipToFinal) nhưng Controller
// body record chỉ giữ 3 fields cũ → ASP.NET deserialization drop → handler
// nhận default Drafter mode + skipToFinal=false → FE F1+F2 wire fail 2 ngày
// prod từ Mig 28 deploy 2026-05-13.
public record TransitionPeBody(
    PurchaseEvaluationPhase TargetPhase,
    ApprovalDecision Decision,
    string? Comment,
    WorkflowReturnMode? ReturnMode = null,     // F1 mode Trả lại
    Guid? ReturnTargetUserId = null,           // F1 Assignee target
    bool SkipToFinal = false,                  // F2 duyệt thẳng Cấp cuối
    // [Mig 54 2026-06-18 — anh Kiệt FDC] ③ CCM duyệt done miễn CEO + ① giá chốt.
    bool FinalizeByCcmDelegation = false,
    decimal? ApprovedPriceAmount = null,
    string? ApprovedPriceSource = null,
    // [S117 2026-07-14 — anh Kiệt FDC] Max của khoảng khi source="ProMinMax" (duyệt theo Min–Max).
    decimal? ApprovedPriceMaxAmount = null,
    // [S96 2026-07-01 — anh Kiệt FDC] false = BỎ tick "Cấp này KẾT THÚC" → vẫn trình CEO.
    bool ApplyLevelFinalize = true);

public record AddSupplierBody(
    Guid SupplierId,
    string? DisplayName, string? ContactName, string? ContactEmail, string? ContactPhone,
    string? PaymentTermText, string? Note);

public record SelectWinnerBody(Guid DetailId, IReadOnlyList<Guid>? SupplierIds);   // [multi-NCC] hạng mục DetailId + tập NCC/TP thắng hạng mục đó; [] hoặc null = bỏ chọn hạng mục này

public record DetailBody(
    string GroupCode, string GroupName, string? ItemCode, string NoiDung, string? DonViTinh,
    decimal KhoiLuongNganSach, decimal KhoiLuongThiCong, decimal DonGiaNganSach,
    decimal ThanhTienNganSach, string? GhiChu);

public record QuoteBody(
    Guid PurchaseEvaluationDetailId, Guid PurchaseEvaluationSupplierId,
    decimal BgVat, decimal ChuaVat, decimal ThanhTien, bool IsSelected, string? Note);
