using CartWise.Domain.Enums;

namespace CartWise.Domain.Entities;

public class Purchase
{
    private readonly List<PurchaseItem> _items = [];

    public Guid PurchaseId { get; private set; }

    public Guid HouseholdId { get; private set; }

    public Guid? StoreLocationId { get; private set; }

    public string PurchasedByUserId { get; private set; } = null!;

    public DateTime PurchasedUtc { get; private set; }

    public decimal? Subtotal { get; private set; }

    public decimal? Tax { get; private set; }

    public decimal? Total { get; private set; }

    public PurchaseSourceType SourceType { get; private set; }

    public DateTime CreatedUtc { get; private set; }

    public IReadOnlyCollection<PurchaseItem> Items => _items.AsReadOnly();

    private Purchase()
    {
    }

    public Purchase(
        Guid householdId,
        string purchasedByUserId,
        DateTime purchasedUtc,
        DateTime createdUtc,
        PurchaseSourceType sourceType = PurchaseSourceType.Manual,
        Guid? storeLocationId = null)
    {
        if (householdId == Guid.Empty)
        {
            throw new ArgumentException("HouseholdId is required.", nameof(householdId));
        }

        if (string.IsNullOrWhiteSpace(purchasedByUserId))
        {
            throw new ArgumentException("PurchasedByUserId is required.", nameof(purchasedByUserId));
        }

        PurchaseId = Guid.NewGuid();
        HouseholdId = householdId;
        StoreLocationId = storeLocationId;
        PurchasedByUserId = purchasedByUserId;
        PurchasedUtc = purchasedUtc;
        SourceType = sourceType;
        CreatedUtc = createdUtc;
    }

    public bool IsCompleted => Subtotal.HasValue;

    public PurchaseItem AddItem(
        string description,
        decimal linePrice,
        DateTime addedUtc,
        decimal quantity = 1m,
        string? unit = null,
        Guid? productId = null,
        Guid? groceryConceptId = null,
        Guid? shoppingListItemId = null,
        decimal? unitPrice = null)
    {
        if (IsCompleted)
        {
            throw new InvalidOperationException("Cannot add items to a completed purchase.");
        }

        var item = new PurchaseItem(PurchaseId, description, linePrice, addedUtc, quantity, unit, productId, groceryConceptId, shoppingListItemId, unitPrice);
        _items.Add(item);
        return item;
    }

    public void Complete(decimal? tax = null)
    {
        if (IsCompleted)
        {
            throw new InvalidOperationException("Purchase is already completed.");
        }

        Subtotal = _items.Sum(i => i.LinePrice);
        Tax = tax;
        Total = Subtotal + (tax ?? 0m);
    }
}
