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

namespace TakeoutSaaS.Domain.Tenants.Repositories;

/// <summary>
/// 租户聚合仓储。
/// </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="status">租户状态，为空不按状态过滤。</param>
    /// <param name="keyword">名称或编码关键字，为空不按关键字过滤。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>符合条件的租户列表。</returns>
    Task<IReadOnlyList<Tenant>> SearchAsync(
        TenantStatus? status,
        string? keyword,
        CancellationToken cancellationToken = default);

    /// <summary>
    /// 分页查询租户（支持多条件过滤）。
    /// </summary>
    /// <param name="status">租户状态，为空不按状态过滤。</param>
    /// <param name="verificationStatus">实名认证状态，为空不按认证状态过滤。</param>
    /// <param name="name">租户名称，为空不按名称过滤。</param>
    /// <param name="contactName">联系人姓名，为空不按联系人过滤。</param>
    /// <param name="contactPhone">联系电话，为空不按电话过滤。</param>
    /// <param name="keyword">兼容关键词：名称/编码/联系人/电话，为空不按关键字过滤。</param>
    /// <param name="page">页码（从 1 开始）。</param>
    /// <param name="pageSize">每页大小。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>分页数据与总数。</returns>
    Task<(IReadOnlyList<Tenant> Items, int Total)> SearchPagedAsync(
        TenantStatus? status,
        TenantVerificationStatus? verificationStatus,
        string? name,
        string? contactName,
        string? contactPhone,
        string? keyword,
        int page,
        int pageSize,
        CancellationToken cancellationToken = default);

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

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

    /// <summary>
    /// 判断编码是否存在。
    /// </summary>
    /// <param name="code">租户编码。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>存在返回 true，否则 false。</returns>
    Task<bool> ExistsByCodeAsync(string code, CancellationToken cancellationToken = default);

    /// <summary>
    /// 依据租户编码查询租户 ID。
    /// </summary>
    /// <param name="code">租户编码。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>租户 ID，未找到返回 null。</returns>
    Task<long?> FindIdByCodeAsync(string code, CancellationToken cancellationToken = default);

    /// <summary>
    /// 判断租户名称是否存在（支持排除指定租户）。
    /// </summary>
    /// <param name="name">租户名称。</param>
    /// <param name="excludeTenantId">排除的租户 ID（用于更新场景）。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>存在返回 true，否则 false。</returns>
    Task<bool> ExistsByNameAsync(string name, long? excludeTenantId = null, CancellationToken cancellationToken = default);

    /// <summary>
    /// 判断联系人手机号是否存在。
    /// </summary>
    /// <param name="phone">联系人手机号。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>存在返回 true，否则 false。</returns>
    Task<bool> ExistsByContactPhoneAsync(string phone, CancellationToken cancellationToken = default);

    /// <summary>
    /// 依据联系人手机号查询租户 ID。
    /// </summary>
    /// <param name="phone">联系人手机号。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>租户 ID，未找到返回 null。</returns>
    Task<long?> FindTenantIdByContactPhoneAsync(string phone, CancellationToken cancellationToken = default);

    /// <summary>
    /// 获取实名资料。
    /// </summary>
    /// <param name="tenantId">租户 ID（雪花算法）。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>实名资料实体，未提交返回 null。</returns>
    Task<TenantVerificationProfile?> GetVerificationProfileAsync(long tenantId, CancellationToken cancellationToken = default);

    /// <summary>
    /// 批量获取实名资料。
    /// </summary>
    /// <param name="tenantIds">租户 ID 列表。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>实名资料列表（未提交的不返回）。</returns>
    Task<IReadOnlyList<TenantVerificationProfile>> GetVerificationProfilesAsync(
        IReadOnlyCollection<long> tenantIds,
        CancellationToken cancellationToken = default);

    /// <summary>
    /// 新增或更新实名资料。
    /// </summary>
    /// <param name="profile">实名资料实体。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>异步任务。</returns>
    Task UpsertVerificationProfileAsync(TenantVerificationProfile profile, CancellationToken cancellationToken = default);

    /// <summary>
    /// 获取当前订阅。
    /// </summary>
    /// <param name="tenantId">租户 ID（雪花算法）。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>当前有效订阅，若无则 null。</returns>
    Task<TenantSubscription?> GetActiveSubscriptionAsync(long tenantId, CancellationToken cancellationToken = default);

    /// <summary>
    /// 批量获取当前订阅。
    /// </summary>
    /// <param name="tenantIds">租户 ID 列表。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>订阅列表（可能包含同一租户的多条订阅记录）。</returns>
    Task<IReadOnlyList<TenantSubscription>> GetSubscriptionsAsync(
        IReadOnlyCollection<long> tenantIds,
        CancellationToken cancellationToken = default);

    /// <summary>
    /// 依据订阅 ID 查询。
    /// </summary>
    /// <param name="tenantId">租户 ID（雪花算法）。</param>
    /// <param name="subscriptionId">订阅 ID（雪花算法）。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>订阅实体，未找到返回 null。</returns>
    Task<TenantSubscription?> FindSubscriptionByIdAsync(long tenantId, long subscriptionId, 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="subscription">订阅实体。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>异步任务。</returns>
    Task UpdateSubscriptionAsync(TenantSubscription subscription, CancellationToken cancellationToken = default);

    /// <summary>
    /// 记录订阅历史。
    /// </summary>
    /// <param name="history">订阅历史实体。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>异步任务。</returns>
    Task AddSubscriptionHistoryAsync(TenantSubscriptionHistory history, CancellationToken cancellationToken = default);

    /// <summary>
    /// 获取订阅历史。
    /// </summary>
    /// <param name="tenantId">租户 ID（雪花算法）。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>订阅历史列表。</returns>
    Task<IReadOnlyList<TenantSubscriptionHistory>> GetSubscriptionHistoryAsync(long tenantId, CancellationToken cancellationToken = default);

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

    /// <summary>
    /// 查询审核日志。
    /// </summary>
    /// <param name="tenantId">租户 ID（雪花算法）。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>审核日志列表。</returns>
    Task<IReadOnlyList<TenantAuditLog>> GetAuditLogsAsync(long tenantId, CancellationToken cancellationToken = default);

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