using MediatR;
using MembershipService.Domain.AggregatesModel.StampCardAggregate;

namespace MembershipService.API.Application.Commands;

/// <summary>
/// EN: Handler for adding a stamp to a member's card. Auto-creates card if none exists.
/// VI: Handler de them stamp vao card cua member. Tu dong tao card neu chua co.
/// </summary>
public class AddStampCommandHandler : IRequestHandler<AddStampCommand, AddStampResult>
{
    private readonly IStampCardRepository _stampCardRepository;
    private readonly ILogger<AddStampCommandHandler> _logger;

    public AddStampCommandHandler(
        IStampCardRepository stampCardRepository,
        ILogger<AddStampCommandHandler> logger)
    {
        _stampCardRepository = stampCardRepository ?? throw new ArgumentNullException(nameof(stampCardRepository));
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }

    public async Task<AddStampResult> Handle(AddStampCommand request, CancellationToken cancellationToken)
    {
        var cardWasAutoCreated = false;

        // EN: Find active card for member+shop
        // VI: Tim card dang hoat dong cho member+shop
        var stampCard = await _stampCardRepository.GetActiveCardAsync(
            request.ShopId, request.MemberId, cancellationToken);

        // EN: If no active card exists, auto-create one
        // VI: Neu khong co card dang hoat dong, tu dong tao moi
        if (stampCard == null)
        {
            stampCard = new StampCard(
                request.ShopId,
                request.MemberId,
                "Loyalty Card",
                totalStampsRequired: 10);

            _stampCardRepository.Add(stampCard);
            cardWasAutoCreated = true;

            _logger.LogInformation(
                "Auto-created stamp card {StampCardId} for member {MemberId} at shop {ShopId}",
                stampCard.Id, request.MemberId, request.ShopId);
        }

        // EN: Add stamp to the card
        // VI: Them stamp vao card
        stampCard.AddStamp();
        _stampCardRepository.Update(stampCard);
        await _stampCardRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken);

        _logger.LogInformation(
            "Added stamp to card {StampCardId}: {Current}/{Total} (Order: {OrderId})",
            stampCard.Id, stampCard.CurrentStamps, stampCard.TotalStampsRequired, request.OrderId);

        return new AddStampResult(
            stampCard.Id,
            stampCard.CurrentStamps,
            stampCard.TotalStampsRequired,
            stampCard.IsCompleted,
            cardWasAutoCreated);
    }
}
