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 { private readonly IApplicationDbContext _context; private readonly ICurrentUserService _currentUser; public GetCustomerOrderHistoryQueryHandler( IApplicationDbContext context, ICurrentUserService currentUser) { _context = context; _currentUser = currentUser; } public async Task 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, _ => 0 }; } private string GetStatusMessage(DeliveryStatus status) { return status switch { DeliveryStatus.None => "ثبت نشده", DeliveryStatus.Pending => "در انتظار پردازش", DeliveryStatus.InTransit => "ارسال شده", DeliveryStatus.Delivered => "تحویل داده شد", DeliveryStatus.Cancelled => "لغو شده", DeliveryStatus.Returned => "مرجوع شده", _ => "نامشخص" }; } 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; } }