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

namespace CMSMicroservice.Application.UserOrderCQ.Queries.GetCustomerOrders;

public class GetCustomerOrdersQueryHandler : IRequestHandler<GetCustomerOrdersQuery, GetCustomerOrdersResponseDto>
{
    private readonly IApplicationDbContext _context;

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

    public async Task<GetCustomerOrdersResponseDto> Handle(GetCustomerOrdersQuery request, CancellationToken cancellationToken)
    {
        // UserId > 0 → filter by that user
        // UserId == 0 → show ALL users (admin mode)
        var userId = request.UserId;

        var query = _context.UserOrders
            .AsNoTracking()
            .Where(x => userId == 0 || x.UserId == userId)
            .Include(x => x.Package)
            .Include(x => x.Transaction)
            .Include(x => x.UserAddress)
            .Include(x => x.User)
            .Include(x => x.FactorDetails)
                .ThenInclude(f => f.Product)
            .Include(x => x.OrderVAT)
            .AsQueryable();

        // Apply filters
        if (request.PaymentStatusFilter.HasValue)
            query = query.Where(x => (int)x.PaymentStatus == request.PaymentStatusFilter.Value);

        if (request.DeliveryStatusFilter.HasValue)
            query = query.Where(x => (int)x.DeliveryStatus == request.DeliveryStatusFilter.Value);

        if (request.FromDate.HasValue)
            query = query.Where(x => x.Created >= request.FromDate.Value);

        if (request.ToDate.HasValue)
            query = query.Where(x => x.Created <= request.ToDate.Value);

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

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

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

        var models = orders.Select(order => new CustomerOrderModel
        {
            Id = order.Id,
            Amount = order.Amount,
            PackageId = order.PackageId,
            TransactionId = order.TransactionId,
            PaymentStatus = order.PaymentStatus,
            PaymentDate = order.PaymentDate,
            UserId = order.UserId,
            UserAddressId = order.UserAddressId,
            PaymentMethod = order.PaymentMethod,
            UserAddressText = order.UserAddress?.Address ?? "",
            DeliveryStatus = order.DeliveryStatus,
            TrackingCode = order.TrackingCode ?? "",
            DeliveryDescription = order.DeliveryDescription ?? "",
            UserFullName = UserDisplayName.From(order.User),
            UserNationalCode = order.User?.NationalCode ?? "",
            VatAmount = order.OrderVAT?.VATAmount ?? 0,
            VatPercentage = order.OrderVAT != null ? (double)order.OrderVAT.VATRate * 100 : 0,
            FactorDetails = order.FactorDetails?.Select(fd => new FactorDetailModel
            {
                ProductId = fd.ProductId,
                ProductTitle = fd.Product?.Title ?? "",
                ProductThumbnailPath = fd.Product?.ThumbnailPath ?? "",
                UnitPrice = fd.UnitPrice,
                Count = fd.Count,
                UnitDiscountPrice = fd.UnitDiscountPrice
            }).ToList() ?? new List<FactorDetailModel>()
        }).ToList();

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