namespace WalletService.Domain.AggregatesModel.WalletAggregate;

using WalletService.Domain.Exceptions;
using WalletService.Domain.SeedWork;

/// <summary>
/// EN: Represents a balance for a specific currency type within a wallet.
/// VI: Đại diện cho số dư của một loại tiền tệ cụ thể trong ví.
/// </summary>
/// <remarks>
/// EN: WalletItem is a child entity of Wallet aggregate, not an aggregate root.
/// Each wallet can have multiple WalletItems, one for each currency type.
/// VI: WalletItem là entity con của Wallet aggregate, không phải aggregate root.
/// Mỗi ví có thể có nhiều WalletItem, một cho mỗi loại tiền tệ.
/// </remarks>
public class WalletItem : Entity
{
    /// <summary>
    /// EN: Parent wallet ID.
    /// VI: ID của ví cha.
    /// </summary>
    public Guid WalletId { get; private set; }

    /// <summary>
    /// EN: Currency type ID for EF Core.
    /// VI: ID loại tiền tệ cho EF Core.
    /// </summary>
    public int CurrencyTypeId { get; private set; }

    /// <summary>
    /// EN: Currency type.
    /// VI: Loại tiền tệ.
    /// </summary>
    public CurrencyType CurrencyType { get; private set; } = null!;

    /// <summary>
    /// EN: Current balance amount.
    /// VI: Số dư hiện tại.
    /// </summary>
    public decimal Balance { get; private set; }

    /// <summary>
    /// EN: Creation timestamp.
    /// VI: Thời điểm tạo.
    /// </summary>
    public DateTime CreatedAt { get; private set; }

    /// <summary>
    /// EN: Last update timestamp.
    /// VI: Thời điểm cập nhật cuối.
    /// </summary>
    public DateTime UpdatedAt { get; private set; }

    protected WalletItem() { }

    /// <summary>
    /// EN: Create a new wallet item for a specific currency.
    /// VI: Tạo wallet item mới cho một loại tiền tệ cụ thể.
    /// </summary>
    public WalletItem(Guid walletId, CurrencyType currencyType, decimal initialBalance = 0)
    {
        if (initialBalance < 0)
            throw new WalletDomainException("Initial balance cannot be negative");

        Id = Guid.NewGuid();
        WalletId = walletId;
        CurrencyType = currencyType;
        CurrencyTypeId = currencyType.Id;
        Balance = initialBalance;
        CreatedAt = DateTime.UtcNow;
        UpdatedAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Add amount to balance.
    /// VI: Cộng số tiền vào số dư.
    /// </summary>
    public void Add(decimal amount)
    {
        if (amount <= 0)
            throw new WalletDomainException("Amount to add must be greater than zero");

        Balance += amount;
        UpdatedAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Subtract amount from balance.
    /// VI: Trừ số tiền từ số dư.
    /// </summary>
    public void Subtract(decimal amount)
    {
        if (amount <= 0)
            throw new WalletDomainException("Amount to subtract must be greater than zero");

        if (Balance < amount)
            throw new InsufficientBalanceException(Balance, amount);

        Balance -= amount;
        UpdatedAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Check if balance is sufficient for an amount.
    /// VI: Kiểm tra số dư có đủ cho một số tiền không.
    /// </summary>
    public bool HasSufficientBalance(decimal amount) => Balance >= amount;

    /// <summary>
    /// EN: Get formatted balance string.
    /// VI: Lấy chuỗi số dư đã được format.
    /// </summary>
    public override string ToString() => $"{Balance:N2} {CurrencyType.Name}";
}
