using CMSMicroservice.Application.Common;
using CMSMicroservice.Application.Common.Exceptions;
using CMSMicroservice.Application.Common.Interfaces;
using CMSMicroservice.Application.Common.Services;
using CMSMicroservice.Domain.Entities.DiscountShop;
using CMSMicroservice.Domain.Entities.Payment;
using CMSMicroservice.Domain.Enums;
using MediatR;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;

namespace CMSMicroservice.Application.DiscountShopCQ.Commands.PlaceOrder;

public class PlaceOrderCommandHandler : IRequestHandler<PlaceOrderCommand, PlaceOrderResponseDto>
{
    private readonly IApplicationDbContext _context;
    private readonly IInventoryService _inventoryService;
    private readonly IPaymentGatewayService _paymentGateway;
    private readonly IConfiguration _configuration;
    private readonly ILogger<PlaceOrderCommandHandler> _logger;
    private readonly IUserPaymentLock _paymentLock;

    public PlaceOrderCommandHandler(
        IApplicationDbContext context,
        IInventoryService inventoryService,
        IPaymentGatewayService paymentGateway,
        IConfiguration configuration,
        ILogger<PlaceOrderCommandHandler> logger,
        IUserPaymentLock paymentLock)
    {
        _context = context;
        _inventoryService = inventoryService;
        _paymentGateway = paymentGateway;
        _configuration = configuration;
        _logger = logger;
        _paymentLock = paymentLock;
    }

    public Task<PlaceOrderResponseDto> Handle(PlaceOrderCommand request, CancellationToken cancellationToken) =>
        _paymentLock.ExecuteAsync(
            PaymentLockScopes.Initiate(request.UserId),
            PaymentLockStrategy.FailFast,
            ct => HandleCore(request, ct),
            cancellationToken);

    private async Task<PlaceOrderResponseDto> HandleCore(PlaceOrderCommand request, CancellationToken cancellationToken)
    {
        // Get user wallet
        var userWallet = await _context.UserWallets
            .FirstOrDefaultAsync(w => w.UserId == request.UserId, cancellationToken);

        if (userWallet == null)
        {
            return new PlaceOrderResponseDto
            {
                Success = false,
                Message = "کیف پول کاربر یافت نشد"
            };
        }

        // Get cart items with products
        var cartItems = await _context.DiscountShoppingCarts
            .Where(c => c.UserId == request.UserId)
            .Include(c => c.Product)
            .ToListAsync(cancellationToken);

        if (!cartItems.Any())
        {
            return new PlaceOrderResponseDto
            {
                Success = false,
                Message = "سبد خرید خالی است"
            };
        }

        // Validate stock and calculate totals
        long totalAmount = 0;
        long totalDiscountAmount = 0;
        var orderDetails = new List<DiscountOrderDetail>();

        foreach (var cartItem in cartItems)
        {
            var product = cartItem.Product;

            // Check stock
            if (product.RemainingCount < cartItem.Count)
            {
                return new PlaceOrderResponseDto
                {
                    Success = false,
                    Message = $"موجودی محصول '{product.Title}' کافی نیست"
                };
            }

            // Check if product is active
            if (!product.IsActive)
            {
                return new PlaceOrderResponseDto
                {
                    Success = false,
                    Message = $"محصول '{product.Title}' غیرفعال است"
                };
            }

            // Calculate discount for this product
            var itemTotal = product.Price * cartItem.Count;
            var maxDiscountForItem = (itemTotal * product.MaxDiscountPercent) / 100;

            totalAmount += itemTotal;
            totalDiscountAmount += maxDiscountForItem;

            orderDetails.Add(new DiscountOrderDetail
            {
                ProductId = product.Id,
                Count = cartItem.Count,
                UnitPrice = product.Price,
                DiscountPercentUsed = product.MaxDiscountPercent,
                DiscountAmount = maxDiscountForItem,
                FinalPrice = itemTotal - maxDiscountForItem
            });
        }

        // Always apply maximum possible discount (100%) — user cannot choose less
        var maxDiscountBalanceUsable = totalDiscountAmount;

        // بررسی کافی بودن موجودی کیف پول اعتباری (تخفیفی)
        if (userWallet.DiscountBalance < maxDiscountBalanceUsable)
        {
            return new PlaceOrderResponseDto
            {
                Success = false,
                Message = $"موجودی کیف پول اعتباری کافی نیست. مبلغ مورد نیاز: {maxDiscountBalanceUsable:N0} تومان، موجودی شما: {userWallet.DiscountBalance:N0} تومان"
            };
        }

        var actualDiscountBalanceUsed = maxDiscountBalanceUsable;

        _logger.LogInformation(
            "Discount auto-applied: max allowed={MaxAllowed}, wallet balance={WalletBalance}, used={Used}",
            maxDiscountBalanceUsable, userWallet.DiscountBalance, actualDiscountBalanceUsed);

        var gatewayAmountRequired = totalAmount - actualDiscountBalanceUsed;

        // Calculate VAT using centralized calculator
        var vatBreakdown = VatCalculator.CalculateBreakdown(gatewayAmountRequired);
        var vatAmount = vatBreakdown.VatAmount;
        var finalGatewayAmount = vatBreakdown.GrossAmount;

        // Create transaction for gateway payment
        var transaction = new Transaction
        {
            Amount = finalGatewayAmount,
            Description = $"خرید از فروشگاه تخفیف - مبلغ کل: {totalAmount:N0}، اعتبار تخفیف: {actualDiscountBalanceUsed:N0}",
            PaymentStatus = PaymentStatus.Pending,
            Type = TransactionType.DiscountShopPurchase
        };

        _context.Transactions.Add(transaction);
        await _context.SaveChangesAsync(cancellationToken);

        // Create order
        var order = new DiscountOrder
        {
            UserId = request.UserId,
            TotalAmount = totalAmount,
            DiscountBalanceUsed = actualDiscountBalanceUsed,
            GatewayAmountPaid = finalGatewayAmount,
            VatAmount = vatAmount,
            PaymentStatus = PaymentStatus.Pending,
            TransactionId = transaction.Id,
            UserAddressId = request.UserAddressId,
            DeliveryStatus = DeliveryStatus.Pending
        };

        _context.DiscountOrders.Add(order);
        await _context.SaveChangesAsync(cancellationToken);

        // Add order details
        foreach (var detail in orderDetails)
        {
            detail.DiscountOrderId = order.Id;
        }

        _context.DiscountOrderDetails.AddRange(orderDetails);

        // رزرو موجودی برای سفارش pending
        foreach (var cartItem in cartItems)
        {
            await _inventoryService.ReserveStockAsync(
                cartItem.ProductId,
                ProductType.DiscountProduct,
                cartItem.Count,
                order.Id,
                cancellationToken);
        }

        // Clear cart
        _context.DiscountShoppingCarts.RemoveRange(cartItems);

        await _context.SaveChangesAsync(cancellationToken);

        // اگر مبلغ درگاه > ۰ باشد، باید به درگاه پرداخت متصل شویم
        string? paymentUrl = null;

        if (finalGatewayAmount > 0)
        {
            try
            {
                // آدرس callback — زرین‌پال بعد از پرداخت مستقیم به فرانت‌آفیس هدایت می‌کند
                var frontOfficeBaseUrl = _configuration["FrontOfficeBaseUrl"] ?? "https://localhost:5268";
                var callbackUrl = $"{frontOfficeBaseUrl}/profile/payment-callback?type=discount-order&orderId={order.Id}";

                // درخواست به درگاه
                var paymentResult = await _paymentGateway.InitiatePaymentAsync(new PaymentRequest
                {
                    Amount = finalGatewayAmount,
                    UserId = request.UserId,
                    Description = $"فروشگاه تخفیفی - سفارش #{order.Id}",
                    CallbackUrl = callbackUrl
                }, cancellationToken);

                if (paymentResult.IsSuccess && !string.IsNullOrEmpty(paymentResult.GatewayUrl))
                {
                    // ذخیره Authority/RefId در تراکنش برای verify بعدی
                    transaction.RefId = paymentResult.RefId;

                    // ثبت PaymentTransaction — جدول جدید با اطلاعات درگاه
                    var paymentTx = new PaymentTransaction
                    {
                        GatewayProvider = _configuration["PaymentProvider"] ?? "zarinpal",
                        MerchantId = _configuration["ZarinPal:MerchantId"] ?? "",
                        Amount = finalGatewayAmount,
                        CallbackUrl = callbackUrl,
                        Description = $"فروشگاه تخفیفی - سفارش #{order.Id}",
                        Mobile = null,
                        UserId = request.UserId,
                        RequestStatusCode = 100,
                        RequestStatusMessage = "Success",
                        Authority = paymentResult.RefId,
                        PaymentStatus = false, // هنوز verify نشده
                        TransactionId = transaction.Id,
                        OrderId = order.Id.ToString()
                    };
                    _context.PaymentTransactions.Add(paymentTx);
                    await _context.SaveChangesAsync(cancellationToken);

                    paymentUrl = paymentResult.GatewayUrl;
                    _logger.LogInformation(
                        "Payment gateway initiated for DiscountOrder #{OrderId}: RefId={RefId}, Url={Url}",
                        order.Id, paymentResult.RefId, paymentResult.GatewayUrl);
                }
                else
                {
                    _logger.LogError(
                        "Payment gateway initiation failed for DiscountOrder #{OrderId}: {Error}",
                        order.Id, paymentResult.ErrorMessage);

                    return new PlaceOrderResponseDto
                    {
                        Success = false,
                        Message = $"خطا در اتصال به درگاه پرداخت: {paymentResult.ErrorMessage}",
                        OrderId = order.Id
                    };
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Payment gateway exception for DiscountOrder #{OrderId}", order.Id);
                return new PlaceOrderResponseDto
                {
                    Success = false,
                    Message = $"خطا در اتصال به درگاه پرداخت: {ex.Message}",
                    OrderId = order.Id
                };
            }
        }
        else
        {
            // اگر کل مبلغ از کیف تخفیفی پرداخت شد — مستقیماً تکمیل شود
            transaction.PaymentStatus = PaymentStatus.Success;
            transaction.PaymentDate = DateTime.Now;
            order.PaymentStatus = PaymentStatus.Success;
            order.PaymentDate = DateTime.Now;
            order.DeliveryStatus = DeliveryStatus.Pending;

            var walletForDeduct = await _context.UserWallets
                .FirstOrDefaultAsync(w => w.UserId == request.UserId, cancellationToken);
            if (walletForDeduct != null && actualDiscountBalanceUsed > 0)
            {
                walletForDeduct.DiscountBalance -= actualDiscountBalanceUsed;

                // ثبت لاگ تغییرات کیف پول
                _context.UserWalletHistories.Add(new Domain.Entities.UserWalletHistory
                {
                    WalletId = walletForDeduct.Id,
                    CurrentBalance = walletForDeduct.Balance,
                    ChangeValue = 0,
                    CurrentNetworkBalance = walletForDeduct.NetworkBalance,
                    ChangeNerworkValue = 0,
                    CurrentDiscountBalance = walletForDeduct.DiscountBalance,
                    ChangeDiscountValue = -actualDiscountBalanceUsed,
                    IsIncrease = false,
                    RefrenceId = transaction.Id
                });
            }

            foreach (var cartItem in cartItems)
            {
                await _inventoryService.ConfirmSaleAsync(
                    cartItem.ProductId, ProductType.DiscountProduct,
                    cartItem.Count, order.Id, cancellationToken);
                cartItem.Product.SaleCount += cartItem.Count;
            }

            await _context.SaveChangesAsync(cancellationToken);
            _logger.LogInformation(
                "DiscountOrder #{OrderId} fully paid via discount balance ({Amount} T)",
                order.Id, actualDiscountBalanceUsed);
        }

        return new PlaceOrderResponseDto
        {
            Success = true,
            Message = finalGatewayAmount > 0
                ? "سفارش ایجاد شد. در حال انتقال به درگاه پرداخت..."
                : "سفارش با موفقیت ثبت و پرداخت شد",
            OrderId = order.Id,
            TransactionId = transaction.Id,
            TotalAmount = totalAmount,
            DiscountBalanceUsed = actualDiscountBalanceUsed,
            GatewayAmountRequired = finalGatewayAmount,
            PaymentUrl = paymentUrl
        };
    }
}
