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

namespace Baya.Application.Features.Reviews.Queries.ListReviewsForNurse;

/// <summary>
/// Public reviews read. Returns <b>published</b> reviews only (the publish gate is enforced at the query
/// layer, not the UI) and the nurse's rating aggregate — read from the denormalized, published-only columns
/// and cached, with cache invalidation on every moderation transition.
/// </summary>
internal sealed class ListReviewsForNurseQueryHandler(
    IUnitOfWork unitOfWork,
    ICacheService cache)
    : IRequestHandler<ListReviewsForNurseQuery, OperationResult<NurseReviewsResult>>
{
    public async ValueTask<OperationResult<NurseReviewsResult>> Handle(ListReviewsForNurseQuery request, CancellationToken cancellationToken)
    {
        var page = request.Page < 1 ? 1 : request.Page;
        var pageSize = request.PageSize is < 1 or > 100 ? 20 : request.PageSize;

        var aggregate = await cache.GetOrCreateAsync(
            ReviewCache.AggregateKey(request.NurseProfileId),
            async ct => await unitOfWork.ReviewRepository.GetNurseAggregateAsync(request.NurseProfileId, ct),
            ReviewCache.Ttl,
            cancellationToken);

        var reviews = await unitOfWork.ReviewRepository.ListPublishedForNurseAsync(request.NurseProfileId, page, pageSize, cancellationToken);

        return OperationResult<NurseReviewsResult>.SuccessResult(new NurseReviewsResult(aggregate, reviews));
    }
}
