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

namespace MembershipService.API.Application.Commands;

/// <summary>
/// EN: Handler for creating a new loyalty stamp card.
/// VI: Handler de tao stamp card loyalty moi.
/// </summary>
public class CreateStampCardCommandHandler : IRequestHandler<CreateStampCardCommand, CreateStampCardResult>
{
    private readonly IStampCardRepository _stampCardRepository;
    private readonly ILogger<CreateStampCardCommandHandler> _logger;

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

    public async Task<CreateStampCardResult> Handle(CreateStampCardCommand request, CancellationToken cancellationToken)
    {
        // EN: Check if member already has an active card at this shop
        // VI: Kiem tra member da co card dang hoat dong tai shop nay chua
        var existingCard = await _stampCardRepository.GetActiveCardAsync(request.ShopId, request.MemberId, cancellationToken);
        if (existingCard != null)
        {
            throw new InvalidOperationException(
                $"Member {request.MemberId} already has an active stamp card at shop {request.ShopId} / " +
                $"Member {request.MemberId} da co stamp card dang hoat dong tai shop {request.ShopId}");
        }

        // EN: Create new stamp card
        // VI: Tao stamp card moi
        var stampCard = new StampCard(
            request.ShopId,
            request.MemberId,
            request.CardName,
            request.TotalStampsRequired);

        _stampCardRepository.Add(stampCard);
        await _stampCardRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken);

        _logger.LogInformation(
            "Created stamp card {StampCardId} for member {MemberId} at shop {ShopId} with {TotalStamps} stamps required",
            stampCard.Id, request.MemberId, request.ShopId, request.TotalStampsRequired);

        return new CreateStampCardResult(
            stampCard.Id,
            stampCard.ShopId,
            stampCard.MemberId,
            stampCard.CardName,
            stampCard.TotalStampsRequired,
            stampCard.CreatedAt);
    }
}
