using MediatR;
using TakeoutSaaS.Application.App.Subscriptions.Contracts;
using TakeoutSaaS.Application.App.Subscriptions.Queries;
using TakeoutSaaS.Application.App.TenantPackages.Contracts;
using TakeoutSaaS.Domain.Tenants.Enums;
using TakeoutSaaS.Domain.Tenants.Repositories;

namespace TakeoutSaaS.Application.App.Subscriptions.Handlers;

/// <summary>
/// 获取订阅详情查询处理器。
/// </summary>
public sealed class GetSubscriptionDetailQueryHandler(
    ISubscriptionRepository subscriptionRepository,
    ITenantRepository tenantRepository)
    : IRequestHandler<GetSubscriptionDetailQuery, SubscriptionDetailDto?>
{
    /// <inheritdoc />
    public async Task<SubscriptionDetailDto?> Handle(
        GetSubscriptionDetailQuery request,
        CancellationToken cancellationToken)
    {
        // 1. 查询订阅详情
        var detail = await subscriptionRepository.GetDetailAsync(request.SubscriptionId, cancellationToken);

        // 2. 如果不存在，返回 null
        if (detail is null)
        {
            return null;
        }

        // 3. 查询变更历史
        var histories = await subscriptionRepository.GetHistoriesAsync(request.SubscriptionId, cancellationToken);

        // 4. 查询配额使用情况
        var quotaUsages = await tenantRepository.GetQuotaUsagesAsync(detail.TenantId, cancellationToken);

        // 5. 映射套餐信息
        var packageDto = MapToPackageDto(detail.Package);
        var scheduledPackageDto = detail.ScheduledPackage is not null
            ? MapToPackageDto(detail.ScheduledPackage)
            : null;

        // 6. 映射配额使用情况
        var quotaUsageDtos = quotaUsages.Select(u =>
        {
            var limit = (int?)u.LimitValue;
            var used = (int)u.UsedValue;
            var remaining = limit.HasValue ? Math.Max(0, limit.Value - used) : (int?)null;
            var usagePercentage = limit.HasValue && limit.Value > 0
                ? Math.Round((decimal)used / limit.Value * 100, 2)
                : (decimal?)null;

            return new SubscriptionQuotaUsageDto
            {
                QuotaType = u.QuotaType,
                QuotaName = GetQuotaTypeName(u.QuotaType),
                Limit = limit,
                Used = used,
                Remaining = remaining,
                UsagePercentage = usagePercentage
            };
        }).ToList();

        // 7. 映射变更历史
        var historyDtos = histories.Select(h => new SubscriptionHistoryDto
        {
            Id = h.Id,
            SubscriptionId = h.SubscriptionId,
            ChangeType = h.ChangeType.ToString(),
            PreviousPackageId = h.FromPackageId,
            PreviousPackageName = h.FromPackageName,
            NewPackageId = h.ToPackageId,
            NewPackageName = h.ToPackageName,
            PreviousEffectiveTo = h.EffectiveFrom,
            NewEffectiveTo = h.EffectiveTo,
            Notes = h.Notes,
            CreatedAt = h.CreatedAt,
            CreatedBy = h.CreatedBy?.ToString()
        }).ToList();

        // 8. 返回订阅详情 DTO
        return new SubscriptionDetailDto
        {
            Id = detail.Id,
            TenantId = detail.TenantId,
            TenantName = detail.TenantName,
            TenantCode = detail.TenantCode,
            TenantPackageId = detail.TenantPackageId,
            PackageName = detail.PackageName,
            ScheduledPackageId = detail.ScheduledPackageId,
            ScheduledPackageName = detail.ScheduledPackageName,
            Status = detail.Status,
            EffectiveFrom = detail.EffectiveFrom,
            EffectiveTo = detail.EffectiveTo,
            NextBillingDate = detail.NextBillingDate,
            AutoRenew = detail.AutoRenew,
            Notes = detail.Notes,
            CreatedAt = detail.CreatedAt,
            UpdatedAt = detail.UpdatedAt,
            Package = packageDto,
            ScheduledPackage = scheduledPackageDto,
            QuotaUsages = quotaUsageDtos,
            ChangeHistory = historyDtos
        };
    }

    /// <summary>
    /// 映射套餐实体为 DTO。
    /// </summary>
    private static TenantPackageListDto MapToPackageDto(TakeoutSaaS.Domain.Tenants.Entities.TenantPackage package)
    {
        return new TenantPackageListDto
        {
            Id = package.Id,
            Name = package.Name,
            Description = package.Description,
            PackageType = package.PackageType,
            MonthlyPrice = package.MonthlyPrice,
            YearlyPrice = package.YearlyPrice,
            MaxStoreCount = package.MaxStoreCount,
            MaxAccountCount = package.MaxAccountCount,
            MaxStorageGb = package.MaxStorageGb,
            MaxSmsCredits = package.MaxSmsCredits,
            MaxDeliveryOrders = package.MaxDeliveryOrders,
            FeaturePoliciesJson = package.FeaturePoliciesJson,
            IsActive = package.IsActive,
            IsPublicVisible = package.IsPublicVisible,
            IsAllowNewTenantPurchase = package.IsAllowNewTenantPurchase,
            PublishStatus = package.PublishStatus,
            IsRecommended = package.IsRecommended,
            Tags = package.Tags ?? [],
            SortOrder = package.SortOrder
        };
    }

    /// <summary>
    /// 获取配额类型名称。
    /// </summary>
    private static string GetQuotaTypeName(TenantQuotaType quotaType)
    {
        return quotaType switch
        {
            TenantQuotaType.Store => "门店数量",
            TenantQuotaType.Account => "账号数量",
            TenantQuotaType.StorageGb => "存储空间(GB)",
            TenantQuotaType.SmsCredits => "短信额度",
            TenantQuotaType.DeliveryOrders => "配送订单数",
            _ => quotaType.ToString()
        };
    }
}
