// EN: Handler for CreateExchangeCommand.
// VI: Handler cho CreateExchangeCommand.

using MediatR;
using OrderService.API.Application.DTOs;
using OrderService.Domain.AggregatesModel.OrderAggregate;
using OrderService.Domain.Events;

namespace OrderService.API.Application.Commands;

/// <summary>
/// EN: Handler for exchange — processes return + creates new order in same transaction.
/// VI: Handler cho đổi hàng — xử lý trả hàng + tạo đơn mới trong cùng transaction.
/// </summary>
public class CreateExchangeCommandHandler : IRequestHandler<CreateExchangeCommand, CreateExchangeResult>
{
    private readonly IOrderRepository _orderRepository;
    private readonly ILogger<CreateExchangeCommandHandler> _logger;

    public CreateExchangeCommandHandler(
        IOrderRepository orderRepository,
        ILogger<CreateExchangeCommandHandler> logger)
    {
        _orderRepository = orderRepository ?? throw new ArgumentNullException(nameof(orderRepository));
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }

    public async Task<CreateExchangeResult> Handle(CreateExchangeCommand request, CancellationToken cancellationToken)
    {
        _logger.LogInformation(
            "EN: Processing exchange for order {OriginalOrderId} in shop {ShopId} / VI: Xử lý đổi hàng cho đơn {OriginalOrderId} trong shop {ShopId}",
            request.OriginalOrderId, request.ShopId);

        // EN: Validate original order
        // VI: Xác thực đơn hàng gốc
        var originalOrder = await _orderRepository.GetByIdAsync(request.OriginalOrderId, cancellationToken);

        if (originalOrder == null)
        {
            return new CreateExchangeResult(false, null, null, null,
                $"Original order {request.OriginalOrderId} not found / Đơn hàng gốc {request.OriginalOrderId} không tìm thấy");
        }

        if (originalOrder.ShopId != request.ShopId)
        {
            return new CreateExchangeResult(false, null, null, null,
                "Order does not belong to this shop / Đơn hàng không thuộc shop này");
        }

        if (originalOrder.Status != OrderStatus.Completed && originalOrder.Status != OrderStatus.Paid)
        {
            return new CreateExchangeResult(false, null, null, null,
                $"Cannot exchange order with status {originalOrder.Status.Name} / Không thể đổi hàng cho đơn có trạng thái {originalOrder.Status.Name}");
        }

        var originalItemsMap = originalOrder.Items.ToDictionary(i => i.Id);

        // EN: Step 1: Create return order
        // VI: Bước 1: Tạo đơn trả hàng
        var returnOrder = new Order(request.ShopId, originalOrder.CustomerId);
        decimal returnAmount = 0;

        foreach (var returnItem in request.ReturnItems)
        {
            if (!originalItemsMap.TryGetValue(returnItem.OrderItemId, out var originalItem))
            {
                return new CreateExchangeResult(false, null, null, null,
                    $"Order item {returnItem.OrderItemId} not found in original order / Item {returnItem.OrderItemId} không tìm thấy trong đơn gốc");
            }

            if (returnItem.Quantity <= 0 || returnItem.Quantity > originalItem.Quantity)
            {
                return new CreateExchangeResult(false, null, null, null,
                    $"Invalid return quantity for item {returnItem.OrderItemId} / Số lượng trả không hợp lệ cho item {returnItem.OrderItemId}");
            }

            var orderItem = new OrderItem(
                originalItem.ProductId,
                originalItem.ProductName,
                originalItem.ProductType,
                returnItem.Quantity,
                originalItem.UnitPrice,
                metadata: returnItem.Reason,
                trackInventory: originalItem.TrackInventory);

            returnOrder.AddItem(orderItem);
            returnAmount += returnItem.Quantity * originalItem.UnitPrice;
        }

        returnOrder.MarkAsValidated();
        returnOrder.ProcessReturn(request.Reason, request.OriginalOrderId);

        // EN: Step 2: Create new order with replacement items
        // VI: Bước 2: Tạo đơn mới với items thay thế
        var newOrder = new Order(request.ShopId, originalOrder.CustomerId);
        decimal newOrderAmount = 0;

        foreach (var newItem in request.NewItems)
        {
            // EN: Product name will need to be passed from frontend or resolved via cross-service call.
            //     For now, use "Exchange Item" as placeholder — frontend should pass full product info.
            // VI: Tên sản phẩm cần được truyền từ frontend hoặc resolve qua cross-service call.
            //     Tạm thời dùng "Exchange Item" — frontend nên truyền đầy đủ thông tin sản phẩm.
            var orderItem = new OrderItem(
                newItem.ProductId,
                "Exchange Item", // EN: Should be resolved / VI: Cần được resolve
                "Physical",
                newItem.Quantity,
                newItem.UnitPrice,
                trackInventory: true);

            newOrder.AddItem(orderItem);
            newOrderAmount += newItem.Quantity * newItem.UnitPrice;
        }

        newOrder.MarkAsValidated();

        // EN: Calculate price difference (positive = customer pays more, negative = refund)
        // VI: Tính chênh lệch giá (dương = khách trả thêm, âm = hoàn tiền)
        decimal priceDifference = newOrderAmount - returnAmount;

        _orderRepository.Add(returnOrder);
        _orderRepository.Add(newOrder);

        // EN: Raise exchange domain event
        // VI: Phát ra domain event đổi hàng
        returnOrder.AddDomainEvent(new OrderExchangedDomainEvent(returnOrder, newOrder));

        await _orderRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken);

        _logger.LogInformation(
            "EN: Exchange processed — Return: {ReturnId}, New: {NewId}, Difference: {Diff} / VI: Đổi hàng đã xử lý — Trả: {ReturnId}, Mới: {NewId}, Chênh lệch: {Diff}",
            returnOrder.Id, newOrder.Id, priceDifference);

        return new CreateExchangeResult(true, returnOrder.Id, newOrder.Id, priceDifference, null);
    }
}
