using MembershipService.Domain.Events;
using MembershipService.Domain.SeedWork;

namespace MembershipService.Domain.AggregatesModel.StampCardAggregate;

/// <summary>
/// EN: Stamp card aggregate root - digital loyalty stamp card for cafe (buy N get 1 free).
/// VI: Stamp card aggregate root - the stamp ky thuat so cho cafe (mua N tang 1).
/// </summary>
public class StampCard : Entity, IAggregateRoot
{
    // EN: Private fields for encapsulation
    // VI: Fields private de dong goi
    private Guid _shopId;
    private Guid _memberId;
    private string _cardName;
    private int _totalStampsRequired;
    private int _currentStamps;
    private bool _isCompleted;
    private bool _rewardClaimed;
    private DateTime _createdAt;
    private DateTime? _completedAt;

    /// <summary>
    /// EN: Shop ID that issued this stamp card.
    /// VI: ID shop da phat hanh stamp card nay.
    /// </summary>
    public Guid ShopId => _shopId;

    /// <summary>
    /// EN: Member ID who owns this stamp card.
    /// VI: ID member so huu stamp card nay.
    /// </summary>
    public Guid MemberId => _memberId;

    /// <summary>
    /// EN: Display name of the stamp card (e.g. "Coffee Lovers Card").
    /// VI: Ten hien thi cua stamp card (vd: "The Coffee Lovers").
    /// </summary>
    public string CardName => _cardName;

    /// <summary>
    /// EN: Total stamps required to complete the card and earn a reward.
    /// VI: Tong so stamp can de hoan thanh card va nhan thuong.
    /// </summary>
    public int TotalStampsRequired => _totalStampsRequired;

    /// <summary>
    /// EN: Current number of stamps collected.
    /// VI: So stamp hien tai da thu thap.
    /// </summary>
    public int CurrentStamps => _currentStamps;

    /// <summary>
    /// EN: Whether the card has been completed (all stamps collected).
    /// VI: Card da hoan thanh chua (da thu thap du stamp).
    /// </summary>
    public bool IsCompleted => _isCompleted;

    /// <summary>
    /// EN: Whether the reward has been claimed after completion.
    /// VI: Phan thuong da duoc nhan sau khi hoan thanh chua.
    /// </summary>
    public bool RewardClaimed => _rewardClaimed;

    /// <summary>
    /// EN: Creation timestamp.
    /// VI: Thoi gian tao.
    /// </summary>
    public DateTime CreatedAt => _createdAt;

    /// <summary>
    /// EN: Completion timestamp (when all stamps collected).
    /// VI: Thoi gian hoan thanh (khi thu thap du stamp).
    /// </summary>
    public DateTime? CompletedAt => _completedAt;

    /// <summary>
    /// EN: Private constructor for EF Core.
    /// VI: Constructor private cho EF Core.
    /// </summary>
    protected StampCard()
    {
        _cardName = string.Empty;
    }

    /// <summary>
    /// EN: Create a new stamp card for a member at a shop.
    /// VI: Tao stamp card moi cho member tai shop.
    /// </summary>
    /// <param name="shopId">Shop ID / ID shop</param>
    /// <param name="memberId">Member ID / ID member</param>
    /// <param name="cardName">Card display name / Ten hien thi card</param>
    /// <param name="totalStampsRequired">Total stamps needed for reward (default 10) / Tong stamp can cho thuong (mac dinh 10)</param>
    public StampCard(Guid shopId, Guid memberId, string cardName, int totalStampsRequired = 10) : this()
    {
        if (shopId == Guid.Empty)
            throw new ArgumentException("Shop ID cannot be empty / Shop ID khong duoc rong", nameof(shopId));
        if (memberId == Guid.Empty)
            throw new ArgumentException("Member ID cannot be empty / Member ID khong duoc rong", nameof(memberId));
        if (string.IsNullOrWhiteSpace(cardName))
            throw new ArgumentException("Card name cannot be empty / Ten card khong duoc rong", nameof(cardName));
        if (totalStampsRequired < 1)
            throw new ArgumentException("Total stamps required must be at least 1 / Tong stamp can it nhat la 1", nameof(totalStampsRequired));

        Id = Guid.NewGuid();
        _shopId = shopId;
        _memberId = memberId;
        _cardName = cardName;
        _totalStampsRequired = totalStampsRequired;
        _currentStamps = 0;
        _isCompleted = false;
        _rewardClaimed = false;
        _createdAt = DateTime.UtcNow;

        // EN: Raise domain event for stamp card creation
        // VI: Phat domain event khi tao stamp card
        AddDomainEvent(new StampCardCreatedDomainEvent(this));
    }

    /// <summary>
    /// EN: Add a stamp to the card. If total stamps reached, mark as completed.
    /// VI: Them stamp vao card. Neu dat du stamp, danh dau hoan thanh.
    /// </summary>
    public void AddStamp()
    {
        if (_isCompleted)
            throw new InvalidOperationException("Cannot add stamp to a completed card / Khong the them stamp vao card da hoan thanh");

        _currentStamps++;

        // EN: Raise stamp added event
        // VI: Phat event khi them stamp
        AddDomainEvent(new StampAddedDomainEvent(this));

        // EN: Check if card is now complete
        // VI: Kiem tra card da hoan thanh chua
        if (_currentStamps >= _totalStampsRequired)
        {
            _isCompleted = true;
            _completedAt = DateTime.UtcNow;

            // EN: Raise card completed event for notifications / rewards
            // VI: Phat event hoan thanh card cho thong bao / phan thuong
            AddDomainEvent(new StampCardCompletedDomainEvent(this));
        }
    }

    /// <summary>
    /// EN: Claim the reward after card completion.
    /// VI: Nhan thuong sau khi hoan thanh card.
    /// </summary>
    public void ClaimReward()
    {
        if (!_isCompleted)
            throw new InvalidOperationException("Cannot claim reward on an incomplete card / Khong the nhan thuong tren card chua hoan thanh");
        if (_rewardClaimed)
            throw new InvalidOperationException("Reward already claimed / Phan thuong da duoc nhan roi");

        _rewardClaimed = true;

        // EN: Raise reward claimed event
        // VI: Phat event khi nhan thuong
        AddDomainEvent(new RewardClaimedDomainEvent(this));
    }

    /// <summary>
    /// EN: Reset the stamp card for a new round (after reward has been claimed).
    /// VI: Reset stamp card cho vong moi (sau khi da nhan thuong).
    /// </summary>
    public void Reset()
    {
        if (!_rewardClaimed)
            throw new InvalidOperationException("Cannot reset card before reward is claimed / Khong the reset card truoc khi nhan thuong");

        _currentStamps = 0;
        _isCompleted = false;
        _rewardClaimed = false;
        _completedAt = null;
    }
}
