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

namespace MembershipService.API.Application.Queries;

/// <summary>
/// EN: Handler for getting member level progress.
/// VI: Handler để lấy tiến độ level của member.
/// </summary>
public class GetMemberProgressQueryHandler : IRequestHandler<GetMemberProgressQuery, MemberProgressDto?>
{
    private readonly IMemberRepository _memberRepository;
    private readonly ILevelDefinitionRepository _levelDefinitionRepository;

    public GetMemberProgressQueryHandler(
        IMemberRepository memberRepository,
        ILevelDefinitionRepository levelDefinitionRepository)
    {
        _memberRepository = memberRepository ?? throw new ArgumentNullException(nameof(memberRepository));
        _levelDefinitionRepository = levelDefinitionRepository ?? throw new ArgumentNullException(nameof(levelDefinitionRepository));
    }

    public async Task<MemberProgressDto?> Handle(GetMemberProgressQuery request, CancellationToken cancellationToken)
    {
        var member = await _memberRepository.GetByIdAsync(request.MemberId, cancellationToken);
        if (member == null)
        {
            return null;
        }

        // EN: Get all active level definitions
        // VI: Lấy tất cả level definitions đang active
        var levelRules = await _levelDefinitionRepository.GetAllActiveAsync();
        if (!levelRules.Any())
        {
            return null;
        }

        // EN: Find current and next level
        // VI: Tìm level hiện tại và level tiếp theo
        var currentLevelDef = levelRules.FirstOrDefault(l => l.LevelNumber == member.CurrentLevel);
        var nextLevelDef = levelRules
            .Where(l => l.LevelNumber > member.CurrentLevel)
            .OrderBy(l => l.LevelNumber)
            .FirstOrDefault();

        // EN: Calculate progress
        // VI: Tính toán tiến độ
        int expToNextLevel = 0;
        int progressPercent = 100;

        if (nextLevelDef != null && currentLevelDef != null)
        {
            var expInCurrentLevel = member.CurrentExp - currentLevelDef.RequiredExp;
            var expNeededForNextLevel = nextLevelDef.RequiredExp - currentLevelDef.RequiredExp;
            
            expToNextLevel = nextLevelDef.RequiredExp - member.CurrentExp;
            progressPercent = expNeededForNextLevel > 0 
                ? (int)(expInCurrentLevel * 100.0 / expNeededForNextLevel)
                : 100;
            
            progressPercent = Math.Clamp(progressPercent, 0, 100);
        }

        return new MemberProgressDto
        {
            MemberId = member.Id,
            CurrentLevel = member.CurrentLevel,
            CurrentLevelName = currentLevelDef?.Name ?? $"Level {member.CurrentLevel}",
            CurrentExp = member.CurrentExp,
            TotalExpEarned = member.TotalExpEarned,
            ExpToNextLevel = expToNextLevel,
            ProgressPercent = progressPercent,
            NextLevel = nextLevelDef?.LevelNumber,
            NextLevelName = nextLevelDef?.Name,
            BadgeColor = currentLevelDef?.BadgeColor
        };
    }
}
