using Microsoft.EntityFrameworkCore;
using TakeoutSaaS.Domain.Tenants.Entities;
using TakeoutSaaS.Domain.Tenants.Enums;
using TakeoutSaaS.Domain.Tenants.Repositories;
using TakeoutSaaS.Infrastructure.App.Persistence;

namespace TakeoutSaaS.Infrastructure.App.Persistence.Repositories;

/// <summary>
/// 租户支付记录仓储实现（EF Core）。
/// </summary>
public sealed class TenantPaymentRepository(TakeoutAppDbContext context) : ITenantPaymentRepository
{
    /// <inheritdoc />
    public async Task<(IReadOnlyList<TenantPayment> Items, int Total)> SearchPagedAsync(
        long tenantId,
        DateTime from,
        DateTime to,
        int page,
        int pageSize,
        CancellationToken cancellationToken = default)
    {
        // 1. 归一化分页参数
        var normalizedPage = page <= 0 ? 1 : page;
        var normalizedPageSize = pageSize <= 0 ? 20 : pageSize;

        // 2. 构建查询（按支付时间倒序）
        var query = context.TenantPayments
            .AsNoTracking()
            .Where(x => x.DeletedAt == null
                        && x.TenantId == tenantId
                        && (x.PaidAt ?? x.CreatedAt) >= from
                        && (x.PaidAt ?? x.CreatedAt) <= to);

        // 3. 执行分页
        var total = await query.CountAsync(cancellationToken);
        var items = await query
            .OrderByDescending(x => x.PaidAt ?? x.CreatedAt)
            .Skip((normalizedPage - 1) * normalizedPageSize)
            .Take(normalizedPageSize)
            .ToListAsync(cancellationToken);

        // 4. 返回分页结果
        return (items, total);
    }

    /// <inheritdoc />
    public async Task<IReadOnlyList<TenantPayment>> GetByBillingIdAsync(long billingStatementId, CancellationToken cancellationToken = default)
    {
        return await context.TenantPayments
            .AsNoTracking()
            .Where(x => x.DeletedAt == null && x.BillingStatementId == billingStatementId)
            .OrderByDescending(x => x.CreatedAt)
            .ToListAsync(cancellationToken);
    }

    /// <inheritdoc />
    public async Task<decimal> GetTotalPaidAmountAsync(long billingStatementId, CancellationToken cancellationToken = default)
    {
        // 1. 仅统计支付成功的记录
        return await context.TenantPayments
            .AsNoTracking()
            .Where(x => x.DeletedAt == null
                        && x.BillingStatementId == billingStatementId
                        && x.Status == TenantPaymentStatus.Success)
            .SumAsync(x => x.Amount, cancellationToken);
    }

    /// <inheritdoc />
    public Task<TenantPayment?> FindByIdAsync(long paymentId, CancellationToken cancellationToken = default)
    {
        return context.TenantPayments
            .AsNoTracking()
            .FirstOrDefaultAsync(x => x.DeletedAt == null && x.Id == paymentId, cancellationToken);
    }

    /// <inheritdoc />
    public Task<TenantPayment?> GetByTransactionNoAsync(string transactionNo, CancellationToken cancellationToken = default)
    {
        var normalized = transactionNo.Trim();

        return context.TenantPayments
            .AsNoTracking()
            .FirstOrDefaultAsync(x => x.DeletedAt == null && x.TransactionNo == normalized, cancellationToken);
    }

    /// <inheritdoc />
    public Task AddAsync(TenantPayment payment, CancellationToken cancellationToken = default)
    {
        return context.TenantPayments.AddAsync(payment, cancellationToken).AsTask();
    }

    /// <inheritdoc />
    public Task UpdateAsync(TenantPayment payment, CancellationToken cancellationToken = default)
    {
        context.TenantPayments.Update(payment);
        return Task.CompletedTask;
    }

    /// <inheritdoc />
    public Task SaveChangesAsync(CancellationToken cancellationToken = default)
    {
        return context.SaveChangesAsync(cancellationToken);
    }
}
