using MediatR;
using TakeoutSaaS.Application.App.Tenants.Commands;
using TakeoutSaaS.Application.App.Tenants.Dto;
using TakeoutSaaS.Application.Identity.Abstractions;
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.Security;

namespace TakeoutSaaS.Application.App.Tenants.Handlers;

/// <summary>
/// 领取租户入驻审核处理器。
/// </summary>
public sealed class ClaimTenantReviewCommandHandler(
    ITenantRepository tenantRepository,
    ICurrentUserAccessor currentUserAccessor,
    IAdminAuthService adminAuthService)
    : IRequestHandler<ClaimTenantReviewCommand, TenantReviewClaimDto>
{
    /// <inheritdoc />
    public async Task<TenantReviewClaimDto> Handle(ClaimTenantReviewCommand request, CancellationToken cancellationToken)
    {
        // 1. 校验租户存在
        var tenant = await tenantRepository.FindByIdAsync(request.TenantId, cancellationToken)
            ?? throw new BusinessException(ErrorCodes.NotFound, "租户不存在");

        // 2. 查询是否已领取
        var existingClaim = await tenantRepository.GetActiveReviewClaimAsync(request.TenantId, cancellationToken);
        if (existingClaim != null)
        {
            if (existingClaim.ClaimedBy == currentUserAccessor.UserId)
            {
                return existingClaim.ToDto();
            }

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

        // 3. (空行后) 获取当前用户显示名（用于展示快照）
        var profile = await adminAuthService.GetProfileAsync(currentUserAccessor.UserId, cancellationToken);
        var displayName = string.IsNullOrWhiteSpace(profile.DisplayName)
            ? $"user:{currentUserAccessor.UserId}"
            : profile.DisplayName;

        // 4. (空行后) 构造领取记录与审计日志
        var now = DateTime.UtcNow;
        var claim = new TenantReviewClaim
        {
            TenantId = request.TenantId,
            ClaimedBy = currentUserAccessor.UserId,
            ClaimedByName = displayName,
            ClaimedAt = now,
            ReleasedAt = null
        };

        var auditLog = new TenantAuditLog
        {
            TenantId = tenant.Id,
            Action = TenantAuditAction.ReviewClaimed,
            Title = "领取审核",
            Description = $"领取人：{displayName}",
            OperatorId = currentUserAccessor.UserId,
            OperatorName = displayName,
            PreviousStatus = tenant.Status,
            CurrentStatus = tenant.Status
        };

        // 5. (空行后) 写入领取记录（处理并发领取冲突）
        var success = await tenantRepository.TryAddReviewClaimAsync(claim, auditLog, cancellationToken);
        if (!success)
        {
            var current = await tenantRepository.GetActiveReviewClaimAsync(request.TenantId, cancellationToken);
            if (current == null)
            {
                throw new BusinessException(ErrorCodes.Conflict, "审核领取失败，请刷新后重试");
            }

            if (current.ClaimedBy == currentUserAccessor.UserId)
            {
                return current.ToDto();
            }

            throw new BusinessException(ErrorCodes.Conflict, $"该审核已被 {current.ClaimedByName} 领取");
        }

        // 6. (空行后) 返回领取结果
        return claim.ToDto();
    }
}
