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

namespace MembershipService.API.Application.Commands;

/// <summary>
/// EN: Handler for updating an existing level definition.
/// VI: Handler để cập nhật level definition.
/// </summary>
public class UpdateLevelDefinitionCommandHandler : IRequestHandler<UpdateLevelDefinitionCommand, UpdateLevelDefinitionResult>
{
    private readonly ILevelDefinitionRepository _levelDefinitionRepository;
    private readonly ILogger<UpdateLevelDefinitionCommandHandler> _logger;

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

    public async Task<UpdateLevelDefinitionResult> Handle(UpdateLevelDefinitionCommand request, CancellationToken cancellationToken)
    {
        // EN: Get level definition from repository
        // VI: Lấy level definition từ repository
        var levelDefinition = await _levelDefinitionRepository.GetAsync(request.Id);
        if (levelDefinition == null)
        {
            throw new KeyNotFoundException($"Level definition {request.Id} not found");
        }

        // EN: Apply partial updates using domain methods
        // VI: Áp dụng partial updates qua các domain methods
        if (!string.IsNullOrEmpty(request.Name))
        {
            levelDefinition.UpdateName(request.Name);
        }

        if (request.RequiredExp.HasValue)
        {
            levelDefinition.UpdateRequiredExp(request.RequiredExp.Value);
        }

        if (request.ClearDescription)
        {
            levelDefinition.UpdateDescription(null);
        }
        else if (request.Description != null)
        {
            levelDefinition.UpdateDescription(request.Description);
        }

        if (request.ClearIconUrl)
        {
            levelDefinition.UpdateIconUrl(null);
        }
        else if (request.IconUrl != null)
        {
            levelDefinition.UpdateIconUrl(request.IconUrl);
        }

        if (request.ClearBadgeColor)
        {
            levelDefinition.UpdateBadgeColor(null);
        }
        else if (request.BadgeColor != null)
        {
            levelDefinition.UpdateBadgeColor(request.BadgeColor);
        }

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

        _logger.LogInformation(
            "Updated level definition {LevelId} with number {LevelNumber}",
            levelDefinition.Id, levelDefinition.LevelNumber);

        return new UpdateLevelDefinitionResult
        {
            Id = levelDefinition.Id,
            LevelNumber = levelDefinition.LevelNumber,
            Name = levelDefinition.Name,
            RequiredExp = levelDefinition.RequiredExp,
            Description = levelDefinition.Description,
            IconUrl = levelDefinition.IconUrl,
            BadgeColor = levelDefinition.BadgeColor,
            IsActive = levelDefinition.IsActive,
            UpdatedAt = levelDefinition.UpdatedAt
        };
    }
}
