using MediatR;
using MembershipService.Domain.AggregatesModel.LevelAggregate;

namespace MembershipService.API.Application.Commands;

/// <summary>
/// EN: Handler for creating a new level definition.
/// VI: Handler để tạo level definition mới.
/// </summary>
public class CreateLevelDefinitionCommandHandler : IRequestHandler<CreateLevelDefinitionCommand, CreateLevelDefinitionResult>
{
    private readonly ILevelDefinitionRepository _levelDefinitionRepository;
    private readonly ILogger<CreateLevelDefinitionCommandHandler> _logger;

    public CreateLevelDefinitionCommandHandler(
        ILevelDefinitionRepository levelDefinitionRepository,
        ILogger<CreateLevelDefinitionCommandHandler> logger)
    {
        _levelDefinitionRepository = levelDefinitionRepository ?? throw new ArgumentNullException(nameof(levelDefinitionRepository));
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }

    public async Task<CreateLevelDefinitionResult> Handle(CreateLevelDefinitionCommand request, CancellationToken cancellationToken)
    {
        // EN: Check if level number already exists
        // VI: Kiểm tra xem level number đã tồn tại chưa
        var exists = await _levelDefinitionRepository.ExistsByLevelNumberAsync(request.LevelNumber);
        if (exists)
        {
            throw new InvalidOperationException($"Level number {request.LevelNumber} already exists");
        }

        // EN: Create new level definition
        // VI: Tạo level definition mới
        var levelDefinition = new LevelDefinition(
            request.LevelNumber,
            request.Name,
            request.RequiredExp,
            request.Description,
            request.IconUrl,
            request.BadgeColor);

        _levelDefinitionRepository.Add(levelDefinition);
        await _levelDefinitionRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken);

        _logger.LogInformation(
            "Created level definition {LevelId} with number {LevelNumber} and name {LevelName}",
            levelDefinition.Id, levelDefinition.LevelNumber, levelDefinition.Name);

        return new CreateLevelDefinitionResult
        {
            Id = levelDefinition.Id,
            LevelNumber = levelDefinition.LevelNumber,
            Name = levelDefinition.Name,
            RequiredExp = levelDefinition.RequiredExp,
            CreatedAt = levelDefinition.CreatedAt
        };
    }
}
