using CMSMicroservice.Application.Common.Interfaces;
using CMSMicroservice.Application.CommissionCQ.Commands.CalculateWeeklyBalances;
using CMSMicroservice.Application.CommissionCQ.Commands.CalculateWeeklyCommissionPool;

namespace CMSMicroservice.Application.CommissionCQ.Commands.TriggerWeeklyCalculation;

public class TriggerWeeklyCalculationCommandHandler : IRequestHandler<TriggerWeeklyCalculationCommand, TriggerWeeklyCalculationResponseDto>
{
    private readonly IApplicationDbContext _context;
    private readonly IMediator _mediator;
    private readonly ICommissionCalculationStrategyFactory _strategyFactory;

    public TriggerWeeklyCalculationCommandHandler(
        IApplicationDbContext context,
        IMediator mediator,
        ICommissionCalculationStrategyFactory strategyFactory)
    {
        _context = context;
        _mediator = mediator;
        _strategyFactory = strategyFactory;
    }

    public async Task<TriggerWeeklyCalculationResponseDto> Handle(
        TriggerWeeklyCalculationCommand request, 
        CancellationToken cancellationToken)
    {
        var executionId = Guid.NewGuid().ToString();
        var startedAt = DateTime.Now;

        try
        {
            // Validate week number format
            if (request.WeekDefinitionId <= 0)
            {
                return new TriggerWeeklyCalculationResponseDto
                {
                    Success = false,
                    Message = "شماره هفته نمی‌تواند خالی باشد",
                    ExecutionId = executionId,
                    StartedAt = startedAt
                };
            }

            var steps = new List<string>();
            
            // ⭐ دریافت استراتژی براساس Config (ORM یا SP)
            var strategy = await _strategyFactory.CreateStrategyAsync(cancellationToken);
            var strategyName = strategy.GetType().Name.Contains("StoredProcedure") ? "SP" : "ORM";

            // Step 1: Calculate Weekly Balances (تا 15 لول)
            if (!request.SkipBalances)
            {
                var balancesCount = await strategy.CalculateWeeklyBalancesAsync(
                    request.WeekDefinitionId,
                    request.ForceRecalculate,
                    request.PackageId,
                    cancellationToken);
                
                steps.Add($"محاسبه امتیازات هفتگی ({balancesCount} کاربر)");
            }

            // Step 2: Calculate Pool & Process Payouts (محاسبه استخر + پرداخت کاربران)
            if (!request.SkipPayouts)
            {
                var poolId = await strategy.CalculateWeeklyCommissionPoolAsync(
                    request.WeekDefinitionId,
                    request.ForceRecalculate,
                    request.PackageId,
                    cancellationToken);
                
                steps.Add($"محاسبه استخر و پرداخت کاربران (Pool: {poolId})");
            }

            return new TriggerWeeklyCalculationResponseDto
            {
                Success = true,
                Message = $"محاسبات هفته {request.WeekDefinitionId} با موفقیت انجام شد [{strategyName}]. مراحل: {string.Join(", ", steps)}",
                ExecutionId = executionId,
                StartedAt = startedAt
            };
        }
        catch (Exception ex)
        {
            return new TriggerWeeklyCalculationResponseDto
            {
                Success = false,
                Message = $"خطا در اجرای محاسبات: {ex.Message}",
                ExecutionId = executionId,
                StartedAt = startedAt
            };
        }
    }
}
