using CMSMicroservice.Protobuf.Protos.DiscountOrder; using Google.Protobuf.WellKnownTypes; using MudBlazor; namespace FrontOffice.Main.Utilities; // ── DTOs ── public record DiscountOrderSummary( long Id, string OrderNumber, long TotalPrice, long DiscountBalanceUsed, long GatewayAmount, bool PaymentCompleted, int PaymentStatus, int DeliveryStatus, string? TrackingCode, int ItemsCount, DateTime Created); public record DiscountOrderDetail( long Id, string OrderNumber, long TotalPrice, long DiscountBalanceUsed, long GatewayAmount, bool PaymentCompleted, int PaymentStatus, string? TransactionId, int DeliveryStatus, string? TrackingCode, string? Notes, string? AdminNotes, DiscountOrderAddress? Address, List Items, DateTime Created); public record DiscountOrderAddress( long Id, string Title, string Address, string PostalCode, string? Phone); public record DiscountOrderItem( long ProductId, string Title, long UnitPrice, int MaxDiscountPercent, int Count, long TotalPrice, long DiscountAmount, long FinalPrice); public record PlaceDiscountOrderResult( bool Success, string Message, long OrderId, long GatewayAmount, string? PaymentUrl); public record DiscountOrderListResult( List Orders, int TotalCount, int TotalPages, int CurrentPage); // ── Service ── public class DiscountOrderService { private readonly DiscountOrderContract.DiscountOrderContractClient _client; public DiscountOrderService(DiscountOrderContract.DiscountOrderContractClient client) { _client = client; } public async Task PlaceOrderAsync(long addressId, long discountBalanceToUse, string? notes = null) { try { var request = new PlaceOrderRequest { UserAddressId = addressId, DiscountBalanceToUse = discountBalanceToUse }; if (!string.IsNullOrWhiteSpace(notes)) request.Notes = notes; var response = await _client.PlaceOrderAsync(request); return new PlaceDiscountOrderResult( Success: response.Success, Message: response.Message ?? string.Empty, OrderId: response.OrderId, GatewayAmount: response.GatewayAmount, PaymentUrl: response.PaymentUrl); } catch (Exception ex) { return new PlaceDiscountOrderResult(false, ex.Message, 0, 0, null); } } public async Task CompletePaymentAsync(long orderId, string? transactionId, bool success) { try { var response = await _client.CompleteOrderPaymentAsync(new CompleteOrderPaymentRequest { OrderId = orderId, TransactionId = transactionId, PaymentSuccess = success }); return response.Success; } catch { return false; } } public async Task<(bool Success, string Message, long OrderId)> VerifyDiscountOrderPaymentAsync( long orderId, string authority, string status) { try { var response = await _client.CustomerVerifyDiscountOrderPaymentAsync( new CustomerVerifyDiscountOrderPaymentRequest { OrderId = orderId, Authority = authority, Status = status }); return (response.Success, response.Message, response.OrderId); } catch (Grpc.Core.RpcException ex) { return (false, ex.Status.Detail ?? "خطا در بررسی وضعیت پرداخت", orderId); } } public async Task GetUserOrdersAsync(int page = 1, int pageSize = 10) { try { var response = await _client.GetUserOrdersAsync(new GetUserOrdersRequest { PageNumber = page, PageSize = pageSize }); var orders = response.Models.Select(m => new DiscountOrderSummary( Id: m.Id, OrderNumber: m.OrderNumber ?? string.Empty, TotalPrice: m.TotalPrice, DiscountBalanceUsed: m.DiscountBalanceUsed, GatewayAmount: m.GatewayAmount, PaymentCompleted: m.PaymentCompleted, PaymentStatus: (int)m.PaymentStatus, DeliveryStatus: (int)m.DeliveryStatus, TrackingCode: m.TrackingCode, ItemsCount: m.ItemsCount, Created: m.Created?.ToDateTime() ?? DateTime.MinValue )).ToList(); var totalCount = (int)(response.MetaData?.TotalCount ?? 0); var totalPages = (int)(response.MetaData?.TotalPage ?? 0); return new DiscountOrderListResult(orders, totalCount, totalPages, page); } catch { return new DiscountOrderListResult(new(), 0, 0, page); } } public async Task GetOrderByIdAsync(long orderId) { try { var r = await _client.GetOrderByIdAsync(new GetOrderByIdRequest { OrderId = orderId }); var address = r.Address != null ? new DiscountOrderAddress(r.Address.Id, r.Address.Title ?? "", r.Address.Address ?? "", r.Address.PostalCode ?? "", r.Address.Phone) : null; var items = r.Items.Select(i => new DiscountOrderItem( ProductId: i.ProductId, Title: i.ProductTitle ?? string.Empty, UnitPrice: i.UnitPrice, MaxDiscountPercent: i.MaxDiscountPercent, Count: i.Count, TotalPrice: i.TotalPrice, DiscountAmount: i.DiscountAmount, FinalPrice: i.FinalPrice )).ToList(); return new DiscountOrderDetail( Id: r.Id, OrderNumber: r.OrderNumber ?? string.Empty, TotalPrice: r.TotalPrice, DiscountBalanceUsed: r.DiscountBalanceUsed, GatewayAmount: r.GatewayAmount, PaymentCompleted: r.PaymentCompleted, PaymentStatus: (int)r.PaymentStatus, TransactionId: r.TransactionId, DeliveryStatus: (int)r.DeliveryStatus, TrackingCode: r.TrackingCode, Notes: r.Notes, AdminNotes: r.AdminNotes, Address: address, Items: items, Created: r.Created?.ToDateTime() ?? DateTime.MinValue); } catch { return null; } } public static string GetDeliveryStatusText(int status) => status switch { 0 => "در انتظار", 1 => "در حال پردازش", 2 => "ارسال شده", 3 => "تحویل داده شده", 4 => "لغو شده", _ => "نامشخص" }; public static Color GetDeliveryStatusColor(int status) => status switch { 0 => Color.Warning, 1 => Color.Info, 2 => Color.Primary, 3 => Color.Success, 4 => Color.Error, _ => Color.Default }; // PaymentStatus: 0=Pending, 1=Completed, 2=Failed, 3=Refunded public static string GetPaymentStatusText(int status) => status switch { 0 => "در انتظار پرداخت", 1 => "پرداخت شده", 2 => "پرداخت ناموفق", 3 => "بازگشت وجه", _ => "نامشخص" }; public static Color GetPaymentStatusColor(int status) => status switch { 0 => Color.Warning, 1 => Color.Success, 2 => Color.Error, 3 => Color.Info, _ => Color.Default }; }