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

namespace Baya.Application.Features.Identity.Commands.UpsertNurseProfile;

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

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

        var profile = await unitOfWork.NurseProfileRepository.GetByUserIdAsync(userId, cancellationToken);
        if (profile is null)
        {
            // Created unverified and not accepting bookings — verification (b6) is the only path to
            // is_verified; the nurse opts into bookability separately.
            profile = new NurseProfile { UserId = userId };
            Apply(profile, request);
            await unitOfWork.NurseProfileRepository.AddAsync(profile, cancellationToken);
        }
        else
        {
            Apply(profile, request);
        }

        await unitOfWork.CommitAsync();

        var dto = await unitOfWork.NurseProfileRepository.GetMineAsync(userId, cancellationToken);
        return OperationResult<NurseProfileDto>.SuccessResult(dto!);
    }

    private static void Apply(NurseProfile profile, UpsertNurseProfileCommand request)
    {
        profile.Bio = request.Bio;
        profile.YearsOfExperience = request.YearsOfExperience;
        profile.EducationLevel = request.EducationLevel;
        profile.EducationField = request.EducationField;
        profile.SpecializationsJson = request.SpecializationsJson;
    }
}
