using MediatR;
using Microsoft.Extensions.Logging;
using TakeoutSaaS.Application.App.Tenants.Commands;
using TakeoutSaaS.Domain.Tenants.Enums;
using TakeoutSaaS.Domain.Tenants.Repositories;
using TakeoutSaaS.Shared.Abstractions.Constants;
using TakeoutSaaS.Shared.Abstractions.Exceptions;
using TakeoutSaaS.Shared.Abstractions.Security;

namespace TakeoutSaaS.Application.App.Tenants.Handlers;

/// <summary>
/// 审核驳回租户命令处理器。
/// </summary>
public sealed class RejectTenantCommandHandler(
    ITenantRepository tenantRepository,
    ICurrentUserAccessor currentUserAccessor,
    ILogger<RejectTenantCommandHandler> logger)
    : IRequestHandler<RejectTenantCommand>
{
    /// <inheritdoc />
    public async Task Handle(RejectTenantCommand request, CancellationToken cancellationToken)
    {
        // 1. 解析租户 ID
        if (!long.TryParse(request.TenantId, out var tenantId) || tenantId <= 0)
        {
            throw new BusinessException(ErrorCodes.BadRequest, "租户 ID 无效");
        }

        // 2. 校验驳回原因
        var rejectReason = request.RejectReason?.Trim();
        if (string.IsNullOrWhiteSpace(rejectReason))
        {
            throw new BusinessException(ErrorCodes.BadRequest, "驳回原因不能为空");
        }

        // 3. 获取租户（带跟踪）
        var tenant = await tenantRepository.GetByIdForUpdateAsync(tenantId, cancellationToken);
        if (tenant is null)
        {
            throw new BusinessException(ErrorCodes.NotFound, "租户不存在");
        }

        // 4. 校验租户状态（只有待审核状态才能驳回）
        if (tenant.Status != TenantStatus.PendingReview)
        {
            throw new BusinessException(ErrorCodes.BadRequest, $"租户当前状态为 {tenant.Status}，无法驳回");
        }

        // 5. 获取认证资料（带跟踪）
        var verification = await tenantRepository.GetVerificationForUpdateAsync(tenantId, cancellationToken);
        if (verification is null)
        {
            throw new BusinessException(ErrorCodes.NotFound, "租户认证资料不存在");
        }

        // 6. 更新认证资料状态（租户状态保持 PendingReview，等待重新提交）
        verification.Status = TenantVerificationStatus.Rejected;
        verification.ReviewedAt = DateTime.UtcNow;
        verification.ReviewedBy = currentUserAccessor.UserId;
        verification.ReviewedByName = request.ReviewedByName?.Trim();
        verification.ReviewRemarks = rejectReason;

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

        logger.LogInformation(
            "租户 {TenantId} 审核驳回，驳回原因：{RejectReason}，审核人：{ReviewedBy}",
            tenantId,
            rejectReason,
            currentUserAccessor.UserId);
    }
}
