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

namespace CMSMicroservice.Application.TransactionsCQ.Queries.GetCustomerTransactionsByFilter;

public class GetCustomerTransactionsByFilterQueryHandler : IRequestHandler<GetCustomerTransactionsByFilterQuery, GetCustomerTransactionsByFilterResponseDto>
{
    private readonly IApplicationDbContext _context;
    private readonly ICurrentUserService _currentUser;

    public GetCustomerTransactionsByFilterQueryHandler(
        IApplicationDbContext context,
        ICurrentUserService currentUser)
    {
        _context = context;
        _currentUser = currentUser;
    }

    public async Task<GetCustomerTransactionsByFilterResponseDto> Handle(GetCustomerTransactionsByFilterQuery request, CancellationToken cancellationToken)
    {
        // Resolve UserId from JWT if not specified
        var userId = request.UserId == 0
            ? (long.TryParse(_currentUser.UserId, out var currentUserId) ? currentUserId : 0)
            : request.UserId;

        if (userId == 0)
            throw new UnauthorizedAccessException("User ID not found");

        // Transaction doesn't have UserId, find through UserOrders
        var query = _context.Transactions
            .AsNoTracking()
            .Include(x => x.UserOrders)
            .Where(x => x.UserOrders.Any(o => o.UserId == userId))
            .AsQueryable();

        // Apply filters
        if (request.IdFilter.HasValue)
            query = query.Where(x => x.Id == request.IdFilter.Value);

        if (request.AmountFilter.HasValue)
            query = query.Where(x => x.Amount == request.AmountFilter.Value);

        if (!string.IsNullOrEmpty(request.DescriptionFilter))
            query = query.Where(x => x.Description.Contains(request.DescriptionFilter));

        if (request.PaymentStatusFilter.HasValue)
        {
            var status = request.PaymentStatusFilter.Value 
                ? Domain.Enums.PaymentStatus.Success 
                : Domain.Enums.PaymentStatus.Reject;
            query = query.Where(x => x.PaymentStatus == status);
        }

        if (!string.IsNullOrEmpty(request.RefIdFilter))
            query = query.Where(x => x.RefId == request.RefIdFilter);

        if (request.TypeFilter.HasValue)
            query = query.Where(x => (int)x.Type == request.TypeFilter.Value);

        // Apply sorting
        if (!string.IsNullOrEmpty(request.SortBy))
            query = query.ApplyOrder(request.SortBy);
        else
            query = query.OrderByDescending(x => x.Created);

        // Get metadata
        var metaData = await query.GetMetaData(request.PaginationState, cancellationToken);

        // Get paginated results
        var transactions = await query
            .PaginatedListAsync(request.PaginationState)
            .ToListAsync(cancellationToken);

        var models = transactions.Select(t => new CustomerTransactionModel
        {
            Id = t.Id,
            Amount = t.Amount,
            Description = t.Description ?? "",
            PaymentStatus = t.PaymentStatus,
            PaymentDate = t.PaymentDate,
            RefId = t.RefId ?? "",
            Type = t.Type
        }).ToList();

        return new GetCustomerTransactionsByFilterResponseDto
        {
            MetaData = metaData,
            Models = models
        };
    }
}
