namespace BudgetApp.Domain.Models;

/// <summary>
/// Abstract base class for all budget types.
/// Represents a container for money with a balance that cannot be negative.
/// </summary>
public abstract class Budget
{
    public Guid Id { get; protected set; }
    public string Name { get; protected set; }
    public Money Balance { get; protected set; }

    protected Budget(Guid id, string name, Money initialBalance)
    {
        if (string.IsNullOrWhiteSpace(name))
            throw new ArgumentException("Name cannot be null or empty.", nameof(name));
        
        if (initialBalance == null)
            throw new ArgumentNullException(nameof(initialBalance));

        Id = id;
        Name = name;
        Balance = initialBalance;
        ValidateBalance();
    }

    /// <summary>
    /// Adds money to the budget balance.
    /// </summary>
    public void AddMoney(Money amount)
    {
        if (amount == null)
            throw new ArgumentNullException(nameof(amount));
        
        if (Balance.Currency != amount.Currency)
            throw new InvalidOperationException($"Cannot add money with different currency: {Balance.Currency} and {amount.Currency}");

        Balance = Balance.Add(amount);
        ValidateBalance();
    }

    /// <summary>
    /// Removes money from the budget balance.
    /// Ensures balance never becomes negative.
    /// </summary>
    public void RemoveMoney(Money amount)
    {
        if (amount == null)
            throw new ArgumentNullException(nameof(amount));
        
        if (Balance.Currency != amount.Currency)
            throw new InvalidOperationException($"Cannot remove money with different currency: {Balance.Currency} and {amount.Currency}");

        var newBalance = Balance.Subtract(amount);
        Balance = newBalance;
        ValidateBalance();
    }

    /// <summary>
    /// Validates that the balance is never negative.
    /// </summary>
    protected void ValidateBalance()
    {
        if (Balance.Amount < 0)
            throw new InvalidOperationException($"Budget balance cannot be negative. Current balance: {Balance}");
    }
}

