"""
RideModel API views for ThrillWiki API v1.

This module implements comprehensive endpoints for ride model management:
- List / Create: GET /ride-models/  POST /ride-models/
- Retrieve / Update / Delete: GET /ride-models/{pk}/  PATCH/PUT/DELETE
- Filter options: GET /ride-models/filter-options/
- Search: GET /ride-models/search/?q=...
- Statistics: GET /ride-models/stats/
- Variants: CRUD operations for ride model variants
- Technical specs: CRUD operations for technical specifications
- Photos: CRUD operations for ride model photos
"""

from datetime import timedelta
from typing import Any

from django.db.models import Count, Q
from django.utils import timezone
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, ValidationError
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 serializers
from apps.api.v1.serializers.ride_models import (
    RideModelCreateInputSerializer,
    RideModelDetailOutputSerializer,
    RideModelFilterInputSerializer,
    RideModelListOutputSerializer,
    RideModelStatsOutputSerializer,
    RideModelUpdateInputSerializer,
    RideModelVariantCreateInputSerializer,
    RideModelVariantOutputSerializer,
    RideModelVariantUpdateInputSerializer,
)

# Attempt to import models; fall back gracefully if not present
try:
    from apps.rides.models import (
        RideModel,
        RideModelPhoto,
        RideModelTechnicalSpec,
        RideModelVariant,
    )
    from apps.rides.models.company import Company

    MODELS_AVAILABLE = True
except ImportError:
    try:
        # Try alternative import path
        from apps.rides.models.rides import (
            Company,
            RideModel,
            RideModelPhoto,
            RideModelTechnicalSpec,
            RideModelVariant,
        )

        MODELS_AVAILABLE = True
    except ImportError:
        RideModel = None
        RideModelVariant = None
        RideModelPhoto = None
        RideModelTechnicalSpec = None
        Company = None
        MODELS_AVAILABLE = False


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


# === RIDE MODEL VIEWS ===


class RideModelListCreateAPIView(APIView):
    permission_classes = [permissions.AllowAny]

    @extend_schema(
        summary="List ride models with filtering and pagination",
        description="List ride models with comprehensive filtering and pagination.",
        parameters=[
            OpenApiParameter(
                name="manufacturer_slug",
                location=OpenApiParameter.PATH,
                type=OpenApiTypes.STR,
                required=True,
            ),
            OpenApiParameter(name="page", location=OpenApiParameter.QUERY, type=OpenApiTypes.INT),
            OpenApiParameter(name="page_size", location=OpenApiParameter.QUERY, type=OpenApiTypes.INT),
            OpenApiParameter(name="search", location=OpenApiParameter.QUERY, type=OpenApiTypes.STR),
            OpenApiParameter(name="category", location=OpenApiParameter.QUERY, type=OpenApiTypes.STR),
            OpenApiParameter(
                name="target_market",
                location=OpenApiParameter.QUERY,
                type=OpenApiTypes.STR,
            ),
            OpenApiParameter(
                name="is_discontinued",
                location=OpenApiParameter.QUERY,
                type=OpenApiTypes.BOOL,
            ),
        ],
        responses={200: RideModelListOutputSerializer(many=True)},
        tags=["Ride Models"],
    )
    def get(self, request: Request, manufacturer_slug: str) -> Response:
        """List ride models for a specific manufacturer with filtering and pagination."""
        if not MODELS_AVAILABLE:
            return Response(
                {
                    "detail": "Ride model listing is not available because domain models are not imported. "
                    "Implement apps.rides.models.RideModel to enable listing."
                },
                status=status.HTTP_501_NOT_IMPLEMENTED,
            )

        # Get manufacturer or 404
        try:
            manufacturer = Company.objects.get(slug=manufacturer_slug)
        except Company.DoesNotExist:
            raise NotFound("Manufacturer not found") from None

        qs = (
            RideModel.objects.filter(manufacturer=manufacturer)
            .select_related("manufacturer")
            .prefetch_related("photos")
        )

        # Apply filters
        filter_serializer = RideModelFilterInputSerializer(data=request.query_params)
        if filter_serializer.is_valid():
            filters = filter_serializer.validated_data

            # Search filter
            if filters.get("search"):
                search_term = filters["search"]
                qs = qs.filter(
                    Q(name__icontains=search_term)
                    | Q(description__icontains=search_term)
                    | Q(manufacturer__name__icontains=search_term)
                )

            # Category filter
            if filters.get("category"):
                qs = qs.filter(category__in=filters["category"])

            # Manufacturer filters
            if filters.get("manufacturer_id"):
                qs = qs.filter(manufacturer_id=filters["manufacturer_id"])
            if filters.get("manufacturer_slug"):
                qs = qs.filter(manufacturer__slug=filters["manufacturer_slug"])

            # Target market filter
            if filters.get("target_market"):
                qs = qs.filter(target_market__in=filters["target_market"])

            # Discontinued filter
            if filters.get("is_discontinued") is not None:
                qs = qs.filter(is_discontinued=filters["is_discontinued"])

            # Year filters
            if filters.get("first_installation_year_min"):
                qs = qs.filter(first_installation_year__gte=filters["first_installation_year_min"])
            if filters.get("first_installation_year_max"):
                qs = qs.filter(first_installation_year__lte=filters["first_installation_year_max"])

            # Installation count filter
            if filters.get("min_installations"):
                qs = qs.filter(total_installations__gte=filters["min_installations"])

            # Height filters
            if filters.get("min_height_ft"):
                qs = qs.filter(typical_height_range_max_ft__gte=filters["min_height_ft"])
            if filters.get("max_height_ft"):
                qs = qs.filter(typical_height_range_min_ft__lte=filters["max_height_ft"])

            # Speed filters
            if filters.get("min_speed_mph"):
                qs = qs.filter(typical_speed_range_max_mph__gte=filters["min_speed_mph"])
            if filters.get("max_speed_mph"):
                qs = qs.filter(typical_speed_range_min_mph__lte=filters["max_speed_mph"])

            # Ordering
            ordering = filters.get("ordering", "manufacturer__name,name")
            if ordering:
                order_fields = ordering.split(",")
                qs = qs.order_by(*order_fields)

        paginator = StandardResultsSetPagination()
        page = paginator.paginate_queryset(qs, request)
        serializer = RideModelListOutputSerializer(page, many=True, context={"request": request})
        return paginator.get_paginated_response(serializer.data)

    @extend_schema(
        summary="Create a new ride model",
        description="Create a new ride model for a specific manufacturer.",
        parameters=[
            OpenApiParameter(
                name="manufacturer_slug",
                location=OpenApiParameter.PATH,
                type=OpenApiTypes.STR,
                required=True,
            ),
        ],
        request=RideModelCreateInputSerializer,
        responses={201: RideModelDetailOutputSerializer()},
        tags=["Ride Models"],
    )
    def post(self, request: Request, manufacturer_slug: str) -> Response:
        """Create a new ride model for a specific manufacturer."""
        if not MODELS_AVAILABLE:
            return Response(
                {"detail": "Ride model creation is not available because domain models are not imported."},
                status=status.HTTP_501_NOT_IMPLEMENTED,
            )

        # Get manufacturer or 404
        try:
            manufacturer = Company.objects.get(slug=manufacturer_slug)
        except Company.DoesNotExist:
            raise NotFound("Manufacturer not found") from None

        serializer_in = RideModelCreateInputSerializer(data=request.data)
        serializer_in.is_valid(raise_exception=True)
        validated = serializer_in.validated_data

        # Create ride model (use manufacturer from URL, not from request data)
        ride_model = RideModel.objects.create(
            name=validated["name"],
            description=validated.get("description", ""),
            category=validated.get("category", ""),
            manufacturer=manufacturer,
            typical_height_range_min_ft=validated.get("typical_height_range_min_ft"),
            typical_height_range_max_ft=validated.get("typical_height_range_max_ft"),
            typical_speed_range_min_mph=validated.get("typical_speed_range_min_mph"),
            typical_speed_range_max_mph=validated.get("typical_speed_range_max_mph"),
            typical_capacity_range_min=validated.get("typical_capacity_range_min"),
            typical_capacity_range_max=validated.get("typical_capacity_range_max"),
            track_type=validated.get("track_type", ""),
            support_structure=validated.get("support_structure", ""),
            train_configuration=validated.get("train_configuration", ""),
            restraint_system=validated.get("restraint_system", ""),
            first_installation_year=validated.get("first_installation_year"),
            last_installation_year=validated.get("last_installation_year"),
            is_discontinued=validated.get("is_discontinued", False),
            notable_features=validated.get("notable_features", ""),
            target_market=validated.get("target_market", ""),
        )

        out_serializer = RideModelDetailOutputSerializer(ride_model, context={"request": request})
        return Response(out_serializer.data, status=status.HTTP_201_CREATED)


class RideModelDetailAPIView(APIView):
    permission_classes = [permissions.AllowAny]

    def _get_ride_model_or_404(self, manufacturer_slug: str, ride_model_slug: str) -> Any:
        if not MODELS_AVAILABLE:
            raise NotFound("Ride model models not available")
        try:
            return (
                RideModel.objects.select_related("manufacturer")
                .prefetch_related("photos", "variants", "technical_specs")
                .get(manufacturer__slug=manufacturer_slug, slug=ride_model_slug)
            )
        except RideModel.DoesNotExist:
            raise NotFound("Ride model not found") from None

    @extend_schema(
        summary="Retrieve a ride model",
        description="Get detailed information about a specific ride model.",
        parameters=[
            OpenApiParameter(
                name="manufacturer_slug",
                location=OpenApiParameter.PATH,
                type=OpenApiTypes.STR,
                required=True,
            ),
            OpenApiParameter(
                name="ride_model_slug",
                location=OpenApiParameter.PATH,
                type=OpenApiTypes.STR,
                required=True,
            ),
        ],
        responses={200: RideModelDetailOutputSerializer()},
        tags=["Ride Models"],
    )
    def get(self, request: Request, manufacturer_slug: str, ride_model_slug: str) -> Response:
        ride_model = self._get_ride_model_or_404(manufacturer_slug, ride_model_slug)
        serializer = RideModelDetailOutputSerializer(ride_model, context={"request": request})
        return Response(serializer.data)

    @extend_schema(
        summary="Update a ride model",
        description="Update a ride model (partial update supported).",
        parameters=[
            OpenApiParameter(
                name="manufacturer_slug",
                location=OpenApiParameter.PATH,
                type=OpenApiTypes.STR,
                required=True,
            ),
            OpenApiParameter(
                name="ride_model_slug",
                location=OpenApiParameter.PATH,
                type=OpenApiTypes.STR,
                required=True,
            ),
        ],
        request=RideModelUpdateInputSerializer,
        responses={200: RideModelDetailOutputSerializer()},
        tags=["Ride Models"],
    )
    def patch(self, request: Request, manufacturer_slug: str, ride_model_slug: str) -> Response:
        ride_model = self._get_ride_model_or_404(manufacturer_slug, ride_model_slug)
        serializer_in = RideModelUpdateInputSerializer(data=request.data, partial=True)
        serializer_in.is_valid(raise_exception=True)

        # Update fields
        for field, value in serializer_in.validated_data.items():
            if field == "manufacturer_id":
                try:
                    manufacturer = Company.objects.get(id=value)
                    ride_model.manufacturer = manufacturer
                except Company.DoesNotExist:
                    raise ValidationError({"manufacturer_id": "Manufacturer not found"}) from None
            else:
                setattr(ride_model, field, value)

        ride_model.save()

        serializer = RideModelDetailOutputSerializer(ride_model, context={"request": request})
        return Response(serializer.data)

    def put(self, request: Request, manufacturer_slug: str, ride_model_slug: str) -> Response:
        # Full replace - reuse patch behavior for simplicity
        return self.patch(request, manufacturer_slug, ride_model_slug)

    @extend_schema(
        summary="Delete a ride model",
        description="Delete a ride model.",
        parameters=[
            OpenApiParameter(
                name="manufacturer_slug",
                location=OpenApiParameter.PATH,
                type=OpenApiTypes.STR,
                required=True,
            ),
            OpenApiParameter(
                name="ride_model_slug",
                location=OpenApiParameter.PATH,
                type=OpenApiTypes.STR,
                required=True,
            ),
        ],
        responses={204: None},
        tags=["Ride Models"],
    )
    def delete(self, request: Request, manufacturer_slug: str, ride_model_slug: str) -> Response:
        ride_model = self._get_ride_model_or_404(manufacturer_slug, ride_model_slug)
        ride_model.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)


# === RIDE MODEL SEARCH AND FILTER OPTIONS ===


class RideModelSearchAPIView(APIView):
    permission_classes = [permissions.AllowAny]

    @extend_schema(
        summary="Search ride models",
        description="Search ride models by name, description, or manufacturer.",
        parameters=[
            OpenApiParameter(
                name="q",
                location=OpenApiParameter.QUERY,
                type=OpenApiTypes.STR,
                required=True,
            )
        ],
        responses={200: RideModelListOutputSerializer(many=True)},
        tags=["Ride Models"],
    )
    def get(self, request: Request) -> Response:
        q = request.query_params.get("q", "")
        if not q:
            return Response([], status=status.HTTP_200_OK)

        if not MODELS_AVAILABLE:
            return Response(
                [
                    {
                        "id": 1,
                        "name": "Hyper Coaster",
                        "manufacturer": {"name": "Bolliger & Mabillard"},
                        "category": "RC",
                    }
                ]
            )

        qs = RideModel.objects.filter(
            Q(name__icontains=q) | Q(description__icontains=q) | Q(manufacturer__name__icontains=q)
        ).select_related("manufacturer")[:20]

        results = [
            {
                "id": model.id,
                "name": model.name,
                "slug": model.slug,
                "manufacturer": {
                    "id": model.manufacturer.id if model.manufacturer else None,
                    "name": model.manufacturer.name if model.manufacturer else None,
                    "slug": model.manufacturer.slug if model.manufacturer else None,
                },
                "category": model.category,
                "target_market": model.target_market,
                "is_discontinued": model.is_discontinued,
            }
            for model in qs
        ]
        return Response(results)


class RideModelFilterOptionsAPIView(APIView):
    permission_classes = [permissions.AllowAny]

    @extend_schema(
        summary="Get filter options for ride models",
        description="Get available filter options for ride model filtering.",
        responses={200: OpenApiTypes.OBJECT},
        tags=["Ride Models"],
    )
    def get(self, request: Request) -> Response:
        """Return filter options for ride models with Rich Choice Objects metadata."""
        # Import Rich Choice registry
        from apps.core.choices.registry import get_choices

        if not MODELS_AVAILABLE:
            # Use Rich Choice Objects for fallback options
            try:
                # Get rich choice objects from registry
                categories = get_choices("categories", "rides")
                target_markets = get_choices("target_markets", "rides")

                # Convert Rich Choice Objects to frontend format with metadata
                categories_data = [
                    {
                        "value": choice.value,
                        "label": choice.label,
                        "description": choice.description,
                        "color": choice.metadata.get("color"),
                        "icon": choice.metadata.get("icon"),
                        "css_class": choice.metadata.get("css_class"),
                        "sort_order": choice.metadata.get("sort_order", 0),
                    }
                    for choice in categories
                ]

                target_markets_data = [
                    {
                        "value": choice.value,
                        "label": choice.label,
                        "description": choice.description,
                        "color": choice.metadata.get("color"),
                        "icon": choice.metadata.get("icon"),
                        "css_class": choice.metadata.get("css_class"),
                        "sort_order": choice.metadata.get("sort_order", 0),
                    }
                    for choice in target_markets
                ]

            except Exception:
                # Ultimate fallback with basic structure
                categories_data = [
                    {
                        "value": "RC",
                        "label": "Roller Coaster",
                        "description": "High-speed thrill rides with tracks",
                        "color": "red",
                        "icon": "roller-coaster",
                        "css_class": "bg-red-100 text-red-800",
                        "sort_order": 1,
                    },
                    {
                        "value": "DR",
                        "label": "Dark Ride",
                        "description": "Indoor themed experiences",
                        "color": "purple",
                        "icon": "dark-ride",
                        "css_class": "bg-purple-100 text-purple-800",
                        "sort_order": 2,
                    },
                    {
                        "value": "FR",
                        "label": "Flat Ride",
                        "description": "Spinning and rotating attractions",
                        "color": "blue",
                        "icon": "flat-ride",
                        "css_class": "bg-blue-100 text-blue-800",
                        "sort_order": 3,
                    },
                    {
                        "value": "WR",
                        "label": "Water Ride",
                        "description": "Water-based attractions and slides",
                        "color": "cyan",
                        "icon": "water-ride",
                        "css_class": "bg-cyan-100 text-cyan-800",
                        "sort_order": 4,
                    },
                    {
                        "value": "TR",
                        "label": "Transport",
                        "description": "Transportation systems within parks",
                        "color": "green",
                        "icon": "transport",
                        "css_class": "bg-green-100 text-green-800",
                        "sort_order": 5,
                    },
                    {
                        "value": "OT",
                        "label": "Other",
                        "description": "Miscellaneous attractions",
                        "color": "gray",
                        "icon": "other",
                        "css_class": "bg-gray-100 text-gray-800",
                        "sort_order": 6,
                    },
                ]
                target_markets_data = [
                    {
                        "value": "FAMILY",
                        "label": "Family",
                        "description": "Suitable for all family members",
                        "color": "green",
                        "icon": "family",
                        "css_class": "bg-green-100 text-green-800",
                        "sort_order": 1,
                    },
                    {
                        "value": "THRILL",
                        "label": "Thrill",
                        "description": "High-intensity thrill experience",
                        "color": "orange",
                        "icon": "thrill",
                        "css_class": "bg-orange-100 text-orange-800",
                        "sort_order": 2,
                    },
                    {
                        "value": "EXTREME",
                        "label": "Extreme",
                        "description": "Maximum intensity experience",
                        "color": "red",
                        "icon": "extreme",
                        "css_class": "bg-red-100 text-red-800",
                        "sort_order": 3,
                    },
                    {
                        "value": "KIDDIE",
                        "label": "Kiddie",
                        "description": "Designed for young children",
                        "color": "pink",
                        "icon": "kiddie",
                        "css_class": "bg-pink-100 text-pink-800",
                        "sort_order": 4,
                    },
                    {
                        "value": "ALL_AGES",
                        "label": "All Ages",
                        "description": "Enjoyable for all age groups",
                        "color": "blue",
                        "icon": "all-ages",
                        "css_class": "bg-blue-100 text-blue-800",
                        "sort_order": 5,
                    },
                ]

            return Response(
                {
                    "categories": categories_data,
                    "target_markets": target_markets_data,
                    "manufacturers": [{"id": 1, "name": "Bolliger & Mabillard", "slug": "bolliger-mabillard"}],
                    "ordering_options": [
                        {"value": "name", "label": "Name A-Z"},
                        {"value": "-name", "label": "Name Z-A"},
                        {"value": "manufacturer__name", "label": "Manufacturer A-Z"},
                        {"value": "-manufacturer__name", "label": "Manufacturer Z-A"},
                        {"value": "first_installation_year", "label": "Oldest First"},
                        {"value": "-first_installation_year", "label": "Newest First"},
                        {"value": "total_installations", "label": "Fewest Installations"},
                        {"value": "-total_installations", "label": "Most Installations"},
                    ],
                }
            )

        # Get static choice definitions from Rich Choice Objects (primary source)
        # Get dynamic data from database queries

        # Get rich choice objects from registry
        categories = get_choices("categories", "rides")
        target_markets = get_choices("target_markets", "rides")

        # Convert Rich Choice Objects to frontend format with metadata
        categories_data = [
            {
                "value": choice.value,
                "label": choice.label,
                "description": choice.description,
                "color": choice.metadata.get("color"),
                "icon": choice.metadata.get("icon"),
                "css_class": choice.metadata.get("css_class"),
                "sort_order": choice.metadata.get("sort_order", 0),
            }
            for choice in categories
        ]

        target_markets_data = [
            {
                "value": choice.value,
                "label": choice.label,
                "description": choice.description,
                "color": choice.metadata.get("color"),
                "icon": choice.metadata.get("icon"),
                "css_class": choice.metadata.get("css_class"),
                "sort_order": choice.metadata.get("sort_order", 0),
            }
            for choice in target_markets
        ]

        # Get actual data from database
        manufacturers = (
            Company.objects.filter(roles__contains=["MANUFACTURER"], ride_models__isnull=False)
            .distinct()
            .values("id", "name", "slug")
        )

        return Response(
            {
                "categories": categories_data,
                "target_markets": target_markets_data,
                "manufacturers": list(manufacturers),
                "ordering_options": [
                    {"value": "name", "label": "Name A-Z"},
                    {"value": "-name", "label": "Name Z-A"},
                    {"value": "manufacturer__name", "label": "Manufacturer A-Z"},
                    {"value": "-manufacturer__name", "label": "Manufacturer Z-A"},
                    {"value": "first_installation_year", "label": "Oldest First"},
                    {"value": "-first_installation_year", "label": "Newest First"},
                    {"value": "total_installations", "label": "Fewest Installations"},
                    {"value": "-total_installations", "label": "Most Installations"},
                ],
            }
        )


# === RIDE MODEL STATISTICS ===


class RideModelStatsAPIView(APIView):
    permission_classes = [permissions.AllowAny]

    @extend_schema(
        summary="Get ride model statistics",
        description="Get comprehensive statistics about ride models.",
        responses={200: RideModelStatsOutputSerializer()},
        tags=["Ride Models"],
    )
    def get(self, request: Request) -> Response:
        """Get ride model statistics."""
        if not MODELS_AVAILABLE:
            return Response(
                {
                    "total_models": 50,
                    "total_installations": 500,
                    "active_manufacturers": 15,
                    "discontinued_models": 10,
                    "by_category": {"RC": 30, "FR": 15, "WR": 5},
                    "by_target_market": {"THRILL": 25, "FAMILY": 20, "EXTREME": 5},
                    "by_manufacturer": {"Bolliger & Mabillard": 8, "Intamin": 6},
                    "recent_models": 3,
                }
            )

        # Calculate statistics
        total_models = RideModel.objects.count()
        total_installations = RideModel.objects.aggregate(total=Count("rides"))["total"] or 0

        active_manufacturers = (
            Company.objects.filter(roles__contains=["MANUFACTURER"], ride_models__isnull=False).distinct().count()
        )

        discontinued_models = RideModel.objects.filter(is_discontinued=True).count()

        # Category breakdown
        by_category = {}
        category_counts = RideModel.objects.exclude(category="").values("category").annotate(count=Count("id"))
        for item in category_counts:
            by_category[item["category"]] = item["count"]

        # Target market breakdown
        by_target_market = {}
        market_counts = RideModel.objects.exclude(target_market="").values("target_market").annotate(count=Count("id"))
        for item in market_counts:
            by_target_market[item["target_market"]] = item["count"]

        # Manufacturer breakdown (top 10)
        by_manufacturer = {}
        manufacturer_counts = (
            RideModel.objects.filter(manufacturer__isnull=False)
            .values("manufacturer__name")
            .annotate(count=Count("id"))
            .order_by("-count")[:10]
        )
        for item in manufacturer_counts:
            by_manufacturer[item["manufacturer__name"]] = item["count"]

        # Recent models (last 30 days)
        thirty_days_ago = timezone.now() - timedelta(days=30)
        recent_models = RideModel.objects.filter(created_at__gte=thirty_days_ago).count()

        return Response(
            {
                "total_models": total_models,
                "total_installations": total_installations,
                "active_manufacturers": active_manufacturers,
                "discontinued_models": discontinued_models,
                "by_category": by_category,
                "by_target_market": by_target_market,
                "by_manufacturer": by_manufacturer,
                "recent_models": recent_models,
            }
        )


# === RIDE MODEL VARIANTS ===


class RideModelVariantListCreateAPIView(APIView):
    permission_classes = [permissions.AllowAny]

    @extend_schema(
        summary="List variants for a ride model",
        description="Get all variants for a specific ride model.",
        responses={200: RideModelVariantOutputSerializer(many=True)},
        tags=["Ride Model Variants"],
    )
    def get(self, request: Request, ride_model_pk: int) -> Response:
        if not MODELS_AVAILABLE:
            return Response([])

        try:
            ride_model = RideModel.objects.get(pk=ride_model_pk)
        except RideModel.DoesNotExist:
            raise NotFound("Ride model not found") from None

        variants = RideModelVariant.objects.filter(ride_model=ride_model)
        serializer = RideModelVariantOutputSerializer(variants, many=True)
        return Response(serializer.data)

    @extend_schema(
        summary="Create a variant for a ride model",
        description="Create a new variant for a specific ride model.",
        request=RideModelVariantCreateInputSerializer,
        responses={201: RideModelVariantOutputSerializer()},
        tags=["Ride Model Variants"],
    )
    def post(self, request: Request, ride_model_pk: int) -> Response:
        if not MODELS_AVAILABLE:
            return Response(
                {"detail": "Variants not available"},
                status=status.HTTP_501_NOT_IMPLEMENTED,
            )

        try:
            ride_model = RideModel.objects.get(pk=ride_model_pk)
        except RideModel.DoesNotExist:
            raise NotFound("Ride model not found") from None

        # Override ride_model_id in the data
        data = request.data.copy()
        data["ride_model_id"] = ride_model_pk

        serializer_in = RideModelVariantCreateInputSerializer(data=data)
        serializer_in.is_valid(raise_exception=True)
        validated = serializer_in.validated_data

        variant = RideModelVariant.objects.create(
            ride_model=ride_model,
            name=validated["name"],
            description=validated.get("description", ""),
            min_height_ft=validated.get("min_height_ft"),
            max_height_ft=validated.get("max_height_ft"),
            min_speed_mph=validated.get("min_speed_mph"),
            max_speed_mph=validated.get("max_speed_mph"),
            distinguishing_features=validated.get("distinguishing_features", ""),
        )

        serializer = RideModelVariantOutputSerializer(variant)
        return Response(serializer.data, status=status.HTTP_201_CREATED)


class RideModelVariantDetailAPIView(APIView):
    permission_classes = [permissions.AllowAny]

    def _get_variant_or_404(self, ride_model_pk: int, pk: int) -> Any:
        if not MODELS_AVAILABLE:
            raise NotFound("Variants not available")
        try:
            return RideModelVariant.objects.get(ride_model_id=ride_model_pk, pk=pk)
        except RideModelVariant.DoesNotExist:
            raise NotFound("Variant not found") from None

    @extend_schema(
        summary="Get a ride model variant",
        responses={200: RideModelVariantOutputSerializer()},
        tags=["Ride Model Variants"],
    )
    def get(self, request: Request, ride_model_pk: int, pk: int) -> Response:
        variant = self._get_variant_or_404(ride_model_pk, pk)
        serializer = RideModelVariantOutputSerializer(variant)
        return Response(serializer.data)

    @extend_schema(
        summary="Update a ride model variant",
        request=RideModelVariantUpdateInputSerializer,
        responses={200: RideModelVariantOutputSerializer()},
        tags=["Ride Model Variants"],
    )
    def patch(self, request: Request, ride_model_pk: int, pk: int) -> Response:
        variant = self._get_variant_or_404(ride_model_pk, pk)
        serializer_in = RideModelVariantUpdateInputSerializer(data=request.data, partial=True)
        serializer_in.is_valid(raise_exception=True)

        for field, value in serializer_in.validated_data.items():
            setattr(variant, field, value)
        variant.save()

        serializer = RideModelVariantOutputSerializer(variant)
        return Response(serializer.data)

    @extend_schema(
        summary="Delete a ride model variant",
        responses={204: None},
        tags=["Ride Model Variants"],
    )
    def delete(self, request: Request, ride_model_pk: int, pk: int) -> Response:
        variant = self._get_variant_or_404(ride_model_pk, pk)
        variant.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)


# Note: Similar patterns would be implemented for RideModelTechnicalSpec and RideModelPhoto
# For brevity, I'm including the class definitions but not the full implementations


class RideModelTechnicalSpecListCreateAPIView(APIView):
    """CRUD operations for ride model technical specifications."""

    permission_classes = [permissions.AllowAny]
    # Implementation similar to variants...


class RideModelTechnicalSpecDetailAPIView(APIView):
    """CRUD operations for individual technical specifications."""

    permission_classes = [permissions.AllowAny]
    # Implementation similar to variant detail...


class RideModelPhotoListCreateAPIView(APIView):
    """CRUD operations for ride model photos."""

    permission_classes = [permissions.AllowAny]
    # Implementation similar to variants...


class RideModelPhotoDetailAPIView(APIView):
    """CRUD operations for individual ride model photos."""

    permission_classes = [permissions.AllowAny]
    # Implementation similar to variant detail...
