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

namespace TakeoutSaaS.Application.App.Tenants.Handlers;

/// <summary>
/// 释放租户审核领取命令处理器。
/// </summary>
public sealed class ReleaseTenantReviewClaimCommandHandler(
    ITenantRepository tenantRepository,
    ICurrentUserAccessor currentUserAccessor,
    IIdGenerator idGenerator,
    ILogger<ReleaseTenantReviewClaimCommandHandler> logger)
    : IRequestHandler<ReleaseTenantReviewClaimCommand>
{
    /// <inheritdoc />
    public async Task Handle(ReleaseTenantReviewClaimCommand request, CancellationToken cancellationToken)
    {
        // 1. 校验租户是否存在
        var tenant = await tenantRepository.FindByIdAsync(request.TenantId, cancellationToken);
        if (tenant is null)
        {
            throw new BusinessException(ErrorCodes.NotFound, "租户不存在");
        }

        // 2. 检查是否有领取记录
        var existingClaim = await tenantRepository.GetActiveReviewClaimAsync(request.TenantId, cancellationToken);
        if (existingClaim is null)
        {
            throw new BusinessException(ErrorCodes.BadRequest, "该租户审核未被领取");
        }

        // 3. 校验是否是自己领取的
        if (existingClaim.ClaimedBy != currentUserAccessor.UserId)
        {
            throw new BusinessException(ErrorCodes.Forbidden, "只能释放自己领取的审核");
        }

        // 4. 释放领取
        existingClaim.ReleasedAt = DateTime.UtcNow;

        // 5. 添加审核日志
        var actorName = currentUserAccessor.IsAuthenticated
            ? $"user:{currentUserAccessor.UserId}"
            : "system";

        await tenantRepository.AddAuditLogAsync(new TenantAuditLog
        {
            Id = idGenerator.NextId(),
            TenantId = request.TenantId,
            Action = TenantAuditAction.ReviewReleased,
            Title = "释放审核",
            Description = $"释放人：{actorName}",
            OperatorId = currentUserAccessor.UserId,
            OperatorName = actorName,
            CurrentStatus = tenant.Status
        }, cancellationToken);

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

        logger.LogInformation("租户 {TenantId} 审核已被 {UserId} 释放", request.TenantId, currentUserAccessor.UserId);
    }
}
