using TakeoutSaaS.Domain.Orders.Entities;
using TakeoutSaaS.Domain.Orders.Enums;
using TakeoutSaaS.Domain.Deliveries.Entities;
using TakeoutSaaS.Domain.Payments.Entities;
using TakeoutSaaS.Domain.Payments.Enums;

namespace TakeoutSaaS.Domain.Orders.Repositories;

/// <summary>
/// 订单聚合仓储契约。
/// </summary>
public interface IOrderRepository
{
    /// <summary>
    /// 依据标识获取订单。
    /// </summary>
    /// <param name="orderId">订单 ID。</param>
    /// <param name="tenantId">租户 ID。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>订单实体或 null。</returns>
    Task<Order?> FindByIdAsync(long orderId, long tenantId, CancellationToken cancellationToken = default);

    /// <summary>
    /// 依据订单号获取订单。
    /// </summary>
    /// <param name="orderNo">订单号。</param>
    /// <param name="tenantId">租户 ID。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>订单实体或 null。</returns>
    Task<Order?> FindByOrderNoAsync(string orderNo, long tenantId, CancellationToken cancellationToken = default);

    /// <summary>
    /// 按状态筛选订单列表。
    /// </summary>
    /// <param name="tenantId">租户 ID。</param>
    /// <param name="status">订单状态。</param>
    /// <param name="paymentStatus">支付状态。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>订单集合。</returns>
    Task<IReadOnlyList<Order>> SearchAsync(long tenantId, OrderStatus? status, PaymentStatus? paymentStatus, CancellationToken cancellationToken = default);

    /// <summary>
    /// 全部订单列表筛选查询。
    /// </summary>
    /// <param name="tenantId">租户 ID。</param>
    /// <param name="storeId">门店 ID。</param>
    /// <param name="startAt">开始时间（含）。</param>
    /// <param name="endAt">结束时间（不含）。</param>
    /// <param name="status">订单状态。</param>
    /// <param name="deliveryType">履约方式。</param>
    /// <param name="paymentMethod">支付方式。</param>
    /// <param name="keyword">关键词（订单号/手机号）。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>订单集合。</returns>
    Task<IReadOnlyList<Order>> SearchAllOrdersAsync(
        long tenantId,
        long? storeId,
        DateTime? startAt,
        DateTime? endAt,
        OrderStatus? status,
        DeliveryType? deliveryType,
        PaymentMethod? paymentMethod,
        string? keyword,
        CancellationToken cancellationToken = default);

    /// <summary>
    /// 全部订单分页筛选查询。
    /// </summary>
    /// <param name="tenantId">租户 ID。</param>
    /// <param name="storeId">门店 ID。</param>
    /// <param name="startAt">开始时间（含）。</param>
    /// <param name="endAt">结束时间（不含）。</param>
    /// <param name="status">订单状态。</param>
    /// <param name="refundedOnly">是否仅退款。</param>
    /// <param name="deliveryType">履约方式。</param>
    /// <param name="paymentMethod">支付方式。</param>
    /// <param name="keyword">关键词（订单号/手机号）。</param>
    /// <param name="sortBy">排序字段。</param>
    /// <param name="sortDescending">是否倒序。</param>
    /// <param name="page">页码。</param>
    /// <param name="pageSize">每页条数。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>分页订单与总数。</returns>
    Task<(IReadOnlyList<Order> Items, int TotalCount)> SearchAllOrdersPageAsync(
        long tenantId,
        long? storeId,
        DateTime? startAt,
        DateTime? endAt,
        OrderStatus? status,
        bool refundedOnly,
        DeliveryType? deliveryType,
        PaymentMethod? paymentMethod,
        string? keyword,
        string? sortBy,
        bool sortDescending,
        int page,
        int pageSize,
        CancellationToken cancellationToken = default);

    /// <summary>
    /// 获取订单明细行。
    /// </summary>
    /// <param name="orderId">订单 ID。</param>
    /// <param name="tenantId">租户 ID。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>订单明细集合。</returns>
    Task<IReadOnlyList<OrderItem>> GetItemsAsync(long orderId, long tenantId, CancellationToken cancellationToken = default);

    /// <summary>
    /// 按订单集合读取明细。
    /// </summary>
    /// <param name="orderIds">订单 ID 集合。</param>
    /// <param name="tenantId">租户 ID。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>订单明细字典。</returns>
    Task<IReadOnlyDictionary<long, IReadOnlyList<OrderItem>>> GetItemsByOrderIdsAsync(
        IReadOnlyCollection<long> orderIds,
        long tenantId,
        CancellationToken cancellationToken = default);

    /// <summary>
    /// 获取订单状态流转记录。
    /// </summary>
    /// <param name="orderId">订单 ID。</param>
    /// <param name="tenantId">租户 ID。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>状态变更记录列表。</returns>
    Task<IReadOnlyList<OrderStatusHistory>> GetStatusHistoryAsync(long orderId, long tenantId, CancellationToken cancellationToken = default);

    /// <summary>
    /// 获取订单退款申请。
    /// </summary>
    /// <param name="orderId">订单 ID。</param>
    /// <param name="tenantId">租户 ID。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>退款申请列表。</returns>
    Task<IReadOnlyList<RefundRequest>> GetRefundsAsync(long orderId, long tenantId, CancellationToken cancellationToken = default);

    /// <summary>
    /// 按订单集合查询已退款订单 ID。
    /// </summary>
    /// <param name="orderIds">订单 ID 集合。</param>
    /// <param name="tenantId">租户 ID。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>已退款订单 ID 集合。</returns>
    Task<IReadOnlySet<long>> GetRefundedOrderIdsAsync(
        IReadOnlyCollection<long> orderIds,
        long tenantId,
        CancellationToken cancellationToken = default);

    /// <summary>
    /// 获取订单最近支付记录。
    /// </summary>
    /// <param name="orderId">订单 ID。</param>
    /// <param name="tenantId">租户 ID。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>支付记录或 null。</returns>
    Task<PaymentRecord?> GetLatestPaymentRecordAsync(long orderId, long tenantId, CancellationToken cancellationToken = default);

    /// <summary>
    /// 获取订单最近配送单。
    /// </summary>
    /// <param name="orderId">订单 ID。</param>
    /// <param name="tenantId">租户 ID。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>配送单或 null。</returns>
    Task<DeliveryOrder?> GetLatestDeliveryOrderAsync(long orderId, long tenantId, CancellationToken cancellationToken = default);

    /// <summary>
    /// 新增订单。
    /// </summary>
    /// <param name="order">订单实体。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>异步任务。</returns>
    Task AddOrderAsync(Order order, CancellationToken cancellationToken = default);

    /// <summary>
    /// 新增订单明细。
    /// </summary>
    /// <param name="items">明细集合。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>异步任务。</returns>
    Task AddItemsAsync(IEnumerable<OrderItem> items, CancellationToken cancellationToken = default);

    /// <summary>
    /// 新增订单状态记录。
    /// </summary>
    /// <param name="history">状态记录。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>异步任务。</returns>
    Task AddStatusHistoryAsync(OrderStatusHistory history, CancellationToken cancellationToken = default);

    /// <summary>
    /// 新增退款申请。
    /// </summary>
    /// <param name="refund">退款申请实体。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>异步任务。</returns>
    Task AddRefundAsync(RefundRequest refund, CancellationToken cancellationToken = default);

    /// <summary>
    /// 持久化变更。
    /// </summary>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>异步任务。</returns>
    Task SaveChangesAsync(CancellationToken cancellationToken = default);

    /// <summary>
    /// 更新订单。
    /// </summary>
    /// <param name="order">订单实体。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>异步任务。</returns>
    Task UpdateOrderAsync(Order order, CancellationToken cancellationToken = default);

    /// <summary>
    /// 删除订单。
    /// </summary>
    /// <param name="orderId">订单 ID。</param>
    /// <param name="tenantId">租户 ID。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>异步任务。</returns>
    Task DeleteOrderAsync(long orderId, long tenantId, CancellationToken cancellationToken = default);

    /// <summary>
    /// 获取门店活跃订单（待接单、制作中、待取餐）。
    /// </summary>
    /// <param name="tenantId">租户 ID。</param>
    /// <param name="storeId">门店 ID。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>活跃订单集合。</returns>
    Task<IReadOnlyList<Order>> GetActiveOrdersAsync(long tenantId, long storeId, CancellationToken cancellationToken = default);

    /// <summary>
    /// 获取指定时间后变更的订单（重连补偿）。
    /// </summary>
    /// <param name="tenantId">租户 ID。</param>
    /// <param name="storeId">门店 ID。</param>
    /// <param name="since">起始时间（UTC）。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>变更订单集合。</returns>
    Task<IReadOnlyList<Order>> GetOrdersChangedSinceAsync(long tenantId, long storeId, DateTime since, CancellationToken cancellationToken = default);
}
