namespace ERPCore.Domain.Entities;

/// <summary>
/// A cashier's end-of-day close-out. Aggregates every <see cref="SalesSlip"/> the
/// cashier posted on <see cref="BusinessDate"/>, freezes them against this record
/// (<see cref="SalesSlip.DayEndId"/>) so a slip can only ever belong to one day-end,
/// and posts one consolidated GL journal entry for the day's revenue/tax/COGS —
/// the sales-side equivalent of how <see cref="Grn"/> posts per receipt. Unique per
/// (CashierUserId, BusinessDate): closing twice replays the existing record instead
/// of creating a second one (same idempotent-replay pattern as Grn.ConfirmAsync).
/// </summary>
public class SalesDayEnd
{
    public int SalesDayEndId { get; set; }
    public string DocNo { get; set; } = string.Empty;

    public int CashierUserId { get; set; }
    public User? CashierUser { get; set; }

    /// <summary>The calendar date being closed (matched against each slip's <see cref="SalesSlip.SlipDate"/>, UTC).</summary>
    public DateOnly BusinessDate { get; set; }

    public int SlipCount { get; set; }
    public int BundleCount { get; set; }
    public decimal Subtotal { get; set; }
    public decimal DiscountTotal { get; set; }
    public decimal TaxTotal { get; set; }
    public decimal GrandTotal { get; set; }

    /// <summary>Sum of the FIFO cost consumed for these slips (from <see cref="StockLedger"/>), for the COGS GL lines.</summary>
    public decimal CostOfGoodsSold { get; set; }

    /// <summary>Journal number of the real GL journal entry posted for this close (null when there was nothing to post).</summary>
    public string? GlJournalNo { get; set; }
    public DateTime? GlPostedAt { get; set; }

    public int ClosedBy { get; set; }
    public User? ClosedByUser { get; set; }
    public DateTime ClosedAt { get; set; }

    /// <summary>PostgreSQL xmin-backed optimistic concurrency token.</summary>
    public uint RowVersion { get; set; }

    public ICollection<SalesSlip> Slips { get; set; } = new List<SalesSlip>();
    public ICollection<BundleSale> BundleSales { get; set; } = new List<BundleSale>();
}
