using TakeoutSaaS.Domain.Tenants.Entities;
using TakeoutSaaS.Domain.Tenants.Enums;

namespace TakeoutSaaS.Domain.Tenants.Repositories;

/// <summary>
/// 配额包仓储。
/// </summary>
public interface IQuotaPackageRepository
{
    #region 配额包定义

    /// <summary>
    /// 按 ID 查找配额包。
    /// </summary>
    /// <param name="id">配额包 ID（雪花算法）。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>配额包实体，未找到返回 null。</returns>
    Task<QuotaPackage?> FindByIdAsync(long id, CancellationToken cancellationToken = default);

    /// <summary>
    /// 分页查询配额包。
    /// </summary>
    /// <param name="quotaType">配额类型，为空不按类型过滤。</param>
    /// <param name="isActive">启用状态，为空不按状态过滤。</param>
    /// <param name="page">页码（从 1 开始）。</param>
    /// <param name="pageSize">每页大小。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>分页数据与总数。</returns>
    Task<(IReadOnlyList<QuotaPackage> Items, int Total)> SearchPagedAsync(
        TenantQuotaType? quotaType,
        bool? isActive,
        int page,
        int pageSize,
        CancellationToken cancellationToken = default);

    /// <summary>
    /// 新增配额包。
    /// </summary>
    /// <param name="quotaPackage">配额包实体。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>异步任务。</returns>
    Task AddAsync(QuotaPackage quotaPackage, CancellationToken cancellationToken = default);

    /// <summary>
    /// 更新配额包。
    /// </summary>
    /// <param name="quotaPackage">配额包实体。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>异步任务。</returns>
    Task UpdateAsync(QuotaPackage quotaPackage, CancellationToken cancellationToken = default);

    /// <summary>
    /// 软删除配额包。
    /// </summary>
    /// <param name="id">配额包 ID（雪花算法）。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>删除成功返回 true，未找到返回 false。</returns>
    Task<bool> SoftDeleteAsync(long id, CancellationToken cancellationToken = default);

    #endregion

    #region 配额包购买记录

    /// <summary>
    /// 分页查询租户配额购买记录（包含配额包信息）。
    /// </summary>
    /// <param name="tenantId">租户 ID（雪花算法）。</param>
    /// <param name="page">页码（从 1 开始）。</param>
    /// <param name="pageSize">每页大小。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>分页数据与总数。</returns>
    Task<(IReadOnlyList<(TenantQuotaPackagePurchase Purchase, QuotaPackage Package)> Items, int Total)> GetPurchasesPagedAsync(
        long tenantId,
        int page,
        int pageSize,
        CancellationToken cancellationToken = default);

    /// <summary>
    /// 新增配额购买记录。
    /// </summary>
    /// <param name="purchase">购买记录实体。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>异步任务。</returns>
    Task AddPurchaseAsync(TenantQuotaPackagePurchase purchase, CancellationToken cancellationToken = default);

    #endregion

    #region 配额使用情况

    /// <summary>
    /// 查询租户配额使用情况。
    /// </summary>
    /// <param name="tenantId">租户 ID（雪花算法）。</param>
    /// <param name="quotaType">配额类型，为空查询全部。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>配额使用情况列表。</returns>
    Task<IReadOnlyList<TenantQuotaUsage>> GetUsageByTenantAsync(
        long tenantId,
        TenantQuotaType? quotaType,
        CancellationToken cancellationToken = default);

    /// <summary>
    /// 查找特定配额使用记录。
    /// </summary>
    /// <param name="tenantId">租户 ID（雪花算法）。</param>
    /// <param name="quotaType">配额类型。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>配额使用记录，未找到返回 null。</returns>
    Task<TenantQuotaUsage?> FindUsageAsync(
        long tenantId,
        TenantQuotaType quotaType,
        CancellationToken cancellationToken = default);

    /// <summary>
    /// 更新配额使用情况。
    /// </summary>
    /// <param name="usage">配额使用实体。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>异步任务。</returns>
    Task UpdateUsageAsync(TenantQuotaUsage usage, CancellationToken cancellationToken = default);

    #endregion

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