namespace CMSMicroservice.Application.CommissionCQ.Queries.GetAllWeeklyPools;

public class GetAllWeeklyPoolsQueryHandler : IRequestHandler<GetAllWeeklyPoolsQuery, GetAllWeeklyPoolsResponseDto>
{
    private readonly IApplicationDbContext _context;
    private readonly IWeekDefinitionRepository _weekDefinitionRepository;

    public GetAllWeeklyPoolsQueryHandler(
        IApplicationDbContext context,
        IWeekDefinitionRepository weekDefinitionRepository)
    {
        _context = context;
        _weekDefinitionRepository = weekDefinitionRepository;
    }

    public async Task<GetAllWeeklyPoolsResponseDto> Handle(GetAllWeeklyPoolsQuery request, CancellationToken cancellationToken)
    {
        var query = _context.WeeklyCommissionPools
            .Include(i=> i.WeekDefinition)
            .Include(i => i.Package)
            .AsNoTracking();

        // Apply filters
        if (request.FromWeekDefinitionId != null)
        {
            query = query.Where(x => x.WeekDefinitionId >= request.FromWeekDefinitionId);
        }

        if (request.ToWeekDefinitionId != null)
        {
            query = query.Where(x => x.WeekDefinitionId <= request.ToWeekDefinitionId);
        }

        if (request.OnlyCalculated.HasValue && request.OnlyCalculated.Value)
        {
            query = query.Where(x => x.IsCalculated);
        }

        if (request.PackageId.HasValue)
        {
            query = query.Where(x => x.PackageId == request.PackageId.Value);
        }

        // Order by week number descending (newest first)
        query = query.OrderByDescending(x => x.WeekDefinitionId);

        // Count total
        var totalCount = await query.CountAsync(cancellationToken);

        // Paginate
        var pools = await query
            .Skip((request.PageIndex - 1) * request.PageSize)
            .Take(request.PageSize)
            .Select(x => new WeeklyCommissionPoolDto
            {
                Id = x.Id,
                WeekDefinitionId = x.WeekDefinitionId,
                WeekDisplayName = x.WeekDefinition.DisplayName,
                TotalPoolAmount = x.TotalPoolAmount,
                TotalBalances = x.TotalBalances,
                ValuePerBalance = x.ValuePerBalance,
                IsCalculated = x.IsCalculated,
                CalculatedAt = x.CalculatedAt,
                Created = x.Created,
                PackageId = x.PackageId,
                PackageTitle = x.Package != null ? x.Package.Title : string.Empty
            })
            .ToListAsync(cancellationToken);

        // Populate WeekDisplayName from cache
        // foreach (var pool in pools)
        // {
        //     // WeeklyCommissionPoolDto is a record, need to create new instance with display name
        //     // Since records are immutable, we can't modify them directly
        // }
        
        // // Create new list with WeekDisplayName populated
        // var poolsWithDisplayName = pools.Select(p => p with 
        // { 
        //     WeekDisplayName = _weekDefinitionRepository.GetDisplayNameByGregorianWeekNumber(p.WeekNumber) 
        // }).ToList();

        return new GetAllWeeklyPoolsResponseDto
        {
            MetaData = new MetaDataDto
            {
                TotalCount = totalCount,
                PageSize = request.PageSize,
                CurrentPage = request.PageIndex,
                TotalPages = (int)Math.Ceiling(totalCount / (double)request.PageSize)
            },
            Models = pools
        };
    }
}
