from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status from rest_framework.permissions import AllowAny from django.db.models import F from django.utils import timezone from drf_spectacular.utils import extend_schema from datetime import timedelta from apps.parks.models import Park from apps.rides.models import Ride class DiscoveryAPIView(APIView): """ API endpoint for discovery content (Top Lists, Opening/Closing Soon). """ permission_classes = [AllowAny] @extend_schema( summary="Get discovery content", description="Retrieve curated lists for discovery tabs (Top, Opening, Closing).", responses={200: "object"}, tags=["Discovery"], ) def get(self, request): today = timezone.now().date() limit = 10 # --- TOP LISTS --- # Top Parks by average rating top_parks = Park.objects.filter(average_rating__isnull=False).order_by("-average_rating")[:limit] # Top Rides by average rating (fallback to RideRanking in future) top_rides = Ride.objects.filter(average_rating__isnull=False).order_by("-average_rating")[:limit] # --- OPENING --- # Opening Soon (Future opening date) opening_soon_parks = Park.objects.filter(opening_date__gt=today).order_by("opening_date")[:limit] opening_soon_rides = Ride.objects.filter(opening_date__gt=today).order_by("opening_date")[:limit] # Recently Opened (Past opening date, descending) recently_opened_parks = Park.objects.filter(opening_date__lte=today).order_by("-opening_date")[:limit] recently_opened_rides = Ride.objects.filter(opening_date__lte=today).order_by("-opening_date")[:limit] # --- CLOSING --- # Closing Soon (Future closing date) closing_soon_parks = Park.objects.filter(closing_date__gt=today).order_by("closing_date")[:limit] closing_soon_rides = Ride.objects.filter(closing_date__gt=today).order_by("closing_date")[:limit] # Recently Closed (Past closing date, descending) recently_closed_parks = Park.objects.filter(closing_date__lte=today).order_by("-closing_date")[:limit] recently_closed_rides = Ride.objects.filter(closing_date__lte=today).order_by("-closing_date")[:limit] data = { "top_parks": self._serialize(top_parks, "park"), "top_rides": self._serialize(top_rides, "ride"), "opening_soon": { "parks": self._serialize(opening_soon_parks, "park"), "rides": self._serialize(opening_soon_rides, "ride"), }, "recently_opened": { "parks": self._serialize(recently_opened_parks, "park"), "rides": self._serialize(recently_opened_rides, "ride"), }, "closing_soon": { "parks": self._serialize(closing_soon_parks, "park"), "rides": self._serialize(closing_soon_rides, "ride"), }, "recently_closed": { "parks": self._serialize(recently_closed_parks, "park"), "rides": self._serialize(recently_closed_rides, "ride"), } } return Response(data) def _serialize(self, queryset, type_): results = [] for item in queryset: data = { "id": item.id, "name": item.name, "slug": item.slug, "average_rating": item.average_rating, } if type_ == "park": data.update({ "city": item.location.city if item.location else None, "state": item.location.state if item.location else None, }) elif type_ == "ride": data.update({ "park_name": item.park.name, "park_slug": item.park.slug }) results.append(data) return results