namespace CMSMicroservice.Application.CommissionCQ.Queries.GetWithdrawalRequests;

public class GetWithdrawalRequestsQueryHandler : IRequestHandler<GetWithdrawalRequestsQuery, GetWithdrawalRequestsResponseDto>
{
    private readonly IApplicationDbContext _context;

    public GetWithdrawalRequestsQueryHandler(IApplicationDbContext context)
    {
        _context = context;
    }

    public async Task<GetWithdrawalRequestsResponseDto> Handle(GetWithdrawalRequestsQuery request, CancellationToken cancellationToken)
    {
        var query = _context.UserCommissionPayouts
            .AsNoTracking()
            .Include(x => x.User)
            .Where(x => x.WithdrawalMethod != null) // Only requests with withdrawal method
            .AsQueryable();

        // Filters
        if (request.Status.HasValue)
        {
            query = query.Where(x => (int)x.Status == request.Status.Value);
        }

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

        if (!string.IsNullOrEmpty(request.WeekNumber))
        {
            query = query.Where(x => x.WeekNumber == request.WeekNumber);
        }

        if (!string.IsNullOrWhiteSpace(request.IbanNumber))
        {
            query = query.Where(x => x.IbanNumber != null && x.IbanNumber.Contains(request.IbanNumber));
        }

        query = query.ApplyOrder(sortBy: request.SortBy ?? "-Created");

        var meta = await query.GetMetaData(request.PaginationState, cancellationToken);

        var models = await query
            .PaginatedListAsync(paginationState: request.PaginationState)
            .ToListAsync(cancellationToken);

        var result = models.Select(x => new WithdrawalRequestModel
        {
            Id = x.Id,
            UserId = x.UserId,
            UserName = x.User != null ? (x.User.FirstName + " " + x.User.LastName).Trim() : x.User?.Mobile ?? "N/A",
            WeekNumber = x.WeekNumber,
            Amount = x.TotalAmount,
            Status = (int)x.Status,
            WithdrawalMethod = x.WithdrawalMethod.HasValue ? (int)x.WithdrawalMethod.Value : 0,
            IbanNumber = x.IbanNumber,
            RequestedAt = x.WithdrawnAt ?? x.Created,
            ProcessedAt = x.LastModified,
            ProcessedBy = x.ProcessedBy,
            Reason = x.RejectionReason,
            BankReferenceId = x.BankReferenceId,
            BankTrackingCode = x.BankTrackingCode,
            PaymentFailureReason = x.PaymentFailureReason,
            Created = x.Created
        }).ToList();

        return new GetWithdrawalRequestsResponseDto
        {
            MetaData = meta,
            Models = result
        };
    }
}
