using CMSMicroservice.Application.Common.Extensions;
using CMSMicroservice.Application.Common.Interfaces;
using CMSMicroservice.Domain.Enums;
using MediatR;
using Microsoft.EntityFrameworkCore;

namespace CMSMicroservice.Application.WalletCQ.Queries.GetManualCreditCharges;

public class GetManualCreditChargesQueryHandler
    : IRequestHandler<GetManualCreditChargesQuery, GetManualCreditChargesResponseDto>
{
    private readonly IApplicationDbContext _context;

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

    public async Task<GetManualCreditChargesResponseDto> Handle(
        GetManualCreditChargesQuery request,
        CancellationToken cancellationToken)
    {
        var filter = request.Filter;

        var query =
            from t in _context.Transactions.AsNoTracking()
            where t.Type == TransactionType.ManualCreditWalletCharge
            join h in _context.UserWalletHistories.AsNoTracking() on t.Id equals h.RefrenceId
            join w in _context.UserWallets.AsNoTracking() on h.WalletId equals w.Id
            join u in _context.Users.AsNoTracking() on w.UserId equals u.Id
            select new ManualCreditChargeModelDto
            {
                TransactionId = t.Id,
                UserId = w.UserId,
                UserName = ((u.FirstName ?? "") + " " + (u.LastName ?? "")).Trim(),
                Amount = t.Amount,
                Description = t.Description ?? string.Empty,
                RefId = t.RefId,
                NewBalance = h.CurrentBalance,
                Created = t.Created,
                PaymentDate = t.PaymentDate
            };

        if (filter?.UserId is long userId)
            query = query.Where(x => x.UserId == userId);

        if (filter?.TransactionId is long txId)
            query = query.Where(x => x.TransactionId == txId);

        if (!string.IsNullOrWhiteSpace(filter?.RefId))
            query = query.Where(x => x.RefId != null && x.RefId.Contains(filter.RefId));

        if (filter?.CreatedFrom is DateTime from)
            query = query.Where(x => x.Created >= from);

        if (filter?.CreatedTo is DateTime to)
            query = query.Where(x => x.Created <= to);

        query = query.OrderByDescending(x => x.Created);

        return new GetManualCreditChargesResponseDto
        {
            MetaData = await query.GetMetaData(request.PaginationState, cancellationToken),
            Models = await query
                .PaginatedListAsync(paginationState: request.PaginationState)
                .ToListAsync(cancellationToken)
        };
    }
}
