using ERPCore.Domain.Enums;

namespace ERPCore.Domain.Entities;

/// <summary>
/// GRN line (FR-GRN-04..08). <see cref="UnitCost"/> is the gross cost received at:
/// entered on the line, defaulting to the PO price when omitted (a per-receipt price
/// override is now permitted — see docs/02-SECURITY C.3, revised). <see cref="PoUnitPrice"/>
/// snapshots the PO price at receipt so the variance survives later PO edits.
/// <see cref="NetUnitCost"/> = unitCost after trade discount — this is what the FIFO layer
/// costs at (VAT never enters stock value; it is recoverable input tax).
/// <see cref="ReceivedValue"/> = qty × netUnitCost (after discount, before VAT).
/// <see cref="HoldStatus"/> gates issuability. Model: docs/10 Part C.3.
/// </summary>
public class GrnLine
{
    public int GrnLineId { get; set; }

    public int GrnId { get; set; }
    public Grn? Grn { get; set; }

    public int? PoLineId { get; set; }
    public PoLine? PoLine { get; set; }

    public int ItemId { get; set; }
    public Item? Item { get; set; }

    public int? BinId { get; set; }
    public Bin? Bin { get; set; }

    public int? BatchId { get; set; }
    public Batch? Batch { get; set; }

    public decimal Qty { get; set; }

    /// <summary>Gross unit cost received at (entered, or PO price when omitted).</summary>
    public decimal UnitCost { get; set; }

    /// <summary>Snapshot of the PO line price at receipt; null for direct receipts.</summary>
    public decimal? PoUnitPrice { get; set; }

    /// <summary>Trade discount percentage (0–100), entered.</summary>
    public decimal DiscountPct { get; set; }

    /// <summary>UnitCost × (1 − DiscountPct/100) — the inventory (FIFO layer) cost.</summary>
    public decimal NetUnitCost { get; set; }

    /// <summary>VAT percentage (0–100), entered. Recoverable — does not affect stock value.</summary>
    public decimal VatPct { get; set; }

    /// <summary>Qty × NetUnitCost × VatPct/100.</summary>
    public decimal VatAmount { get; set; }

    /// <summary>Qty × NetUnitCost (after discount, before VAT).</summary>
    public decimal ReceivedValue { get; set; }

    /// <summary>Qty × NetUnitCost + VatAmount — payable to the vendor.</summary>
    public decimal LineTotal { get; set; }

    public HoldStatus HoldStatus { get; set; } = HoldStatus.Available;

    /// <summary>
    /// One row per received unit when <see cref="Item.Warranty"/> is
    /// <see cref="Enums.Warranty.Warranty"/> — count must equal <see cref="Qty"/>.
    /// Empty for a non-warranty item.
    /// </summary>
    public ICollection<GrnLineWarrantyNumber> WarrantyNumbers { get; set; } = new List<GrnLineWarrantyNumber>();
}
