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

namespace Baya.Application.Features.Variants.Queries.GetVariant;

internal sealed class GetVariantQueryHandler(ICurrentUser currentUser, IUnitOfWork unitOfWork)
    : IRequestHandler<GetVariantQuery, OperationResult<VariantDto>>
{
    public async ValueTask<OperationResult<VariantDto>> Handle(GetVariantQuery request, CancellationToken cancellationToken)
    {
        var roles = currentUser.Roles;

        // Admin: the full view of any variant, any state.
        if (roles?.Contains(RoleNames.Admin) == true)
            return Resolve(await unitOfWork.NurseServiceVariantRepository.GetProjectedAsync(request.Id, cancellationToken));

        // Owning nurse: the full view of their own variant, any state.
        if (currentUser.UserId is { } userId && roles?.Contains(RoleNames.Nurse) == true)
        {
            var nurseId = await unitOfWork.NurseProfileRepository.GetProfileIdByUserIdAsync(userId, cancellationToken);
            if (nurseId is { } nid)
            {
                var owned = await unitOfWork.NurseServiceVariantRepository.GetOwnedProjectedAsync(request.Id, nid, cancellationToken);
                if (owned is not null)
                    return OperationResult<VariantDto>.SuccessResult(owned);
            }
            // Not their variant → fall through to the public (active-only) projection.
        }

        // Everyone else (incl. anonymous): the public-safe projection — active variants only.
        return Resolve(await unitOfWork.NurseServiceVariantRepository.GetPublicProjectedAsync(request.Id, cancellationToken));
    }

    private static OperationResult<VariantDto> Resolve(VariantDto? dto)
        => dto is null
            ? OperationResult<VariantDto>.NotFoundResult("Variant not found.")
            : OperationResult<VariantDto>.SuccessResult(dto);
}
