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<DiscountOrderItem> 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<DiscountOrderSummary> 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<PlaceDiscountOrderResult> 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<bool> 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<DiscountOrderListResult> 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<DiscountOrderDetail?> 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 => "لغو شده",
        5 => "آماده تحویل در دفتر",
        6 => "مرجوع شده",
        _ => "نامشخص"
    };

    public static Color GetDeliveryStatusColor(int status) => status switch
    {
        0 => Color.Warning,
        1 => Color.Info,
        2 => Color.Primary,
        3 => Color.Success,
        4 => Color.Dark,
        5 => Color.Primary,
        6 => 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
    };
}
