using TakeoutSaaS.Domain.Coupons.Entities;
using TakeoutSaaS.Domain.Coupons.Enums;

namespace TakeoutSaaS.Domain.Coupons.Repositories;

/// <summary>
/// 次卡管理仓储契约。
/// </summary>
public interface IPunchCardRepository
{
    /// <summary>
    /// 查询次卡模板分页。
    /// </summary>
    Task<(IReadOnlyList<PunchCardTemplate> Items, int TotalCount)> SearchTemplatesAsync(
        long tenantId,
        long storeId,
        string? keyword,
        PunchCardStatus? status,
        int page,
        int pageSize,
        CancellationToken cancellationToken = default);

    /// <summary>
    /// 读取指定次卡模板。
    /// </summary>
    Task<PunchCardTemplate?> FindTemplateByIdAsync(
        long tenantId,
        long storeId,
        long templateId,
        CancellationToken cancellationToken = default);

    /// <summary>
    /// 按标识批量读取次卡模板。
    /// </summary>
    Task<IReadOnlyList<PunchCardTemplate>> GetTemplatesByIdsAsync(
        long tenantId,
        long storeId,
        IReadOnlyCollection<long> templateIds,
        CancellationToken cancellationToken = default);

    /// <summary>
    /// 查询单门店全部次卡模板。
    /// </summary>
    Task<IReadOnlyList<PunchCardTemplate>> GetTemplatesByStoreAsync(
        long tenantId,
        long storeId,
        CancellationToken cancellationToken = default);

    /// <summary>
    /// 按模板批量统计售卖与在用信息。
    /// </summary>
    Task<Dictionary<long, PunchCardTemplateAggregateSnapshot>> GetTemplateAggregateByTemplateIdsAsync(
        long tenantId,
        long storeId,
        IReadOnlyCollection<long> templateIds,
        CancellationToken cancellationToken = default);

    /// <summary>
    /// 查询页面统计。
    /// </summary>
    Task<PunchCardTemplateStatsSnapshot> GetTemplateStatsAsync(
        long tenantId,
        long storeId,
        CancellationToken cancellationToken = default);

    /// <summary>
    /// 新增次卡模板。
    /// </summary>
    Task AddTemplateAsync(PunchCardTemplate entity, CancellationToken cancellationToken = default);

    /// <summary>
    /// 更新次卡模板。
    /// </summary>
    Task UpdateTemplateAsync(PunchCardTemplate entity, CancellationToken cancellationToken = default);

    /// <summary>
    /// 删除次卡模板。
    /// </summary>
    Task DeleteTemplateAsync(PunchCardTemplate entity, CancellationToken cancellationToken = default);

    /// <summary>
    /// 查询次卡实例。
    /// </summary>
    Task<PunchCardInstance?> FindInstanceByNoAsync(
        long tenantId,
        long storeId,
        string instanceNo,
        CancellationToken cancellationToken = default);

    /// <summary>
    /// 查询次卡实例。
    /// </summary>
    Task<PunchCardInstance?> FindInstanceByIdAsync(
        long tenantId,
        long storeId,
        long instanceId,
        CancellationToken cancellationToken = default);

    /// <summary>
    /// 按标识批量读取次卡实例。
    /// </summary>
    Task<IReadOnlyList<PunchCardInstance>> GetInstancesByIdsAsync(
        long tenantId,
        long storeId,
        IReadOnlyCollection<long> instanceIds,
        CancellationToken cancellationToken = default);

    /// <summary>
    /// 新增次卡实例。
    /// </summary>
    Task AddInstanceAsync(PunchCardInstance entity, CancellationToken cancellationToken = default);

    /// <summary>
    /// 更新次卡实例。
    /// </summary>
    Task UpdateInstanceAsync(PunchCardInstance entity, CancellationToken cancellationToken = default);

    /// <summary>
    /// 查询使用记录分页。
    /// </summary>
    Task<(IReadOnlyList<PunchCardUsageRecord> Items, int TotalCount)> SearchUsageRecordsAsync(
        long tenantId,
        long storeId,
        long? templateId,
        string? keyword,
        PunchCardUsageRecordFilterStatus? status,
        int page,
        int pageSize,
        CancellationToken cancellationToken = default);

    /// <summary>
    /// 查询导出使用记录（不分页）。
    /// </summary>
    Task<IReadOnlyList<PunchCardUsageRecord>> ListUsageRecordsForExportAsync(
        long tenantId,
        long storeId,
        long? templateId,
        string? keyword,
        PunchCardUsageRecordFilterStatus? status,
        CancellationToken cancellationToken = default);

    /// <summary>
    /// 查询使用记录统计。
    /// </summary>
    Task<PunchCardUsageStatsSnapshot> GetUsageStatsAsync(
        long tenantId,
        long storeId,
        long? templateId,
        DateTime nowUtc,
        CancellationToken cancellationToken = default);

    /// <summary>
    /// 新增使用记录。
    /// </summary>
    Task AddUsageRecordAsync(PunchCardUsageRecord entity, CancellationToken cancellationToken = default);

    /// <summary>
    /// 持久化变更。
    /// </summary>
    Task SaveChangesAsync(CancellationToken cancellationToken = default);
}

/// <summary>
/// 次卡模板聚合快照。
/// </summary>
public sealed record PunchCardTemplateAggregateSnapshot
{
    /// <summary>
    /// 次卡模板标识。
    /// </summary>
    public required long TemplateId { get; init; }

    /// <summary>
    /// 已售数量。
    /// </summary>
    public int SoldCount { get; init; }

    /// <summary>
    /// 在用数量。
    /// </summary>
    public int ActiveCount { get; init; }

    /// <summary>
    /// 累计收入。
    /// </summary>
    public decimal RevenueAmount { get; init; }
}

/// <summary>
/// 次卡模板统计快照。
/// </summary>
public sealed record PunchCardTemplateStatsSnapshot
{
    /// <summary>
    /// 在售数量。
    /// </summary>
    public int OnSaleCount { get; init; }

    /// <summary>
    /// 累计售出数量。
    /// </summary>
    public int TotalSoldCount { get; init; }

    /// <summary>
    /// 累计收入。
    /// </summary>
    public decimal TotalRevenueAmount { get; init; }

    /// <summary>
    /// 使用中数量。
    /// </summary>
    public int ActiveInUseCount { get; init; }
}

/// <summary>
/// 使用记录筛选状态。
/// </summary>
public enum PunchCardUsageRecordFilterStatus
{
    /// <summary>
    /// 正常（包含即将用完）。
    /// </summary>
    Normal = 0,

    /// <summary>
    /// 已用完。
    /// </summary>
    UsedUp = 1,

    /// <summary>
    /// 已过期。
    /// </summary>
    Expired = 2
}

/// <summary>
/// 使用记录统计快照。
/// </summary>
public sealed record PunchCardUsageStatsSnapshot
{
    /// <summary>
    /// 今日使用次数。
    /// </summary>
    public int TodayUsedCount { get; init; }

    /// <summary>
    /// 本月使用次数。
    /// </summary>
    public int MonthUsedCount { get; init; }

    /// <summary>
    /// 7 天内即将过期数量。
    /// </summary>
    public int ExpiringSoonCount { get; init; }
}
