#nullable enable
using Baya.Application.Contracts.Common;
using Baya.Application.Contracts.Persistence;
using Baya.Application.Models.Common;
using Baya.Application.Models.Patients;
using Mediator;

namespace Baya.Application.Features.PatientCareRecords.Queries.GetCarePlan;

internal sealed class GetCarePlanQueryHandler(
    ICurrentUser currentUser,
    IUnitOfWork unitOfWork)
    : IRequestHandler<GetCarePlanQuery, OperationResult<CarePlanDto>>
{
    public async ValueTask<OperationResult<CarePlanDto>> Handle(GetCarePlanQuery request, CancellationToken cancellationToken)
    {
        if (currentUser.UserId is null)
            return OperationResult<CarePlanDto>.UnauthorizedResult("Not authenticated.");

        var (owner, access) = await PatientAccess.ResolveAsync(currentUser, unitOfWork, request.PatientId, cancellationToken);
        if (owner is null)
            return OperationResult<CarePlanDto>.NotFoundResult("Patient not found.");
        if (!access.CanView)
            return OperationResult<CarePlanDto>.ForbiddenResult("You do not have access to this patient's care plan.");

        var plan = await unitOfWork.PatientCareRecordRepository.GetCarePlanAsync(request.PatientId, cancellationToken);
        return OperationResult<CarePlanDto>.SuccessResult(plan is null
            ? new CarePlanDto(request.PatientId, [], [], [])
            : new CarePlanDto(
                request.PatientId,
                CarePlanSerialization.ParseMedications(plan.MedicationsJson),
                CarePlanSerialization.ParseRoutine(plan.RoutineJson),
                CarePlanSerialization.ParseTasks(plan.TasksJson)));
    }
}
