#nullable enable
using Baya.Application.Common;
using Baya.Application.Contracts.Audit;
using Baya.Application.Contracts.Common;
using Baya.Application.Contracts.Persistence;
using Baya.Application.Contracts.Search;
using Baya.Application.Models.Common;
using Baya.Domain.Entities.Verification;
using Mediator;

namespace Baya.Application.Features.Verification.Commands.SuspendVerification;

internal sealed class AdminSuspendVerificationCommandHandler(
    ICurrentUser currentUser,
    IUnitOfWork unitOfWork,
    IAuditLogger auditLogger,
    ICacheService cache,
    IDateTimeProvider dateTimeProvider,
    ISearchIndexMaintainer searchIndex)
    : IRequestHandler<AdminSuspendVerificationCommand, OperationResult<bool>>
{
    public async ValueTask<OperationResult<bool>> Handle(AdminSuspendVerificationCommand request, CancellationToken cancellationToken)
    {
        if (currentUser.UserId is not { } adminId)
            return OperationResult<bool>.UnauthorizedResult("Not authenticated.");

        var verification = await unitOfWork.VerificationRepository.GetTrackedByIdAsync(request.NurseVerificationId, cancellationToken);
        if (verification is null)
            return OperationResult<bool>.NotFoundResult("Verification not found.");

        var now = dateTimeProvider.UtcNow;
        var nurseId = verification.NurseId;

        verification.Status = VerificationStatus.Suspended;
        verification.SuspendedAt = now;
        verification.ReviewedByAdminId = adminId;
        verification.InternalNotes = request.Reason;

        var profile = await unitOfWork.NurseProfileRepository.GetTrackedByIdAsync(nurseId, cancellationToken);
        if (profile is null)
            return OperationResult<bool>.NotFoundResult("Nurse profile not found.");

        // Suspended status → the aggregator reverses is_verified in the same transaction.
        VerificationAggregator.Finalize(verification, profile, now);

        // A suspended nurse must vanish from search — flip all their rows to is_searchable=0 in this commit.
        await searchIndex.ReindexNurseAsync(profile, verification.Status, cancellationToken);

        await unitOfWork.CommitAsync();

        await auditLogger.WriteAsync(
            "nurse_verification",
            verification.Id.ToString(),
            "suspend",
            new Dictionary<string, object?> { ["admin_id"] = adminId, ["reason"] = request.Reason },
            cancellationToken);

        // Safety-critical: a suspended nurse must not read as verified — evict the badge immediately.
        await VerificationCache.InvalidateBadgeAsync(cache, nurseId, cancellationToken);

        return OperationResult<bool>.SuccessResult(true);
    }
}
