using MediatR;
using TakeoutSaaS.Application.App.Deliveries.Dto;
using TakeoutSaaS.Application.App.Deliveries.Queries;
using TakeoutSaaS.Domain.Deliveries.Repositories;
using TakeoutSaaS.Shared.Abstractions.Results;
using TakeoutSaaS.Shared.Abstractions.Tenancy;

namespace TakeoutSaaS.Application.App.Deliveries.Handlers;

/// <summary>
/// 配送单列表查询处理器。
/// </summary>
public sealed class SearchDeliveryOrdersQueryHandler(
    IDeliveryRepository deliveryRepository,
    ITenantProvider tenantProvider)
    : IRequestHandler<SearchDeliveryOrdersQuery, PagedResult<DeliveryOrderDto>>
{
    /// <inheritdoc />
    public async Task<PagedResult<DeliveryOrderDto>> Handle(SearchDeliveryOrdersQuery request, CancellationToken cancellationToken)
    {
        // 1. 获取当前租户标识
        var tenantId = tenantProvider.GetCurrentTenantId();

        // 2. 查询配送单列表（租户隔离）
        var orders = await deliveryRepository.SearchAsync(tenantId, request.Status, request.OrderId, cancellationToken);

        // 3. 本地排序
        var sorted = ApplySorting(orders, request.SortBy, request.SortDescending);

        // 4. 本地分页
        var paged = sorted
            .Skip((request.Page - 1) * request.PageSize)
            .Take(request.PageSize)
            .ToList();

        // 5. 映射 DTO
        var items = paged.Select(order => new DeliveryOrderDto
        {
            Id = order.Id,
            TenantId = order.TenantId,
            OrderId = order.OrderId,
            Provider = order.Provider,
            ProviderOrderId = order.ProviderOrderId,
            Status = order.Status,
            DeliveryFee = order.DeliveryFee,
            CourierName = order.CourierName,
            CourierPhone = order.CourierPhone,
            DispatchedAt = order.DispatchedAt,
            PickedUpAt = order.PickedUpAt,
            DeliveredAt = order.DeliveredAt,
            FailureReason = order.FailureReason,
            CreatedAt = order.CreatedAt
        }).ToList();

        // 6. 返回分页结果
        return new PagedResult<DeliveryOrderDto>(items, request.Page, request.PageSize, orders.Count);
    }

    private static IOrderedEnumerable<Domain.Deliveries.Entities.DeliveryOrder> ApplySorting(
        IReadOnlyCollection<Domain.Deliveries.Entities.DeliveryOrder> orders,
        string? sortBy,
        bool sortDescending)
    {
        return sortBy?.ToLowerInvariant() switch
        {
            "status" => sortDescending ? orders.OrderByDescending(x => x.Status) : orders.OrderBy(x => x.Status),
            "provider" => sortDescending ? orders.OrderByDescending(x => x.Provider) : orders.OrderBy(x => x.Provider),
            _ => sortDescending ? orders.OrderByDescending(x => x.CreatedAt) : orders.OrderBy(x => x.CreatedAt)
        };
    }
}
