using MediatR;
using Microsoft.Extensions.Logging;
using TakeoutSaaS.Application.App.Deliveries.Commands;
using TakeoutSaaS.Application.App.Deliveries.Dto;
using TakeoutSaaS.Domain.Deliveries.Entities;
using TakeoutSaaS.Domain.Deliveries.Repositories;

namespace TakeoutSaaS.Application.App.Deliveries.Handlers;

/// <summary>
/// 创建配送单命令处理器。
/// </summary>
public sealed class CreateDeliveryOrderCommandHandler(IDeliveryRepository deliveryRepository, ILogger<CreateDeliveryOrderCommandHandler> logger)
    : IRequestHandler<CreateDeliveryOrderCommand, DeliveryOrderDto>
{
    /// <inheritdoc />
    public async Task<DeliveryOrderDto> Handle(CreateDeliveryOrderCommand request, CancellationToken cancellationToken)
    {
        // 1. 构建配送单实体
        var deliveryOrder = new DeliveryOrder
        {
            OrderId = request.OrderId,
            Provider = request.Provider,
            ProviderOrderId = request.ProviderOrderId?.Trim(),
            Status = request.Status,
            DeliveryFee = request.DeliveryFee,
            CourierName = request.CourierName?.Trim(),
            CourierPhone = request.CourierPhone?.Trim(),
            DispatchedAt = request.DispatchedAt,
            PickedUpAt = request.PickedUpAt,
            DeliveredAt = request.DeliveredAt,
            FailureReason = request.FailureReason?.Trim()
        };

        // 2. 持久化配送单
        await deliveryRepository.AddDeliveryOrderAsync(deliveryOrder, cancellationToken);
        await deliveryRepository.SaveChangesAsync(cancellationToken);

        // 3. 记录日志
        logger.LogInformation("创建配送单 {DeliveryOrderId} 对应订单 {OrderId}", deliveryOrder.Id, deliveryOrder.OrderId);

        // 4. 映射 DTO 返回
        return MapToDto(deliveryOrder, []);
    }

    private static DeliveryOrderDto MapToDto(DeliveryOrder deliveryOrder, IReadOnlyList<DeliveryEvent> events) => new()
    {
        Id = deliveryOrder.Id,
        TenantId = deliveryOrder.TenantId,
        OrderId = deliveryOrder.OrderId,
        Provider = deliveryOrder.Provider,
        ProviderOrderId = deliveryOrder.ProviderOrderId,
        Status = deliveryOrder.Status,
        DeliveryFee = deliveryOrder.DeliveryFee,
        CourierName = deliveryOrder.CourierName,
        CourierPhone = deliveryOrder.CourierPhone,
        DispatchedAt = deliveryOrder.DispatchedAt,
        PickedUpAt = deliveryOrder.PickedUpAt,
        DeliveredAt = deliveryOrder.DeliveredAt,
        FailureReason = deliveryOrder.FailureReason,
        CreatedAt = deliveryOrder.CreatedAt,
        Events = events.Select(x => new DeliveryEventDto
        {
            Id = x.Id,
            DeliveryOrderId = x.DeliveryOrderId,
            EventType = x.EventType,
            Message = x.Message,
            OccurredAt = x.OccurredAt,
            Payload = x.Payload
        }).ToList()
    };
}
