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

namespace TakeoutSaaS.Infrastructure.App.Repositories;

/// <summary>
/// 租户仓储实现（AdminApi 使用）。
/// </summary>
public sealed class EfTenantRepository(TakeoutAdminDbContext context) : ITenantRepository
{
    /// <inheritdoc />
    public Task<Tenant?> FindByIdAsync(long tenantId, CancellationToken cancellationToken = default)
    {
        // 1. 只读查询租户（跨租户）
        return context.Tenants
            .AsNoTracking()
            .FirstOrDefaultAsync(x => x.Id == tenantId, cancellationToken);
    }

    /// <inheritdoc />
    public async Task<IReadOnlyList<Tenant>> FindByIdsAsync(IReadOnlyCollection<long> tenantIds, CancellationToken cancellationToken = default)
    {
        // 1. tenantIds 为空直接返回
        if (tenantIds.Count == 0)
        {
            return Array.Empty<Tenant>();
        }

        // 2. (空行后) 批量查询租户
        return await context.Tenants
            .AsNoTracking()
            .Where(x => tenantIds.Contains(x.Id))
            .ToListAsync(cancellationToken);
    }

    /// <inheritdoc />
    public async Task<bool> ExistsByCodeAsync(string code, long? excludeTenantId = null, CancellationToken cancellationToken = default)
    {
        // 1. 构建查询
        var query = context.Tenants
            .AsNoTracking()
            .Where(x => x.Code == code && x.DeletedAt == null);

        // 2. 排除指定租户
        if (excludeTenantId.HasValue)
        {
            query = query.Where(x => x.Id != excludeTenantId.Value);
        }

        // 3. 返回是否存在
        return await query.AnyAsync(cancellationToken);
    }

    /// <inheritdoc />
    public async Task<IReadOnlyList<Tenant>> GetAllAsync(string? keyword, CancellationToken cancellationToken = default)
    {
        // 1. 构建基础查询
        var query = context.Tenants
            .AsNoTracking()
            .Where(x => x.DeletedAt == null);

        // 2. 应用关键字过滤
        if (!string.IsNullOrWhiteSpace(keyword))
        {
            var normalized = keyword.Trim();
            query = query.Where(x => x.Name.Contains(normalized) || x.Code.Contains(normalized));
        }

        // 3. 返回列表
        return await query.OrderBy(x => x.Code).ToListAsync(cancellationToken);
    }

    /// <inheritdoc />
    public async Task<TenantDetailResult?> GetDetailAsync(long tenantId, CancellationToken cancellationToken = default)
    {
        // 1. 查询租户基本信息
        var tenant = await context.Tenants
            .AsNoTracking()
            .FirstOrDefaultAsync(t => t.Id == tenantId, cancellationToken);

        if (tenant is null)
        {
            return null;
        }

        // 2. 查询认证信息（取最新一条）
        var verification = await context.TenantVerificationProfiles
            .AsNoTracking()
            .Where(v => v.TenantId == tenantId)
            .OrderByDescending(v => v.CreatedAt)
            .FirstOrDefaultAsync(cancellationToken);

        // 3. 查询订阅信息（取最新一条，包含套餐）
        var subscription = await context.TenantSubscriptions
            .AsNoTracking()
            .Include(s => s.TenantPackage)
            .Where(s => s.TenantId == tenantId)
            .OrderByDescending(s => s.CreatedAt)
            .FirstOrDefaultAsync(cancellationToken);

        // 4. 返回结果
        return new TenantDetailResult(tenant, verification, subscription, subscription?.TenantPackage);
    }

    /// <inheritdoc />
    public async Task<IReadOnlyList<TenantQuotaUsage>> GetQuotaUsagesAsync(long tenantId, CancellationToken cancellationToken = default)
    {
        // 1. 查询租户配额使用情况
        return await context.TenantQuotaUsages
            .AsNoTracking()
            .Where(q => q.TenantId == tenantId && q.DeletedAt == null)
            .OrderBy(q => q.QuotaType)
            .ToListAsync(cancellationToken);
    }

    /// <inheritdoc />
    public async Task<(IReadOnlyList<TenantBillingStatement> Items, int TotalCount)> GetBillingsAsync(
        long tenantId,
        int page,
        int pageSize,
        CancellationToken cancellationToken = default)
    {
        // 1. 构建基础查询
        var query = context.TenantBillingStatements
            .AsNoTracking()
            .Where(b => b.TenantId == tenantId && b.DeletedAt == null);

        // 2. 获取总数
        var totalCount = await query.CountAsync(cancellationToken);

        // 3. 分页查询（按创建时间倒序）
        var items = await query
            .OrderByDescending(b => b.CreatedAt)
            .Skip((page - 1) * pageSize)
            .Take(pageSize)
            .ToListAsync(cancellationToken);

        // 4. 返回结果
        return (items, totalCount);
    }

    /// <inheritdoc />
    public async Task CreateTenantWithRelatedDataAsync(
        Tenant tenant,
        TenantSubscription subscription,
        TenantVerificationProfile verification,
        IReadOnlyList<TenantQuotaUsage> quotaUsages,
        TenantBillingStatement? billing,
        TenantPayment? payment,
        CancellationToken cancellationToken = default)
    {
        // 1. 使用执行策略保证可靠性
        var strategy = context.Database.CreateExecutionStrategy();
        await strategy.ExecuteAsync(async () =>
        {
            // 2. 开启事务
            await using var transaction = await context.Database.BeginTransactionAsync(cancellationToken);

            // 3. 批量添加实体
            await context.Tenants.AddAsync(tenant, cancellationToken);
            await context.TenantSubscriptions.AddAsync(subscription, cancellationToken);
            await context.TenantVerificationProfiles.AddAsync(verification, cancellationToken);

            // 4. 添加配额使用记录
            if (quotaUsages.Count > 0)
            {
                await context.TenantQuotaUsages.AddRangeAsync(quotaUsages, cancellationToken);
            }

            // 5. 添加账单记录
            if (billing is not null)
            {
                await context.TenantBillingStatements.AddAsync(billing, cancellationToken);
            }

            // 6. 添加支付记录
            if (payment is not null)
            {
                await context.TenantPayments.AddAsync(payment, cancellationToken);
            }

            // 7. 保存变更
            await context.SaveChangesAsync(cancellationToken);

            // 8. 提交事务
            await transaction.CommitAsync(cancellationToken);
        });
    }

    /// <inheritdoc />
    public Task<Tenant?> GetByIdForUpdateAsync(long tenantId, CancellationToken cancellationToken = default)
    {
        // 1. 带跟踪查询租户（用于更新）
        return context.Tenants
            .Where(x => x.Id == tenantId && x.DeletedAt == null)
            .FirstOrDefaultAsync(cancellationToken);
    }

    /// <inheritdoc />
    public Task<TenantVerificationProfile?> GetVerificationForUpdateAsync(long tenantId, CancellationToken cancellationToken = default)
    {
        // 1. 带跟踪查询认证资料（取最新一条，用于更新）
        return context.TenantVerificationProfiles
            .Where(v => v.TenantId == tenantId && v.DeletedAt == null)
            .OrderByDescending(v => v.CreatedAt)
            .FirstOrDefaultAsync(cancellationToken);
    }

    /// <inheritdoc />
    public async Task AddAsync(Tenant tenant, CancellationToken cancellationToken = default)
    {
        // 1. 新增租户
        await context.Tenants.AddAsync(tenant, cancellationToken);
    }

    /// <inheritdoc />
    public async Task AddSubscriptionAsync(TenantSubscription subscription, CancellationToken cancellationToken = default)
    {
        // 1. 新增订阅
        await context.TenantSubscriptions.AddAsync(subscription, cancellationToken);
    }

    /// <inheritdoc />
    public async Task AddVerificationAsync(TenantVerificationProfile verification, CancellationToken cancellationToken = default)
    {
        // 1. 新增认证资料
        await context.TenantVerificationProfiles.AddAsync(verification, cancellationToken);
    }

    /// <inheritdoc />
    public Task SaveChangesAsync(CancellationToken cancellationToken = default)
    {
        // 1. 保存变更
        return context.SaveChangesAsync(cancellationToken);
    }

    /// <inheritdoc />
    public Task<TenantReviewClaim?> GetActiveReviewClaimAsync(long tenantId, CancellationToken cancellationToken = default)
    {
        // 1. 查询当前有效的审核领取记录（未释放的）
        return context.TenantReviewClaims
            .Where(c => c.TenantId == tenantId && c.ReleasedAt == null && c.DeletedAt == null)
            .OrderByDescending(c => c.ClaimedAt)
            .FirstOrDefaultAsync(cancellationToken);
    }

    /// <inheritdoc />
    public async Task AddReviewClaimAsync(TenantReviewClaim claim, CancellationToken cancellationToken = default)
    {
        // 1. 新增审核领取记录
        await context.TenantReviewClaims.AddAsync(claim, cancellationToken);
    }

    /// <inheritdoc />
    public async Task AddAuditLogAsync(TenantAuditLog auditLog, CancellationToken cancellationToken = default)
    {
        // 1. 新增审核日志
        await context.TenantAuditLogs.AddAsync(auditLog, cancellationToken);
    }

    /// <inheritdoc />
    public async Task<(IReadOnlyList<TenantAuditLog> Items, int TotalCount)> GetAuditLogsAsync(
        long tenantId,
        int page,
        int pageSize,
        CancellationToken cancellationToken = default)
    {
        // 1. 构建基础查询
        var query = context.TenantAuditLogs
            .AsNoTracking()
            .Where(a => a.TenantId == tenantId && a.DeletedAt == null);

        // 2. 获取总数
        var totalCount = await query.CountAsync(cancellationToken);

        // 3. 分页查询（按创建时间倒序）
        var items = await query
            .OrderByDescending(a => a.CreatedAt)
            .Skip((page - 1) * pageSize)
            .Take(pageSize)
            .ToListAsync(cancellationToken);

        // 4. 返回结果
        return (items, totalCount);
    }
}
