using MediatR;
using Microsoft.Extensions.Logging;
using TakeoutSaaS.Application.App.Payments.Commands;
using TakeoutSaaS.Application.Messaging;
using TakeoutSaaS.Application.Messaging.Abstractions;
using TakeoutSaaS.Application.Messaging.Events;
using TakeoutSaaS.Domain.Orders.Entities;
using TakeoutSaaS.Domain.Orders.Enums;
using TakeoutSaaS.Domain.Orders.Repositories;
using TakeoutSaaS.Domain.Payments.Entities;
using TakeoutSaaS.Domain.Payments.Enums;
using TakeoutSaaS.Domain.Payments.Repositories;
using TakeoutSaaS.Shared.Abstractions.Constants;
using TakeoutSaaS.Shared.Abstractions.Exceptions;
using TakeoutSaaS.Shared.Abstractions.Ids;

namespace TakeoutSaaS.Application.App.Payments.Handlers;

/// <summary>
/// 支付回调处理器。
/// </summary>
public sealed class ProcessPaymentCallbackCommandHandler(
    IOrderRepository orderRepository,
    IPaymentRepository paymentRepository,
    IEventPublisher eventPublisher,
    IIdGenerator idGenerator,
    ILogger<ProcessPaymentCallbackCommandHandler> logger)
    : IRequestHandler<ProcessPaymentCallbackCommand, bool>
{
    /// <inheritdoc />
    public async Task<bool> Handle(ProcessPaymentCallbackCommand request, CancellationToken cancellationToken)
    {
        // 1. 通过 OrderNo 查找订单
        var order = await orderRepository.FindByOrderNoAsync(request.OrderNo, request.TenantId, cancellationToken)
            ?? throw new BusinessException(ErrorCodes.NotFound, "订单不存在");

        // 2. 幂等检查：已支付则直接返回
        if (order.PaymentStatus == PaymentStatus.Paid)
        {
            logger.LogWarning("订单 {OrderNo} 重复支付回调，已忽略", request.OrderNo);
            return true;
        }

        // 3. 校验订单状态
        if (order.Status != OrderStatus.PendingPayment)
        {
            throw new BusinessException(ErrorCodes.BadRequest, $"订单状态 {order.Status} 不允许支付");
        }

        // 4. 创建支付记录
        var paymentRecord = new PaymentRecord
        {
            Id = idGenerator.NextId(),
            TenantId = order.TenantId,
            OrderId = order.Id,
            Method = request.Method,
            Status = PaymentStatus.Paid,
            Amount = request.Amount,
            ChannelTransactionId = request.ChannelTransactionId,
            PaidAt = request.PaidAt,
            Payload = request.RawPayload
        };
        await paymentRepository.AddPaymentAsync(paymentRecord, cancellationToken);

        // 5. 更新订单支付状态与订单状态
        order.PaymentStatus = PaymentStatus.Paid;
        order.PaidAmount = request.Amount;
        order.PaidAt = request.PaidAt;
        order.Status = OrderStatus.AwaitingPreparation;
        await orderRepository.UpdateOrderAsync(order, cancellationToken);

        // 6. 写入状态流转记录
        var history = new OrderStatusHistory
        {
            Id = idGenerator.NextId(),
            OrderId = order.Id,
            TenantId = order.TenantId,
            Status = OrderStatus.AwaitingPreparation,
            Notes = "支付成功，进入待接单",
            OccurredAt = request.PaidAt
        };
        await orderRepository.AddStatusHistoryAsync(history, cancellationToken);

        // 7. 持久化
        await orderRepository.SaveChangesAsync(cancellationToken);

        // 8. 构建商品摘要
        var items = await orderRepository.GetItemsAsync(order.Id, order.TenantId, cancellationToken);
        var itemsSummary = items.Count > 0
            ? string.Join("、", items.Take(3).Select(x => x.ProductName))
              + (items.Count > 3 ? $" 等{items.Count}件" : string.Empty)
            : string.Empty;

        // 9. 发布支付成功事件
        await eventPublisher.PublishAsync(EventRoutingKeys.PaymentSucceeded, new PaymentSucceededEvent
        {
            OrderId = order.Id,
            PaymentNo = paymentRecord.TradeNo ?? string.Empty,
            Amount = request.Amount,
            TenantId = order.TenantId,
            StoreId = order.StoreId,
            OrderNo = order.OrderNo,
            Channel = (int)order.Channel,
            DeliveryType = (int)order.DeliveryType,
            CustomerName = order.CustomerName,
            ItemsSummary = itemsSummary,
            PaidAt = request.PaidAt
        }, cancellationToken);

        // 10. 发布订单状态变更事件（触发 SignalR 推送）
        await eventPublisher.PublishAsync(EventRoutingKeys.OrderStatusChanged, new OrderStatusChangedEvent
        {
            OrderId = order.Id,
            OrderNo = order.OrderNo,
            TenantId = order.TenantId,
            StoreId = order.StoreId,
            OldStatus = (int)OrderStatus.PendingPayment,
            NewStatus = (int)OrderStatus.AwaitingPreparation,
            Channel = (int)order.Channel,
            DeliveryType = (int)order.DeliveryType,
            CustomerName = order.CustomerName,
            ItemsSummary = itemsSummary,
            PaidAmount = request.Amount,
            OccurredAt = request.PaidAt
        }, cancellationToken);

        // 11. 记录日志
        logger.LogInformation("支付回调成功 {OrderNo}，金额 {Amount}", request.OrderNo, request.Amount);

        return true;
    }
}
