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

namespace TakeoutSaaS.Domain.Tenants.Repositories;

/// <summary>
/// 订阅仓储（AdminApi 使用）。
/// </summary>
public interface ISubscriptionRepository
{
    /// <summary>
    /// 获取订阅列表（分页）。
    /// </summary>
    /// <param name="status">订阅状态。</param>
    /// <param name="tenantPackageId">套餐 ID。</param>
    /// <param name="tenantId">租户 ID。</param>
    /// <param name="tenantKeyword">租户关键词（名称或编码）。</param>
    /// <param name="expiringWithinDays">即将到期天数筛选。</param>
    /// <param name="autoRenew">是否自动续费。</param>
    /// <param name="expireFrom">到期时间范围开始。</param>
    /// <param name="expireTo">到期时间范围结束。</param>
    /// <param name="page">页码（从 1 开始）。</param>
    /// <param name="pageSize">每页条数。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>订阅列表和总数。</returns>
    Task<(IReadOnlyList<SubscriptionListResult> Items, int TotalCount)> GetListAsync(
        SubscriptionStatus? status,
        long? tenantPackageId,
        long? tenantId,
        string? tenantKeyword,
        int? expiringWithinDays,
        bool? autoRenew,
        DateTime? expireFrom,
        DateTime? expireTo,
        int page,
        int pageSize,
        CancellationToken cancellationToken = default);

    /// <summary>
    /// 根据 ID 获取订阅。
    /// </summary>
    /// <param name="subscriptionId">订阅 ID。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>订阅实体，不存在则返回 null。</returns>
    Task<TenantSubscription?> GetByIdAsync(long subscriptionId, CancellationToken cancellationToken = default);

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

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

    /// <summary>
    /// 获取订阅详情。
    /// </summary>
    /// <param name="subscriptionId">订阅 ID。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>订阅详情结果，不存在则返回 null。</returns>
    Task<SubscriptionDetailResult?> GetDetailAsync(long subscriptionId, CancellationToken cancellationToken = default);

    /// <summary>
    /// 获取订阅变更历史。
    /// </summary>
    /// <param name="subscriptionId">订阅 ID。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>变更历史列表。</returns>
    Task<IReadOnlyList<SubscriptionHistoryResult>> GetHistoriesAsync(long subscriptionId, CancellationToken cancellationToken = default);

    /// <summary>
    /// 获取订阅列表结果（单条，用于更新后返回）。
    /// </summary>
    /// <param name="subscriptionId">订阅 ID。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>订阅列表结果，不存在则返回 null。</returns>
    Task<SubscriptionListResult?> GetListResultByIdAsync(long subscriptionId, CancellationToken cancellationToken = default);
}

/// <summary>
/// 订阅列表结果。
/// </summary>
public sealed record SubscriptionListResult(
    long Id,
    long TenantId,
    string TenantName,
    string TenantCode,
    long TenantPackageId,
    string PackageName,
    long? ScheduledPackageId,
    string? ScheduledPackageName,
    SubscriptionStatus Status,
    DateTime EffectiveFrom,
    DateTime EffectiveTo,
    DateTime? NextBillingDate,
    bool AutoRenew,
    string? Notes,
    DateTime CreatedAt,
    DateTime? UpdatedAt);

/// <summary>
/// 订阅详情结果。
/// </summary>
public sealed record SubscriptionDetailResult(
    long Id,
    long TenantId,
    string TenantName,
    string TenantCode,
    long TenantPackageId,
    string PackageName,
    long? ScheduledPackageId,
    string? ScheduledPackageName,
    SubscriptionStatus Status,
    DateTime EffectiveFrom,
    DateTime EffectiveTo,
    DateTime? NextBillingDate,
    bool AutoRenew,
    string? Notes,
    DateTime CreatedAt,
    DateTime? UpdatedAt,
    TenantPackage Package,
    TenantPackage? ScheduledPackage);

/// <summary>
/// 订阅变更历史结果。
/// </summary>
public sealed record SubscriptionHistoryResult(
    long Id,
    long SubscriptionId,
    SubscriptionChangeType ChangeType,
    long FromPackageId,
    string FromPackageName,
    long ToPackageId,
    string ToPackageName,
    DateTime EffectiveFrom,
    DateTime EffectiveTo,
    string? Notes,
    DateTime CreatedAt,
    long? CreatedBy);
