using CMSMicroservice.Application.Common;
using CMSMicroservice.Application.Common.Exceptions;
using CMSMicroservice.Application.Common.Interfaces;
using CMSMicroservice.Domain.Entities;

namespace CMSMicroservice.Application.UserOrderCQ.Queries.GetCustomerOrder;

public class GetCustomerOrderQueryHandler : IRequestHandler<GetCustomerOrderQuery, GetCustomerOrderResponseDto>
{
    private readonly IApplicationDbContext _context;

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

    public async Task<GetCustomerOrderResponseDto> Handle(GetCustomerOrderQuery request, CancellationToken cancellationToken)
    {
        // UserId > 0 → filter by that user (customer security)
        // UserId == 0 → no user filter (admin can view any order by ID)
        var userId = request.UserId;

        var order = await _context.UserOrders
            .AsNoTracking()
            .Where(x => x.Id == request.OrderId && (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)
            .FirstOrDefaultAsync(cancellationToken);

        if (order == null)
            throw new NotFoundException(nameof(UserOrder), request.OrderId);

        return new GetCustomerOrderResponseDto
        {
            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 ?? "",
            PostalCode = order.UserAddress?.PostalCode ?? "",
            UserMobile = order.User?.Mobile ?? "",
            VatAmount = order.OrderVAT?.VATAmount ?? 0,
            VatPercentage = order.OrderVAT != null ? (double)order.OrderVAT.VATRate * 100 : 0,
            FactorDetails = order.FactorDetails?.Select(fd => new FactorDetailDto
            {
                ProductId = fd.ProductId,
                ProductTitle = fd.Product?.Title ?? "",
                ProductThumbnailPath = fd.Product?.ThumbnailPath ?? "",
                UnitPrice = fd.UnitPrice,
                Count = fd.Count,
                UnitDiscountPrice = fd.UnitDiscountPrice
            }).ToList() ?? new List<FactorDetailDto>()
        };
    }
}
