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

namespace CMSMicroservice.Application.UserOrderCQ.Queries.GetCustomerOrderHistory;

public class GetCustomerOrderHistoryQueryHandler : IRequestHandler<GetCustomerOrderHistoryQuery, GetCustomerOrderHistoryResponseDto>
{
    private readonly IApplicationDbContext _context;
    private readonly ICurrentUserService _currentUser;

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

    public async Task<GetCustomerOrderHistoryResponseDto> Handle(GetCustomerOrderHistoryQuery 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");

        var query = _context.UserOrders
            .AsNoTracking()
            .Where(x => x.UserId == userId)
            .Include(x => x.Package)
            .Include(x => x.FactorDetails)
            .AsQueryable();

        // Apply status filter if specified
        if (request.StatusFilter.HasValue)
        {
            // Status filter is based on OrderStatusEnum from Proto
            // We need to map to DeliveryStatus enum values
            var deliveryStatus = MapProtoStatusToDeliveryStatus(request.StatusFilter.Value);
            if (deliveryStatus.HasValue)
                query = query.Where(x => x.DeliveryStatus == deliveryStatus.Value);
        }

        // Apply date filters
        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 orderModels = orders.Select(order => new CustomerOrderHistoryModel
        {
            Id = order.Id,
            Amount = order.Amount,
            PackageId = order.PackageId,
            PackageName = order.Package?.Title ?? "سفارش محصولات",
            Status = MapDeliveryStatusToProtoStatus(order.DeliveryStatus),
            StatusMessage = GetStatusMessage(order.DeliveryStatus),
            OrderDate = order.Created,
            DeliveryDate = order.PaymentDate?.AddDays(GetEstimatedDeliveryDays(order.DeliveryStatus)),
            TrackingCode = order.TrackingCode ?? "",
            ItemsCount = order.FactorDetails?.Count ?? 0,
            CanCancel = CanCancelOrder(order.DeliveryStatus, order.Created),
            CanReorder = true // همیشه می‌توان دوباره سفارش داد
        }).ToList();

        return new GetCustomerOrderHistoryResponseDto
        {
            MetaData = metaData,
            Orders = orderModels
        };
    }

    private DeliveryStatus? MapProtoStatusToDeliveryStatus(int protoStatus)
    {
        // OrderStatusEnum from Proto:
        // 0=Pending, 1=Confirmed, 2=Processing, 3=Shipped, 4=Delivered, 5=Cancelled, 6=Refunded
        return protoStatus switch
        {
            0 => DeliveryStatus.Pending,
            1 => DeliveryStatus.Pending,
            2 => DeliveryStatus.Pending,
            3 => DeliveryStatus.InTransit,
            4 => DeliveryStatus.Delivered,
            5 => DeliveryStatus.Cancelled,
            6 => DeliveryStatus.Cancelled,
            _ => null
        };
    }

    private int MapDeliveryStatusToProtoStatus(DeliveryStatus status)
    {
        return status switch
        {
            DeliveryStatus.None => 0,
            DeliveryStatus.Pending => 1,
            DeliveryStatus.InTransit => 3,
            DeliveryStatus.Delivered => 4,
            DeliveryStatus.Cancelled => 5,
            DeliveryStatus.Returned => 6,
            DeliveryStatus.ReadyForOfficePickup => 7,
            _ => 0
        };
    }

    private string GetStatusMessage(DeliveryStatus status)
    {
        return status switch
        {
            DeliveryStatus.None => "ثبت نشده",
            DeliveryStatus.Pending => "در انتظار پردازش",
            DeliveryStatus.InTransit => "ارسال شده",
            DeliveryStatus.Delivered => "تحویل داده شد",
            DeliveryStatus.Cancelled => "لغو شده",
            DeliveryStatus.Returned => "مرجوع شده",
            DeliveryStatus.ReadyForOfficePickup => "آماده تحویل در دفتر",
            _ => "نامشخص"
        };
    }

    private int GetEstimatedDeliveryDays(DeliveryStatus status)
    {
        return status switch
        {
            DeliveryStatus.None => 7,
            DeliveryStatus.Pending => 5,
            DeliveryStatus.InTransit => 3,
            DeliveryStatus.Delivered => 0,
            _ => 0
        };
    }

    private bool CanCancelOrder(DeliveryStatus status, DateTime orderDate)
    {
        // فقط سفارشات Pending یا None که کمتر از 24 ساعت از ثبت آنها گذشته قابل لغو هستند
        if (status != DeliveryStatus.Pending && status != DeliveryStatus.None)
            return false;

        var hoursSinceOrder = (DateTime.UtcNow - orderDate).TotalHours;
        return hoursSinceOrder < 24;
    }
}
