using MediatR;
using TakeoutSaaS.Application.App.Orders.Dto;
using TakeoutSaaS.Application.App.Orders.Queries;
using TakeoutSaaS.Domain.Orders.Entities;
using TakeoutSaaS.Domain.Orders.Repositories;
using TakeoutSaaS.Shared.Abstractions.Tenancy;

namespace TakeoutSaaS.Application.App.Orders.Handlers;

/// <summary>
/// 订单详情查询处理器。
/// </summary>
public sealed class GetOrderByIdQueryHandler(
    IOrderRepository orderRepository,
    ITenantProvider tenantProvider)
    : IRequestHandler<GetOrderByIdQuery, OrderDto?>
{
    /// <inheritdoc />
    public async Task<OrderDto?> Handle(GetOrderByIdQuery request, CancellationToken cancellationToken)
    {
        // 1. 获取当前租户
        var tenantId = tenantProvider.GetCurrentTenantId();

        // 2. 查询订单主体
        var order = await orderRepository.FindByIdAsync(request.OrderId, tenantId, cancellationToken);
        if (order == null)
        {
            return null;
        }

        // 3. 查询关联明细
        var items = await orderRepository.GetItemsAsync(order.Id, tenantId, cancellationToken);
        var histories = await orderRepository.GetStatusHistoryAsync(order.Id, tenantId, cancellationToken);
        var refunds = await orderRepository.GetRefundsAsync(order.Id, tenantId, cancellationToken);

        // 4. 映射并返回
        return MapToDto(order, items, histories, refunds);
    }

    private static OrderDto MapToDto(
        Order order,
        IReadOnlyList<OrderItem> items,
        IReadOnlyList<OrderStatusHistory> histories,
        IReadOnlyList<RefundRequest> refunds) => new()
        {
            Id = order.Id,
            TenantId = order.TenantId,
            OrderNo = order.OrderNo,
            StoreId = order.StoreId,
            Channel = order.Channel,
            DeliveryType = order.DeliveryType,
            Status = order.Status,
            PaymentStatus = order.PaymentStatus,
            CustomerName = order.CustomerName,
            CustomerPhone = order.CustomerPhone,
            TableNo = order.TableNo,
            QueueNumber = order.QueueNumber,
            ReservationId = order.ReservationId,
            ItemsAmount = order.ItemsAmount,
            DiscountAmount = order.DiscountAmount,
            PayableAmount = order.PayableAmount,
            PaidAmount = order.PaidAmount,
            PaidAt = order.PaidAt,
            FinishedAt = order.FinishedAt,
            CancelledAt = order.CancelledAt,
            CancelReason = order.CancelReason,
            Remark = order.Remark,
            Items = items.Select(x => new OrderItemDto
            {
                Id = x.Id,
                OrderId = x.OrderId,
                ProductId = x.ProductId,
                ProductName = x.ProductName,
                SkuName = x.SkuName,
                Unit = x.Unit,
                Quantity = x.Quantity,
                UnitPrice = x.UnitPrice,
                DiscountAmount = x.DiscountAmount,
                SubTotal = x.SubTotal,
                AttributesJson = x.AttributesJson
            }).ToList(),
            StatusHistory = histories.Select(x => new OrderStatusHistoryDto
            {
                Id = x.Id,
                OrderId = x.OrderId,
                Status = x.Status,
                OperatorId = x.OperatorId,
                Notes = x.Notes,
                OccurredAt = x.OccurredAt
            }).ToList(),
            Refunds = refunds.Select(x => new RefundRequestDto
            {
                Id = x.Id,
                OrderId = x.OrderId,
                RefundNo = x.RefundNo,
                Amount = x.Amount,
                Reason = x.Reason,
                Status = x.Status,
                RequestedAt = x.RequestedAt,
                ProcessedAt = x.ProcessedAt,
                ReviewNotes = x.ReviewNotes
            }).ToList(),
            CreatedAt = order.CreatedAt
        };
}
