using MediatR;
using TakeoutSaaS.Application.App.Billings.Commands;
using TakeoutSaaS.Domain.Tenants.Repositories;
using TakeoutSaaS.Shared.Abstractions.Constants;
using TakeoutSaaS.Shared.Abstractions.Exceptions;
using TakeoutSaaS.Shared.Abstractions.Tenancy;

namespace TakeoutSaaS.Application.App.Billings.Handlers;

/// <summary>
/// 批量更新账单状态处理器。
/// </summary>
public sealed class BatchUpdateStatusCommandHandler(
    ITenantBillingRepository billingRepository,
    ITenantContextAccessor tenantContextAccessor)
    : IRequestHandler<BatchUpdateStatusCommand, int>
{
    /// <summary>
    /// 处理批量更新账单状态请求。
    /// </summary>
    /// <param name="request">批量更新状态命令。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>成功更新的账单数量。</returns>
    public async Task<int> Handle(BatchUpdateStatusCommand request, CancellationToken cancellationToken)
    {
        // 1. 参数验证
        if (request.BillingIds.Length == 0)
        {
            throw new BusinessException(ErrorCodes.BadRequest, "账单 ID 列表不能为空");
        }

        // 2. 查询所有账单
        var billings = await billingRepository.GetByIdsAsync(request.BillingIds, cancellationToken);
        if (billings.Count == 0)
        {
            throw new BusinessException(ErrorCodes.NotFound, "未找到任何匹配的账单");
        }

        // 3. 批量更新状态（逐租户上下文执行，避免跨租户写入）
        var now = DateTime.UtcNow;
        var currentTenantId = tenantContextAccessor.Current?.TenantId ?? 0;
        if (currentTenantId != 0 && billings.Any(x => x.TenantId != currentTenantId))
        {
            throw new BusinessException(ErrorCodes.Forbidden, "禁止跨租户批量更新账单状态");
        }

        var updatedTotal = 0;
        var grouped = billings.GroupBy(x => x.TenantId).ToList();
        foreach (var group in grouped)
        {
            using (currentTenantId == 0 ? tenantContextAccessor.EnterTenantScope(group.Key, "billing:batch-update") : null)
            {
                var updatedCount = 0;
                foreach (var billing in group)
                {
                    // 业务规则检查：某些状态转换可能不允许
                    if (!CanTransitionStatus(billing.Status, request.NewStatus))
                    {
                        continue;
                    }

                    billing.Status = request.NewStatus;
                    billing.UpdatedAt = now;

                    if (!string.IsNullOrWhiteSpace(request.Notes))
                    {
                        billing.Notes = string.IsNullOrWhiteSpace(billing.Notes)
                            ? $"[批量操作] {request.Notes}"
                            : $"{billing.Notes}\n[批量操作] {request.Notes}";
                    }

                    await billingRepository.UpdateAsync(billing, cancellationToken);
                    updatedCount++;
                }

                if (updatedCount > 0)
                {
                    await billingRepository.SaveChangesAsync(cancellationToken);
                }

                updatedTotal += updatedCount;
            }
        }

        return updatedTotal;
    }

    /// <summary>
    /// 检查状态转换是否允许。
    /// </summary>
    private static bool CanTransitionStatus(
        TakeoutSaaS.Domain.Tenants.Enums.TenantBillingStatus currentStatus,
        TakeoutSaaS.Domain.Tenants.Enums.TenantBillingStatus newStatus)
    {
        // 已支付的账单不能改为其他状态
        if (currentStatus == TakeoutSaaS.Domain.Tenants.Enums.TenantBillingStatus.Paid
            && newStatus != TakeoutSaaS.Domain.Tenants.Enums.TenantBillingStatus.Paid)
        {
            return false;
        }

        // 已取消的账单不能改为其他状态
        if (currentStatus == TakeoutSaaS.Domain.Tenants.Enums.TenantBillingStatus.Cancelled)
        {
            return false;
        }

        return true;
    }
}
