using CMSMicroservice.Application.Common.Interfaces;
using CMSMicroservice.Application.Common.Models;

namespace CMSMicroservice.Application.CommissionCQ.Queries.GetWorkerExecutionLogs;

public class GetWorkerExecutionLogsQueryHandler : IRequestHandler<GetWorkerExecutionLogsQuery, GetWorkerExecutionLogsResponseDto>
{
    private readonly IApplicationDbContext _context;
    private readonly IWeekDefinitionRepository _weekDefinitionRepository;

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

    public async Task<GetWorkerExecutionLogsResponseDto> Handle(
        GetWorkerExecutionLogsQuery request,
        CancellationToken cancellationToken)
    {
        // Query from database
        var query = _context.WorkerExecutionLogs
            .Include(i=> i.WeekDefinition)
            .AsQueryable();

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

        if (request.SuccessOnly == true)
        {
            query = query.Where(x => x.Status == Domain.Entities.Commission.WorkerExecutionStatus.Success ||
                                     x.Status == Domain.Entities.Commission.WorkerExecutionStatus.SuccessWithWarnings);
        }

        if (request.FailedOnly == true)
        {
            query = query.Where(x => x.Status == Domain.Entities.Commission.WorkerExecutionStatus.Failed);
        }

        // Order by most recent first
        query = query.OrderByDescending(x => x.StartedAt);

        var totalCount = await query.CountAsync(cancellationToken);
        var pageSize = request.PaginationState?.PageSize ?? 10;
        var pageNumber = request.PaginationState?.PageNumber ?? 1;

        var logs = await query
            .Skip((pageNumber - 1) * pageSize)
            .Take(pageSize)
            .Select(x => new WorkerExecutionLogModel
            {
                ExecutionId = x.ExecutionId.ToString(),
                WeekDefinitionId = x.WeekDefinitionId,
                WeekDisplayName = x.WeekDefinition.DisplayName,
                Step = "Full", // We only have full execution now
                Success = x.Status == Domain.Entities.Commission.WorkerExecutionStatus.Success ||
                         x.Status == Domain.Entities.Commission.WorkerExecutionStatus.SuccessWithWarnings,
                ErrorMessage = x.ErrorMessage,
                StartedAt = x.StartedAt,
                CompletedAt = x.CompletedAt ?? x.StartedAt,
                DurationMs = x.DurationMs ?? 0,
                RecordsProcessed = x.ProcessedCount,
                Details = x.Details ?? $"Worker execution: {x.Status}"
            })
            .ToListAsync(cancellationToken);

        // // Populate WeekDisplayName from cache
        // foreach (var log in logs)
        // {
        //     log.WeekDisplayName = _weekDefinitionRepository.GetDisplayNameByGregorianWeekNumber(log.WeekNumber);
        // }

        return new GetWorkerExecutionLogsResponseDto
        {
            MetaData = new MetaData
            {
                CurrentPage = pageNumber,
                TotalPage = (int)Math.Ceiling(totalCount / (double)pageSize),
                PageSize = pageSize,
                TotalCount = totalCount,
                HasPrevious = pageNumber > 1,
                HasNext = pageNumber < (int)Math.Ceiling(totalCount / (double)pageSize)
            },
            Models = logs
        };
    }
}
