""" Views for review-related API endpoints. """ from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.permissions import AllowAny from rest_framework import status from drf_spectacular.utils import extend_schema, OpenApiParameter from drf_spectacular.types import OpenApiTypes from itertools import chain from operator import attrgetter from apps.parks.models.reviews import ParkReview from apps.rides.models.reviews import RideReview from ..serializers.reviews import LatestReviewSerializer class LatestReviewsAPIView(APIView): """ API endpoint to get the latest reviews from both parks and rides. Returns a combined list of the most recent reviews across the platform, including username, user avatar, date, score, and review snippet. """ permission_classes = [AllowAny] @extend_schema( summary="Get Latest Reviews", description=( "Retrieve the latest reviews from both parks and rides. " "Returns a combined list sorted by creation date, including " "user information, ratings, and content snippets." ), parameters=[ OpenApiParameter( name="limit", type=OpenApiTypes.INT, location=OpenApiParameter.QUERY, description="Number of reviews to return (default: 20, max: 100)", default=20, ), ], responses={ 200: LatestReviewSerializer(many=True), }, tags=["Reviews"], ) def get(self, request): """Get the latest reviews from both parks and rides.""" # Get limit parameter with validation try: limit = int(request.query_params.get("limit", 20)) limit = min(max(limit, 1), 100) # Clamp between 1 and 100 except (ValueError, TypeError): limit = 20 # Get published reviews from both models park_reviews = ( ParkReview.objects.filter(is_published=True) .select_related("user", "user__profile", "park") .order_by("-created_at")[:limit] ) ride_reviews = ( RideReview.objects.filter(is_published=True) .select_related("user", "user__profile", "ride", "ride__park") .order_by("-created_at")[:limit] ) # Combine and sort by created_at all_reviews = sorted( chain(park_reviews, ride_reviews), key=attrgetter("created_at"), reverse=True, )[:limit] # Serialize the combined results serializer = LatestReviewSerializer(all_reviews, many=True) return Response( {"count": len(all_reviews), "results": serializer.data}, status=status.HTTP_200_OK, )