using MediatR;
using MissionService.Domain.AggregatesModel.CheckInAggregate;

namespace MissionService.API.Application.Commands;

/// <summary>
/// EN: Handler for PerformCheckInCommand
/// VI: Handler cho PerformCheckInCommand
/// </summary>
public class PerformCheckInCommandHandler : IRequestHandler<PerformCheckInCommand, CheckInResult>
{
    private readonly IUserCheckInRepository _checkInRepository;
    private readonly ILogger<PerformCheckInCommandHandler> _logger;

    public PerformCheckInCommandHandler(
        IUserCheckInRepository checkInRepository,
        ILogger<PerformCheckInCommandHandler> logger)
    {
        _checkInRepository = checkInRepository;
        _logger = logger;
    }

    public async Task<CheckInResult> Handle(PerformCheckInCommand request, CancellationToken cancellationToken)
    {
        _logger.LogInformation("Processing check-in for user {UserId}", request.UserId);

        try
        {
            // EN: Get or create check-in profile / VI: Lấy hoặc tạo hồ sơ check-in
            var checkIn = await _checkInRepository.GetOrCreateByUserIdAsync(request.UserId, cancellationToken);

            // EN: Check if already checked in today / VI: Kiểm tra đã check-in hôm nay chưa
            if (!checkIn.CanCheckInToday())
            {
                return new CheckInResult(
                    Success: false,
                    CurrentStreak: checkIn.CurrentStreak,
                    DailyPoints: 0,
                    StreakBonus: 0,
                    MilestoneBonus: 0,
                    TotalPoints: 0,
                    IsMilestone: false,
                    Message: "Already checked in today / Đã điểm danh hôm nay rồi");
            }

            // EN: Perform check-in with default streak config / VI: Thực hiện check-in với cấu hình streak mặc định
            var config = StreakBonusConfig.Default();
            var result = checkIn.CheckIn(config);

            // EN: Save changes / VI: Lưu thay đổi
            await _checkInRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken);

            _logger.LogInformation(
                "Check-in successful for user {UserId}, streak: {Streak}, points: {Points}",
                request.UserId, result.CurrentStreak, result.TotalPoints);

            return new CheckInResult(
                Success: true,
                CurrentStreak: result.CurrentStreak,
                DailyPoints: result.DailyPoints,
                StreakBonus: result.StreakBonus,
                MilestoneBonus: result.MilestoneBonus,
                TotalPoints: result.TotalPoints,
                IsMilestone: result.IsMilestone,
                Message: result.IsMilestone 
                    ? "Milestone reached! / Đạt mốc thưởng!" 
                    : "Check-in successful / Điểm danh thành công");
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Check-in failed for user {UserId}", request.UserId);
            return new CheckInResult(
                Success: false,
                CurrentStreak: 0,
                DailyPoints: 0,
                StreakBonus: 0,
                MilestoneBonus: 0,
                TotalPoints: 0,
                IsMilestone: false,
                Message: "Check-in failed / Điểm danh thất bại");
        }
    }
}
