using TakeoutSaaS.Domain.Billings.Entities;
using TakeoutSaaS.Domain.Billings.Enums;

namespace TakeoutSaaS.Domain.Billings.Repositories;

/// <summary>
/// 账单仓储（AdminApi 使用）。
/// </summary>
public interface IBillingRepository
{
    /// <summary>
    /// 获取账单列表（分页）。
    /// </summary>
    /// <param name="tenantId">租户 ID。</param>
    /// <param name="status">账单状态。</param>
    /// <param name="billingType">账单类型。</param>
    /// <param name="startDate">开始日期。</param>
    /// <param name="endDate">结束日期。</param>
    /// <param name="minAmount">最小金额。</param>
    /// <param name="maxAmount">最大金额。</param>
    /// <param name="keyword">关键词（账单号、租户名）。</param>
    /// <param name="sortBy">排序字段。</param>
    /// <param name="sortDesc">是否降序。</param>
    /// <param name="page">页码（从 1 开始）。</param>
    /// <param name="pageSize">每页条数。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>账单列表和总数。</returns>
    Task<(IReadOnlyList<BillingListResult> Items, int TotalCount)> GetListAsync(
        long? tenantId,
        TenantBillingStatus? status,
        TenantBillingType? billingType,
        DateTime? startDate,
        DateTime? endDate,
        decimal? minAmount,
        decimal? maxAmount,
        string? keyword,
        string? sortBy,
        bool? sortDesc,
        int page,
        int pageSize,
        CancellationToken cancellationToken = default);

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

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

    /// <summary>
    /// 获取账单详情（带租户信息）。
    /// </summary>
    /// <param name="billingId">账单 ID。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>账单详情结果，不存在则返回 null。</returns>
    Task<BillingDetailResult?> GetDetailAsync(long billingId, CancellationToken cancellationToken = default);

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

    /// <summary>
    /// 添加支付记录。
    /// </summary>
    /// <param name="payment">支付记录实体。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>异步操作任务。</returns>
    Task AddPaymentAsync(TenantPayment payment, CancellationToken cancellationToken = default);

    /// <summary>
    /// 获取账单的支付记录列表。
    /// </summary>
    /// <param name="billingStatementId">账单 ID。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>支付记录列表。</returns>
    Task<IReadOnlyList<TenantPayment>> GetPaymentsByBillingIdAsync(long billingStatementId, CancellationToken cancellationToken = default);
}

/// <summary>
/// 账单列表结果。
/// </summary>
public sealed record BillingListResult(
    long Id,
    long TenantId,
    string? TenantName,
    string StatementNo,
    TenantBillingType BillingType,
    DateTime PeriodStart,
    DateTime PeriodEnd,
    decimal AmountDue,
    decimal AmountPaid,
    decimal DiscountAmount,
    decimal TaxAmount,
    string Currency,
    TenantBillingStatus Status,
    DateTime DueDate,
    DateTime? OverdueNotifiedAt,
    DateTime CreatedAt,
    DateTime? UpdatedAt);

/// <summary>
/// 账单详情结果。
/// </summary>
public sealed record BillingDetailResult(
    long Id,
    long TenantId,
    string? TenantName,
    string StatementNo,
    TenantBillingType BillingType,
    DateTime PeriodStart,
    DateTime PeriodEnd,
    decimal AmountDue,
    decimal AmountPaid,
    decimal DiscountAmount,
    decimal TaxAmount,
    string Currency,
    TenantBillingStatus Status,
    DateTime DueDate,
    string? LineItemsJson,
    string? Notes,
    DateTime? OverdueNotifiedAt,
    DateTime? ReminderSentAt,
    DateTime CreatedAt,
    DateTime? UpdatedAt);
