#nullable enable
using System.Globalization;
using Baya.Application.Contracts.Common;
using Baya.Application.Contracts.Persistence;
using Baya.Application.Features.Bookings;
using Baya.Application.Models.Common;
using Baya.Application.Models.Payments;
using Mediator;

namespace Baya.Application.Features.Payments.Queries.GetNursePayableBalance;

internal sealed class GetNursePayableBalanceQueryHandler(
    ICurrentUser currentUser,
    IUnitOfWork unitOfWork)
    : IRequestHandler<GetNursePayableBalanceQuery, OperationResult<NursePayableBalanceDto>>
{
    public async ValueTask<OperationResult<NursePayableBalanceDto>> Handle(GetNursePayableBalanceQuery request, CancellationToken cancellationToken)
    {
        if (currentUser.UserId is not { } userId)
            return OperationResult<NursePayableBalanceDto>.UnauthorizedResult("Not authenticated.");

        // The nurse themself, or an admin/finance role — no one else may read a nurse's payable balance.
        var isAdmin = currentUser.Roles?.Any(BookingRoles.Admin.Contains) == true;
        if (!isAdmin)
        {
            var callerNurseId = await unitOfWork.NurseProfileRepository.GetProfileIdByUserIdAsync(userId, cancellationToken);
            if (callerNurseId is null || callerNurseId != request.NurseId)
                return OperationResult<NursePayableBalanceDto>.ForbiddenResult("You may only read your own payable balance.");
        }

        var balance = await unitOfWork.PaymentRepository.GetNursePayableBalanceAsync(request.NurseId, cancellationToken);
        return OperationResult<NursePayableBalanceDto>.SuccessResult(
            new NursePayableBalanceDto(request.NurseId, balance.ToString(CultureInfo.InvariantCulture)));
    }
}
