"""
Park Rides API views for ThrillWiki API v1.

This module implements endpoints for accessing rides within specific parks:
- GET /parks/{park_slug}/rides/ - List rides at a park with pagination and filtering
- GET /parks/{park_slug}/rides/{ride_slug}/ - Get specific ride details within park context
"""

from django.db.models import Q
from django.db.models.query import QuerySet
from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import OpenApiParameter, extend_schema
from rest_framework import permissions, status
from rest_framework.exceptions import NotFound
from rest_framework.pagination import PageNumberPagination
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.views import APIView

# Import models
try:
    from apps.parks.models import Park
    from apps.rides.models import Ride

    MODELS_AVAILABLE = True
except Exception:
    Park = None  # type: ignore
    Ride = None  # type: ignore
    MODELS_AVAILABLE = False

# Import serializers
try:
    from apps.api.v1.serializers.parks import ParkDetailOutputSerializer
    from apps.api.v1.serializers.rides import RideDetailOutputSerializer, RideListOutputSerializer

    SERIALIZERS_AVAILABLE = True
except Exception:
    SERIALIZERS_AVAILABLE = False


class StandardResultsSetPagination(PageNumberPagination):
    page_size = 20
    page_size_query_param = "page_size"
    max_page_size = 100


class ParkRidesListAPIView(APIView):
    """List rides at a specific park with pagination and filtering."""

    permission_classes = [permissions.AllowAny]

    @extend_schema(
        summary="List rides at a specific park",
        description="Get paginated list of rides at a specific park with filtering options",
        parameters=[
            # Pagination
            OpenApiParameter(
                name="page", location=OpenApiParameter.QUERY, type=OpenApiTypes.INT, description="Page number"
            ),
            OpenApiParameter(
                name="page_size",
                location=OpenApiParameter.QUERY,
                type=OpenApiTypes.INT,
                description="Number of results per page (max 100)",
            ),
            # Filtering
            OpenApiParameter(
                name="category",
                location=OpenApiParameter.QUERY,
                type=OpenApiTypes.STR,
                description="Filter by ride category",
            ),
            OpenApiParameter(
                name="status",
                location=OpenApiParameter.QUERY,
                type=OpenApiTypes.STR,
                description="Filter by operational status",
            ),
            OpenApiParameter(
                name="search",
                location=OpenApiParameter.QUERY,
                type=OpenApiTypes.STR,
                description="Search rides by name",
            ),
            # Ordering
            OpenApiParameter(
                name="ordering",
                location=OpenApiParameter.QUERY,
                type=OpenApiTypes.STR,
                description="Order results by field",
            ),
        ],
        responses={
            200: OpenApiTypes.OBJECT,
            404: OpenApiTypes.OBJECT,
        },
        tags=["Parks", "Rides"],
    )
    def get(self, request: Request, park_slug: str) -> Response:
        """List rides at a specific park."""
        if not MODELS_AVAILABLE:
            return Response(
                {"detail": "Park and ride models not available."},
                status=status.HTTP_501_NOT_IMPLEMENTED,
            )

        # Get the park
        try:
            park, is_historical = Park.get_by_slug(park_slug)
        except Park.DoesNotExist:
            raise NotFound("Park not found") from None

        # Get rides for this park
        qs = (
            Ride.objects.filter(park=park)
            .select_related("manufacturer", "designer", "ride_model", "park_area")
            .prefetch_related("photos")
        )

        # Apply filtering
        qs = self._apply_filters(qs, request.query_params)

        # Apply ordering
        ordering = request.query_params.get("ordering", "name")
        if ordering:
            qs = qs.order_by(ordering)

        # Paginate results
        paginator = StandardResultsSetPagination()
        page = paginator.paginate_queryset(qs, request)

        if SERIALIZERS_AVAILABLE:
            serializer = RideListOutputSerializer(page, many=True, context={"request": request, "park": park})
            return paginator.get_paginated_response(serializer.data)
        else:
            # Fallback serialization
            serializer_data = [
                {
                    "id": ride.id,
                    "name": ride.name,
                    "slug": ride.slug,
                    "category": getattr(ride, "category", ""),
                    "status": getattr(ride, "status", ""),
                    "manufacturer": {
                        "name": ride.manufacturer.name if ride.manufacturer else "",
                        "slug": getattr(ride.manufacturer, "slug", "") if ride.manufacturer else "",
                    },
                }
                for ride in page
            ]
            return paginator.get_paginated_response(serializer_data)

    def _apply_filters(self, qs: QuerySet, params: dict) -> QuerySet:
        """Apply filtering to the rides queryset."""
        # Category filter
        category = params.get("category")
        if category:
            qs = qs.filter(category=category)

        # Status filter
        status_filter = params.get("status")
        if status_filter:
            qs = qs.filter(status=status_filter)

        # Search filter
        search = params.get("search")
        if search:
            qs = qs.filter(
                Q(name__icontains=search) | Q(description__icontains=search) | Q(manufacturer__name__icontains=search)
            )

        return qs


class ParkRideDetailAPIView(APIView):
    """Get specific ride details within park context."""

    permission_classes = [permissions.AllowAny]

    @extend_schema(
        summary="Get ride details within park context",
        description="Get comprehensive details for a specific ride at a specific park",
        responses={
            200: OpenApiTypes.OBJECT,
            404: OpenApiTypes.OBJECT,
        },
        tags=["Parks", "Rides"],
    )
    def get(self, request: Request, park_slug: str, ride_slug: str) -> Response:
        """Get ride details within park context."""
        if not MODELS_AVAILABLE:
            return Response(
                {"detail": "Park and ride models not available."},
                status=status.HTTP_501_NOT_IMPLEMENTED,
            )

        # Get the park
        try:
            park, is_historical = Park.get_by_slug(park_slug)
        except Park.DoesNotExist:
            raise NotFound("Park not found") from None

        # Get the ride
        try:
            ride, is_historical = Ride.get_by_slug(ride_slug, park=park)
        except Ride.DoesNotExist:
            raise NotFound("Ride not found at this park") from None

        # Ensure ride belongs to this park
        if ride.park_id != park.id:
            raise NotFound("Ride not found at this park")

        if SERIALIZERS_AVAILABLE:
            serializer = RideDetailOutputSerializer(ride, context={"request": request, "park": park})
            return Response(serializer.data)
        else:
            # Fallback serialization
            return Response(
                {
                    "id": ride.id,
                    "name": ride.name,
                    "slug": ride.slug,
                    "description": getattr(ride, "description", ""),
                    "category": getattr(ride, "category", ""),
                    "status": getattr(ride, "status", ""),
                    "park": {
                        "id": park.id,
                        "name": park.name,
                        "slug": park.slug,
                    },
                    "manufacturer": (
                        {
                            "name": ride.manufacturer.name if ride.manufacturer else "",
                            "slug": getattr(ride.manufacturer, "slug", "") if ride.manufacturer else "",
                        }
                        if ride.manufacturer
                        else None
                    ),
                }
            )


class ParkComprehensiveDetailAPIView(APIView):
    """Get comprehensive park details including summary of rides."""

    permission_classes = [permissions.AllowAny]

    @extend_schema(
        summary="Get comprehensive park details with rides summary",
        description="Get complete park details including a summary of rides (first 10) and link to full rides list",
        responses={
            200: OpenApiTypes.OBJECT,
            404: OpenApiTypes.OBJECT,
        },
        tags=["Parks"],
    )
    def get(self, request: Request, park_slug: str) -> Response:
        """Get comprehensive park details with rides summary."""
        if not MODELS_AVAILABLE:
            return Response(
                {"detail": "Park and ride models not available."},
                status=status.HTTP_501_NOT_IMPLEMENTED,
            )

        # Get the park
        try:
            park, is_historical = Park.get_by_slug(park_slug)
        except Park.DoesNotExist:
            raise NotFound("Park not found") from None

        # Get park with full related data
        park = (
            Park.objects.select_related("operator", "property_owner", "location")
            .prefetch_related("areas", "rides", "photos")
            .get(pk=park.pk)
        )

        # Get a sample of rides (first 10) for preview
        rides_sample = Ride.objects.filter(park=park).select_related("manufacturer", "designer", "ride_model")[:10]

        if SERIALIZERS_AVAILABLE:
            # Get full park details
            park_serializer = ParkDetailOutputSerializer(park, context={"request": request})
            park_data = park_serializer.data

            # Add rides summary
            rides_serializer = RideListOutputSerializer(
                rides_sample, many=True, context={"request": request, "park": park}
            )

            # Enhance response with rides data
            park_data["rides_summary"] = {
                "total_count": park.ride_count or 0,
                "sample": rides_serializer.data,
                "full_list_url": f"/api/v1/parks/{park_slug}/rides/",
            }

            return Response(park_data)
        else:
            # Fallback serialization
            return Response(
                {
                    "id": park.id,
                    "name": park.name,
                    "slug": park.slug,
                    "description": getattr(park, "description", ""),
                    "location": str(getattr(park, "location", "")),
                    "operator": getattr(park.operator, "name", "") if hasattr(park, "operator") else "",
                    "ride_count": getattr(park, "ride_count", 0),
                    "rides_summary": {
                        "total_count": getattr(park, "ride_count", 0),
                        "sample": [
                            {
                                "id": ride.id,
                                "name": ride.name,
                                "slug": ride.slug,
                                "category": getattr(ride, "category", ""),
                            }
                            for ride in rides_sample
                        ],
                        "full_list_url": f"/api/v1/parks/{park_slug}/rides/",
                    },
                }
            )
