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

namespace Baya.Application.Features.ServiceAreas.Commands.RemoveNurseServiceArea;

internal sealed class RemoveNurseServiceAreaCommandHandler(
    ICurrentUser currentUser,
    IUnitOfWork unitOfWork,
    IDateTimeProvider clock,
    ISearchIndexMaintainer searchIndex)
    : IRequestHandler<RemoveNurseServiceAreaCommand, OperationResult<bool>>
{
    public async ValueTask<OperationResult<bool>> Handle(RemoveNurseServiceAreaCommand request, CancellationToken cancellationToken)
    {
        if (currentUser.UserId is not { } userId)
            return OperationResult<bool>.UnauthorizedResult("Not authenticated.");

        if (currentUser.Roles?.Contains(RoleNames.Nurse) != true)
            return OperationResult<bool>.ForbiddenResult("Only a nurse can manage service areas.");

        var nurseId = await unitOfWork.NurseProfileRepository.GetProfileIdByUserIdAsync(userId, cancellationToken);
        if (nurseId is not { } nid)
            return OperationResult<bool>.NotFoundResult("Service area not found.");

        // Tenancy: a non-owned/nonexistent id resolves to null → not-found (existence is not leaked).
        var area = await unitOfWork.NurseServiceAreaRepository.GetOwnedAsync(request.Id, nid, cancellationToken);
        if (area is null)
            return OperationResult<bool>.NotFoundResult("Service area not found.");

        area.DeletedAt = clock.UtcNow;

        // Drop exactly this nurse×area's index rows across all variants, in the same transaction. Removing an
        // area must never collapse or touch the nurse's other areas.
        await searchIndex.RemoveServiceAreaRowsAsync(area.NurseId, area.CityId, area.DistrictId, cancellationToken);
        await unitOfWork.CommitAsync();

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