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.Repositories;

/// <summary>
/// 租户套餐仓储实现（AdminApi 使用）。
/// </summary>
public sealed class EfTenantPackageRepository(TakeoutAdminDbContext context) : ITenantPackageRepository
{
    /// <inheritdoc />
    public async Task<TenantPackage?> GetByIdAsync(long tenantPackageId, CancellationToken cancellationToken = default)
    {
        // 1. 查询套餐（排除已删除，无跟踪）
        return await context.TenantPackages
            .AsNoTracking()
            .Where(p => p.Id == tenantPackageId && p.DeletedAt == null)
            .FirstOrDefaultAsync(cancellationToken);
    }

    /// <inheritdoc />
    public async Task<TenantPackage?> GetByIdForUpdateAsync(long tenantPackageId, CancellationToken cancellationToken = default)
    {
        // 1. 查询套餐（排除已删除，带跟踪用于更新）
        return await context.TenantPackages
            .Where(p => p.Id == tenantPackageId && p.DeletedAt == null)
            .FirstOrDefaultAsync(cancellationToken);
    }

    /// <inheritdoc />
    public async Task<(IReadOnlyList<TenantPackage> Items, int TotalCount)> GetListAsync(
        string? keyword,
        bool? isActive,
        int page,
        int pageSize,
        CancellationToken cancellationToken = default)
    {
        // 1. 构建基础查询
        var query = context.TenantPackages
            .AsNoTracking()
            .Where(p => p.DeletedAt == null);

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

        // 3. 应用启用状态过滤
        if (isActive.HasValue)
        {
            query = query.Where(p => p.IsActive == isActive.Value);
        }

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

        // 5. 分页查询（按排序序号升序）
        var items = await query
            .OrderBy(p => p.SortOrder)
            .ThenBy(p => p.Id)
            .Skip((page - 1) * pageSize)
            .Take(pageSize)
            .ToListAsync(cancellationToken);

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

    /// <inheritdoc />
    public async Task<IReadOnlyList<TenantPackageUsageResult>> GetUsagesAsync(
        IReadOnlyList<long> tenantPackageIds,
        CancellationToken cancellationToken = default)
    {
        // 1. 如果没有传入套餐 ID，返回空列表
        if (tenantPackageIds.Count == 0)
        {
            return [];
        }

        // 2. 获取当前时间用于计算到期天数
        var now = DateTime.UtcNow;
        var in7Days = now.AddDays(7);
        var in15Days = now.AddDays(15);
        var in30Days = now.AddDays(30);

        // 3. 查询订阅数据并按套餐分组统计
        var subscriptions = await context.TenantSubscriptions
            .AsNoTracking()
            .Where(s => tenantPackageIds.Contains(s.TenantPackageId) && s.DeletedAt == null)
            .Select(s => new
            {
                s.TenantPackageId,
                s.TenantId,
                s.Status,
                s.EffectiveTo,
                MonthlyPrice = context.TenantPackages
                    .Where(p => p.Id == s.TenantPackageId)
                    .Select(p => p.MonthlyPrice)
                    .FirstOrDefault()
            })
            .ToListAsync(cancellationToken);

        // 4. 按套餐 ID 分组统计
        var results = tenantPackageIds.Select(packageId =>
        {
            var packageSubscriptions = subscriptions.Where(s => s.TenantPackageId == packageId).ToList();

            // 4.1 活跃订阅（状态为 Active 且未过期）
            var activeSubscriptions = packageSubscriptions
                .Where(s => s.Status == SubscriptionStatus.Active && s.EffectiveTo > now)
                .ToList();

            // 4.2 活跃租户数（去重）
            var activeTenantCount = activeSubscriptions.Select(s => s.TenantId).Distinct().Count();

            // 4.3 总订阅数
            var totalSubscriptionCount = packageSubscriptions.Count;

            // 4.4 计算 MRR（月度经常性收入）
            var mrr = activeSubscriptions.Sum(s => s.MonthlyPrice ?? 0);

            // 4.5 计算 ARR（年度经常性收入）
            var arr = mrr * 12;

            // 4.6 计算到期租户数（基于活跃订阅）
            var expiringIn7Days = activeSubscriptions.Count(s => s.EffectiveTo <= in7Days);
            var expiringIn15Days = activeSubscriptions.Count(s => s.EffectiveTo <= in15Days);
            var expiringIn30Days = activeSubscriptions.Count(s => s.EffectiveTo <= in30Days);

            return new TenantPackageUsageResult(
                packageId,
                activeSubscriptions.Count,
                activeTenantCount,
                totalSubscriptionCount,
                mrr,
                arr,
                expiringIn7Days,
                expiringIn15Days,
                expiringIn30Days);
        }).ToList();

        // 5. 返回结果
        return results;
    }

    /// <inheritdoc />
    public async Task AddAsync(TenantPackage package, CancellationToken cancellationToken = default)
    {
        // 1. 添加套餐实体
        await context.TenantPackages.AddAsync(package, cancellationToken);
    }

    /// <inheritdoc />
    public Task SoftDeleteAsync(TenantPackage package, CancellationToken cancellationToken = default)
    {
        // 1. 设置软删除时间
        package.DeletedAt = DateTime.UtcNow;

        // 2. 返回已完成任务
        return Task.CompletedTask;
    }

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

    /// <inheritdoc />
    public async Task<(IReadOnlyList<TenantPackageTenantResult> Items, int TotalCount)> GetTenantsAsync(
        long tenantPackageId,
        string? keyword,
        int? expiringWithinDays,
        int page,
        int pageSize,
        CancellationToken cancellationToken = default)
    {
        // 1. 获取当前时间
        var now = DateTime.UtcNow;

        // 2. 构建基础查询：活跃订阅（状态为 Active 且未过期）
        var query = from s in context.TenantSubscriptions.AsNoTracking()
                    join t in context.Tenants.AsNoTracking() on s.TenantId equals t.Id
                    where s.TenantPackageId == tenantPackageId
                          && s.DeletedAt == null
                          && t.DeletedAt == null
                          && s.Status == SubscriptionStatus.Active
                          && s.EffectiveTo > now
                    select new { Subscription = s, Tenant = t };

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

        // 4. 应用到期天数筛选
        if (expiringWithinDays.HasValue)
        {
            var expiryDate = now.AddDays(expiringWithinDays.Value);
            query = query.Where(x => x.Subscription.EffectiveTo <= expiryDate);
        }

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

        // 6. 分页查询（按到期时间升序，即将到期的排前面）
        var items = await query
            .OrderBy(x => x.Subscription.EffectiveTo)
            .ThenBy(x => x.Tenant.Id)
            .Skip((page - 1) * pageSize)
            .Take(pageSize)
            .Select(x => new TenantPackageTenantResult(
                x.Tenant.Id,
                x.Tenant.Code,
                x.Tenant.Name,
                x.Tenant.Status,
                x.Tenant.ContactName,
                x.Tenant.ContactPhone,
                x.Subscription.EffectiveFrom,
                x.Subscription.EffectiveTo))
            .ToListAsync(cancellationToken);

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