using TakeoutSaaS.Domain.Billings.Entities;
using TakeoutSaaS.Domain.Tenants.Entities;

namespace TakeoutSaaS.Domain.Tenants.Repositories;

/// <summary>
/// 租户仓储（AdminApi 使用）。
/// </summary>
public interface ITenantRepository
{
    /// <summary>
    /// 依据 ID 获取租户。
    /// </summary>
    /// <param name="tenantId">租户 ID（雪花算法）。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>租户实体，未找到返回 null。</returns>
    Task<Tenant?> FindByIdAsync(long tenantId, CancellationToken cancellationToken = default);

    /// <summary>
    /// 批量获取租户。
    /// </summary>
    /// <param name="tenantIds">租户 ID 列表。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>租户列表（仅返回找到的租户）。</returns>
    Task<IReadOnlyList<Tenant>> FindByIdsAsync(IReadOnlyCollection<long> tenantIds, CancellationToken cancellationToken = default);

    /// <summary>
    /// 根据编码查询租户是否存在。
    /// </summary>
    /// <param name="code">租户编码。</param>
    /// <param name="excludeTenantId">排除的租户 ID。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>存在返回 true。</returns>
    Task<bool> ExistsByCodeAsync(string code, long? excludeTenantId = null, CancellationToken cancellationToken = default);

    /// <summary>
    /// 获取所有租户列表（用于下拉选择器）。
    /// </summary>
    /// <param name="keyword">关键字（租户名称/编码）。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>租户列表。</returns>
    Task<IReadOnlyList<Tenant>> GetAllAsync(string? keyword, CancellationToken cancellationToken = default);

    /// <summary>
    /// 获取租户详情（包含认证、订阅、套餐信息）。
    /// </summary>
    /// <param name="tenantId">租户 ID。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>租户详情元组，未找到返回 null。</returns>
    Task<TenantDetailResult?> GetDetailAsync(long tenantId, CancellationToken cancellationToken = default);

    /// <summary>
    /// 获取租户配额使用情况列表。
    /// </summary>
    /// <param name="tenantId">租户 ID。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>配额使用情况列表。</returns>
    Task<IReadOnlyList<TenantQuotaUsage>> GetQuotaUsagesAsync(long tenantId, CancellationToken cancellationToken = default);

    /// <summary>
    /// 获取租户账单列表（分页）。
    /// </summary>
    /// <param name="tenantId">租户 ID。</param>
    /// <param name="page">页码（从 1 开始）。</param>
    /// <param name="pageSize">每页条数。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>账单列表和总数。</returns>
    Task<(IReadOnlyList<TenantBillingStatement> Items, int TotalCount)> GetBillingsAsync(
        long tenantId,
        int page,
        int pageSize,
        CancellationToken cancellationToken = default);

    /// <summary>
    /// 在事务中批量创建租户及相关数据。
    /// </summary>
    /// <param name="tenant">租户实体。</param>
    /// <param name="subscription">订阅实体。</param>
    /// <param name="verification">认证资料实体。</param>
    /// <param name="quotaUsages">配额使用记录列表。</param>
    /// <param name="billing">账单实体（可选）。</param>
    /// <param name="payment">支付记录实体（可选）。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>异步操作任务。</returns>
    Task CreateTenantWithRelatedDataAsync(
        Tenant tenant,
        TenantSubscription subscription,
        TenantVerificationProfile verification,
        IReadOnlyList<TenantQuotaUsage> quotaUsages,
        TenantBillingStatement? billing,
        TenantPayment? payment,
        CancellationToken cancellationToken = default);

    /// <summary>
    /// 根据 ID 获取租户（用于更新，带跟踪）。
    /// </summary>
    /// <param name="tenantId">租户 ID。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>租户实体，不存在则返回 null。</returns>
    Task<Tenant?> GetByIdForUpdateAsync(long tenantId, CancellationToken cancellationToken = default);

    /// <summary>
    /// 根据租户 ID 获取认证资料（用于更新，带跟踪）。
    /// </summary>
    /// <param name="tenantId">租户 ID。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>认证资料实体，不存在则返回 null。</returns>
    Task<TenantVerificationProfile?> GetVerificationForUpdateAsync(long tenantId, CancellationToken cancellationToken = default);

    /// <summary>
    /// 新增租户。
    /// </summary>
    /// <param name="tenant">租户实体。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>异步操作任务。</returns>
    Task AddAsync(Tenant tenant, CancellationToken cancellationToken = default);

    /// <summary>
    /// 新增租户订阅。
    /// </summary>
    /// <param name="subscription">订阅实体。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>异步操作任务。</returns>
    Task AddSubscriptionAsync(TenantSubscription subscription, CancellationToken cancellationToken = default);

    /// <summary>
    /// 新增租户认证资料。
    /// </summary>
    /// <param name="verification">认证资料实体。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>异步操作任务。</returns>
    Task AddVerificationAsync(TenantVerificationProfile verification, CancellationToken cancellationToken = default);

    /// <summary>
    /// 保存仓储变更。
    /// </summary>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>异步操作任务。</returns>
    Task SaveChangesAsync(CancellationToken cancellationToken = default);

    /// <summary>
    /// 获取租户当前有效的审核领取记录。
    /// </summary>
    /// <param name="tenantId">租户 ID。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>审核领取记录，未找到返回 null。</returns>
    Task<TenantReviewClaim?> GetActiveReviewClaimAsync(long tenantId, CancellationToken cancellationToken = default);

    /// <summary>
    /// 新增审核领取记录。
    /// </summary>
    /// <param name="claim">审核领取记录。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>异步操作任务。</returns>
    Task AddReviewClaimAsync(TenantReviewClaim claim, CancellationToken cancellationToken = default);

    /// <summary>
    /// 新增审核日志。
    /// </summary>
    /// <param name="auditLog">审核日志。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>异步操作任务。</returns>
    Task AddAuditLogAsync(TenantAuditLog auditLog, CancellationToken cancellationToken = default);

    /// <summary>
    /// 获取租户审核日志列表（分页）。
    /// </summary>
    /// <param name="tenantId">租户 ID。</param>
    /// <param name="page">页码（从 1 开始）。</param>
    /// <param name="pageSize">每页条数。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>审核日志列表和总数。</returns>
    Task<(IReadOnlyList<TenantAuditLog> Items, int TotalCount)> GetAuditLogsAsync(
        long tenantId,
        int page,
        int pageSize,
        CancellationToken cancellationToken = default);
}

/// <summary>
/// 租户详情查询结果。
/// </summary>
public sealed record TenantDetailResult(
    Tenant Tenant,
    TenantVerificationProfile? Verification,
    TenantSubscription? Subscription,
    TenantPackage? Package);
