using MediatR;
using Microsoft.Extensions.Logging;
using TakeoutSaaS.Application.App.Tenants.Commands;
using TakeoutSaaS.Application.App.Tenants.Contracts;
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 ClaimTenantReviewCommandHandler(
    ITenantRepository tenantRepository,
    ICurrentUserAccessor currentUserAccessor,
    IIdGenerator idGenerator,
    ILogger<ClaimTenantReviewCommandHandler> logger)
    : IRequestHandler<ClaimTenantReviewCommand, TenantReviewClaimDto>
{
    /// <inheritdoc />
    public async Task<TenantReviewClaimDto> Handle(ClaimTenantReviewCommand request, CancellationToken cancellationToken)
    {
        // 1. 校验租户是否存在
        var tenant = await tenantRepository.FindByIdAsync(request.TenantId, cancellationToken);
        if (tenant is null)
        {
            throw new BusinessException(ErrorCodes.NotFound, "租户不存在");
        }

        // 2. 校验租户状态（只有待审核状态才能领取）
        if (tenant.Status != TenantStatus.PendingReview)
        {
            throw new BusinessException(ErrorCodes.BadRequest, "租户不在待审核状态，无法领取审核");
        }

        // 3. 检查是否已被领取
        var existingClaim = await tenantRepository.GetActiveReviewClaimAsync(request.TenantId, cancellationToken);
        if (existingClaim is not null)
        {
            // 4. 如果是自己领取的，直接返回
            if (existingClaim.ClaimedBy == currentUserAccessor.UserId)
            {
                return ToDto(existingClaim);
            }

            // 5. 已被他人领取
            throw new BusinessException(ErrorCodes.Conflict, $"该审核已被 {existingClaim.ClaimedByName} 领取");
        }

        // 6. 创建新的领取记录
        var now = DateTime.UtcNow;
        var actorName = currentUserAccessor.IsAuthenticated
            ? $"user:{currentUserAccessor.UserId}"
            : "system";

        var claim = new TenantReviewClaim
        {
            Id = idGenerator.NextId(),
            TenantId = request.TenantId,
            ClaimedBy = currentUserAccessor.UserId,
            ClaimedByName = actorName,
            ClaimedAt = now
        };

        // 7. 保存领取记录
        await tenantRepository.AddReviewClaimAsync(claim, cancellationToken);

        // 8. 添加审核日志
        await tenantRepository.AddAuditLogAsync(new TenantAuditLog
        {
            Id = idGenerator.NextId(),
            TenantId = request.TenantId,
            Action = TenantAuditAction.ReviewClaimed,
            Title = "领取审核",
            Description = $"领取人：{actorName}",
            OperatorId = currentUserAccessor.UserId,
            OperatorName = actorName,
            CurrentStatus = tenant.Status
        }, cancellationToken);

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

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

        return ToDto(claim);
    }

    private static TenantReviewClaimDto ToDto(TenantReviewClaim claim)
        => new()
        {
            Id = claim.Id,
            TenantId = claim.TenantId,
            ClaimedBy = claim.ClaimedBy,
            ClaimedByName = claim.ClaimedByName,
            ClaimedAt = claim.ClaimedAt
        };
}
