"""
RideModel serializers for ThrillWiki API v1.

This module contains all serializers related to ride models, variants,
technical specifications, and related functionality.
"""

from drf_spectacular.utils import (
    OpenApiExample,
    extend_schema_field,
    extend_schema_serializer,
)
from rest_framework import serializers

from apps.core.choices.serializers import RichChoiceFieldSerializer
from config.django import base as settings

from .shared import ModelChoices

# Use dynamic imports to avoid circular import issues


def get_ride_model_classes():
    """Get ride model classes dynamically to avoid import issues."""
    from apps.rides.models import (
        RideModel,
        RideModelPhoto,
        RideModelTechnicalSpec,
        RideModelVariant,
    )

    return RideModel, RideModelVariant, RideModelPhoto, RideModelTechnicalSpec


# === RIDE MODEL SERIALIZERS ===


class RideModelManufacturerOutputSerializer(serializers.Serializer):
    """Output serializer for ride model's manufacturer data."""

    id = serializers.IntegerField()
    name = serializers.CharField()
    slug = serializers.CharField()


class RideModelPhotoOutputSerializer(serializers.Serializer):
    """Output serializer for ride model photos."""

    id = serializers.IntegerField()
    image_url = serializers.SerializerMethodField()
    caption = serializers.CharField()
    alt_text = serializers.CharField()
    photo_type = serializers.CharField()
    is_primary = serializers.BooleanField()
    photographer = serializers.CharField()
    source = serializers.CharField()

    @extend_schema_field(serializers.URLField(allow_null=True))
    def get_image_url(self, obj):
        """Get the image URL."""
        if obj.image:
            return obj.image.public_url
        return None


class RideModelTechnicalSpecOutputSerializer(serializers.Serializer):
    """Output serializer for ride model technical specifications."""

    id = serializers.IntegerField()
    spec_category = serializers.CharField()
    spec_name = serializers.CharField()
    spec_value = serializers.CharField()
    spec_unit = serializers.CharField()
    notes = serializers.CharField()


class RideModelVariantOutputSerializer(serializers.Serializer):
    """Output serializer for ride model variants."""

    id = serializers.IntegerField()
    name = serializers.CharField()
    description = serializers.CharField()
    min_height_ft = serializers.DecimalField(max_digits=6, decimal_places=2, allow_null=True)
    max_height_ft = serializers.DecimalField(max_digits=6, decimal_places=2, allow_null=True)
    min_speed_mph = serializers.DecimalField(max_digits=5, decimal_places=2, allow_null=True)
    max_speed_mph = serializers.DecimalField(max_digits=5, decimal_places=2, allow_null=True)
    distinguishing_features = serializers.CharField()


@extend_schema_serializer(
    examples=[
        OpenApiExample(
            "Ride Model List Example",
            summary="Example ride model list response",
            description="A typical ride model in the list view",
            value={
                "id": 1,
                "name": "Hyper Coaster",
                "slug": "bolliger-mabillard-hyper-coaster",
                "category": "RC",
                "description": "High-speed steel roller coaster with airtime hills",
                "manufacturer": {
                    "id": 1,
                    "name": "Bolliger & Mabillard",
                    "slug": "bolliger-mabillard",
                },
                "target_market": "THRILL",
                "is_discontinued": False,
                "total_installations": 15,
                "first_installation_year": 1999,
                "height_range_display": "200-325 ft",
                "speed_range_display": "70-95 mph",
                "primary_image": {
                    "id": 123,
                    "image_url": "https://example.com/image.jpg",
                    "caption": "B&M Hyper Coaster",
                    "photo_type": "PROMOTIONAL",
                },
            },
        )
    ]
)
class RideModelListOutputSerializer(serializers.Serializer):
    """Output serializer for ride model list view."""

    id = serializers.IntegerField()
    name = serializers.CharField()
    slug = serializers.CharField()
    category = RichChoiceFieldSerializer(choice_group="categories", domain="rides")
    description = serializers.CharField()

    # Manufacturer info
    manufacturer = RideModelManufacturerOutputSerializer(allow_null=True)

    # Market info
    target_market = RichChoiceFieldSerializer(choice_group="target_markets", domain="rides")
    is_discontinued = serializers.BooleanField()
    total_installations = serializers.IntegerField()
    first_installation_year = serializers.IntegerField(allow_null=True)
    last_installation_year = serializers.IntegerField(allow_null=True)

    # Display properties
    height_range_display = serializers.CharField()
    speed_range_display = serializers.CharField()
    installation_years_range = serializers.CharField()

    # Primary image
    primary_image = RideModelPhotoOutputSerializer(allow_null=True)

    # URL
    url = serializers.SerializerMethodField()

    # Metadata
    created_at = serializers.DateTimeField()
    updated_at = serializers.DateTimeField()

    @extend_schema_field(serializers.URLField())
    def get_url(self, obj) -> str:
        """Generate the frontend URL for this ride model."""
        return f"{settings.FRONTEND_DOMAIN}/rides/manufacturers/{obj.manufacturer.slug}/{obj.slug}/"


@extend_schema_serializer(
    examples=[
        OpenApiExample(
            "Ride Model Detail Example",
            summary="Example ride model detail response",
            description="A complete ride model detail response",
            value={
                "id": 1,
                "name": "Hyper Coaster",
                "slug": "bolliger-mabillard-hyper-coaster",
                "category": "RC",
                "description": "High-speed steel roller coaster featuring airtime hills and smooth ride experience",
                "manufacturer": {
                    "id": 1,
                    "name": "Bolliger & Mabillard",
                    "slug": "bolliger-mabillard",
                },
                "typical_height_range_min_ft": 200.0,
                "typical_height_range_max_ft": 325.0,
                "typical_speed_range_min_mph": 70.0,
                "typical_speed_range_max_mph": 95.0,
                "typical_capacity_range_min": 1200,
                "typical_capacity_range_max": 1800,
                "track_type": "Tubular Steel",
                "support_structure": "Steel",
                "train_configuration": "2-3 trains, 7-9 cars per train, 4 seats per car",
                "restraint_system": "Clamshell lap bar",
                "target_market": "THRILL",
                "is_discontinued": False,
                "total_installations": 15,
                "first_installation_year": 1999,
                "notable_features": "Airtime hills, smooth ride, high capacity",
                "photos": [
                    {
                        "id": 123,
                        "image_url": "https://example.com/image.jpg",
                        "caption": "B&M Hyper Coaster",
                        "photo_type": "PROMOTIONAL",
                        "is_primary": True,
                    }
                ],
                "variants": [
                    {
                        "id": 1,
                        "name": "Mega Coaster",
                        "description": "200-299 ft height variant",
                        "min_height_ft": 200.0,
                        "max_height_ft": 299.0,
                    }
                ],
                "technical_specs": [
                    {
                        "id": 1,
                        "spec_category": "DIMENSIONS",
                        "spec_name": "Track Width",
                        "spec_value": "1435",
                        "spec_unit": "mm",
                    }
                ],
                "installations": [
                    {
                        "id": 1,
                        "name": "Nitro",
                        "park_name": "Six Flags Great Adventure",
                        "opening_date": "2001-04-07",
                    }
                ],
            },
        )
    ]
)
class RideModelDetailOutputSerializer(serializers.Serializer):
    """Output serializer for ride model detail view."""

    id = serializers.IntegerField()
    name = serializers.CharField()
    slug = serializers.CharField()
    category = serializers.CharField()
    description = serializers.CharField()

    # Manufacturer info
    manufacturer = RideModelManufacturerOutputSerializer(allow_null=True)

    # Technical specifications
    typical_height_range_min_ft = serializers.DecimalField(max_digits=6, decimal_places=2, allow_null=True)
    typical_height_range_max_ft = serializers.DecimalField(max_digits=6, decimal_places=2, allow_null=True)
    typical_speed_range_min_mph = serializers.DecimalField(max_digits=5, decimal_places=2, allow_null=True)
    typical_speed_range_max_mph = serializers.DecimalField(max_digits=5, decimal_places=2, allow_null=True)
    typical_capacity_range_min = serializers.IntegerField(allow_null=True)
    typical_capacity_range_max = serializers.IntegerField(allow_null=True)

    # Design characteristics
    track_type = serializers.CharField()
    support_structure = serializers.CharField()
    train_configuration = serializers.CharField()
    restraint_system = serializers.CharField()

    # Market information
    first_installation_year = serializers.IntegerField(allow_null=True)
    last_installation_year = serializers.IntegerField(allow_null=True)
    is_discontinued = serializers.BooleanField()
    total_installations = serializers.IntegerField()

    # Design features
    notable_features = serializers.CharField()
    target_market = serializers.CharField()

    # Display properties
    height_range_display = serializers.CharField()
    speed_range_display = serializers.CharField()
    installation_years_range = serializers.CharField()

    # SEO metadata
    meta_title = serializers.CharField()
    meta_description = serializers.CharField()

    # Related data
    photos = RideModelPhotoOutputSerializer(many=True)
    variants = RideModelVariantOutputSerializer(many=True)
    technical_specs = RideModelTechnicalSpecOutputSerializer(many=True)
    installations = serializers.SerializerMethodField()

    # URL
    url = serializers.SerializerMethodField()

    # Metadata
    created_at = serializers.DateTimeField()
    updated_at = serializers.DateTimeField()

    @extend_schema_field(serializers.URLField())
    def get_url(self, obj) -> str:
        """Generate the frontend URL for this ride model."""
        return f"{settings.FRONTEND_DOMAIN}/rides/manufacturers/{obj.manufacturer.slug}/{obj.slug}/"

    @extend_schema_field(serializers.ListField(child=serializers.DictField()))
    def get_installations(self, obj):
        """Get ride installations using this model."""
        from django.apps import apps

        Ride = apps.get_model("rides", "Ride")

        installations = Ride.objects.filter(ride_model=obj).select_related("park")[:10]
        return [
            {
                "id": ride.id,
                "name": ride.name,
                "slug": ride.slug,
                "park_name": ride.park.name,
                "park_slug": ride.park.slug,
                "opening_date": ride.opening_date,
                "status": ride.status,
            }
            for ride in installations
        ]


class RideModelCreateInputSerializer(serializers.Serializer):
    """Input serializer for creating ride models."""

    name = serializers.CharField(max_length=255)
    description = serializers.CharField(allow_blank=True, default="")
    category = serializers.ChoiceField(choices=ModelChoices.get_ride_category_choices(), allow_blank=True, default="")

    # Required manufacturer
    manufacturer_id = serializers.IntegerField()

    # Technical specifications
    typical_height_range_min_ft = serializers.DecimalField(
        max_digits=6, decimal_places=2, required=False, allow_null=True
    )
    typical_height_range_max_ft = serializers.DecimalField(
        max_digits=6, decimal_places=2, required=False, allow_null=True
    )
    typical_speed_range_min_mph = serializers.DecimalField(
        max_digits=5, decimal_places=2, required=False, allow_null=True
    )
    typical_speed_range_max_mph = serializers.DecimalField(
        max_digits=5, decimal_places=2, required=False, allow_null=True
    )
    typical_capacity_range_min = serializers.IntegerField(required=False, allow_null=True, min_value=1)
    typical_capacity_range_max = serializers.IntegerField(required=False, allow_null=True, min_value=1)

    # Design characteristics
    track_type = serializers.CharField(max_length=100, allow_blank=True, default="")
    support_structure = serializers.CharField(max_length=100, allow_blank=True, default="")
    train_configuration = serializers.CharField(max_length=200, allow_blank=True, default="")
    restraint_system = serializers.CharField(max_length=100, allow_blank=True, default="")

    # Market information
    first_installation_year = serializers.IntegerField(required=False, allow_null=True, min_value=1800, max_value=2100)
    last_installation_year = serializers.IntegerField(required=False, allow_null=True, min_value=1800, max_value=2100)
    is_discontinued = serializers.BooleanField(default=False)

    # Design features
    notable_features = serializers.CharField(allow_blank=True, default="")
    target_market = serializers.ChoiceField(
        choices=ModelChoices.get_target_market_choices(),
        required=False,
        allow_blank=True,
    )

    def validate(self, attrs):
        """Cross-field validation."""
        # Height range validation
        min_height = attrs.get("typical_height_range_min_ft")
        max_height = attrs.get("typical_height_range_max_ft")

        if min_height and max_height and min_height > max_height:
            raise serializers.ValidationError("Minimum height cannot be greater than maximum height")

        # Speed range validation
        min_speed = attrs.get("typical_speed_range_min_mph")
        max_speed = attrs.get("typical_speed_range_max_mph")

        if min_speed and max_speed and min_speed > max_speed:
            raise serializers.ValidationError("Minimum speed cannot be greater than maximum speed")

        # Capacity range validation
        min_capacity = attrs.get("typical_capacity_range_min")
        max_capacity = attrs.get("typical_capacity_range_max")

        if min_capacity and max_capacity and min_capacity > max_capacity:
            raise serializers.ValidationError("Minimum capacity cannot be greater than maximum capacity")

        # Installation years validation
        first_year = attrs.get("first_installation_year")
        last_year = attrs.get("last_installation_year")

        if first_year and last_year and first_year > last_year:
            raise serializers.ValidationError("First installation year cannot be after last installation year")

        return attrs


class RideModelUpdateInputSerializer(serializers.Serializer):
    """Input serializer for updating ride models."""

    name = serializers.CharField(max_length=255, required=False)
    description = serializers.CharField(allow_blank=True, required=False)
    category = serializers.ChoiceField(
        choices=ModelChoices.get_ride_category_choices(),
        allow_blank=True,
        required=False,
    )

    # Manufacturer
    manufacturer_id = serializers.IntegerField(required=False)

    # Technical specifications
    typical_height_range_min_ft = serializers.DecimalField(
        max_digits=6, decimal_places=2, required=False, allow_null=True
    )
    typical_height_range_max_ft = serializers.DecimalField(
        max_digits=6, decimal_places=2, required=False, allow_null=True
    )
    typical_speed_range_min_mph = serializers.DecimalField(
        max_digits=5, decimal_places=2, required=False, allow_null=True
    )
    typical_speed_range_max_mph = serializers.DecimalField(
        max_digits=5, decimal_places=2, required=False, allow_null=True
    )
    typical_capacity_range_min = serializers.IntegerField(required=False, allow_null=True, min_value=1)
    typical_capacity_range_max = serializers.IntegerField(required=False, allow_null=True, min_value=1)

    # Design characteristics
    track_type = serializers.CharField(max_length=100, allow_blank=True, required=False)
    support_structure = serializers.CharField(max_length=100, allow_blank=True, required=False)
    train_configuration = serializers.CharField(max_length=200, allow_blank=True, required=False)
    restraint_system = serializers.CharField(max_length=100, allow_blank=True, required=False)

    # Market information
    first_installation_year = serializers.IntegerField(required=False, allow_null=True, min_value=1800, max_value=2100)
    last_installation_year = serializers.IntegerField(required=False, allow_null=True, min_value=1800, max_value=2100)
    is_discontinued = serializers.BooleanField(required=False)

    # Design features
    notable_features = serializers.CharField(allow_blank=True, required=False)
    target_market = serializers.ChoiceField(
        choices=ModelChoices.get_target_market_choices(),
        allow_blank=True,
        required=False,
    )

    def validate(self, attrs):
        """Cross-field validation."""
        # Height range validation
        min_height = attrs.get("typical_height_range_min_ft")
        max_height = attrs.get("typical_height_range_max_ft")

        if min_height and max_height and min_height > max_height:
            raise serializers.ValidationError("Minimum height cannot be greater than maximum height")

        # Speed range validation
        min_speed = attrs.get("typical_speed_range_min_mph")
        max_speed = attrs.get("typical_speed_range_max_mph")

        if min_speed and max_speed and min_speed > max_speed:
            raise serializers.ValidationError("Minimum speed cannot be greater than maximum speed")

        # Capacity range validation
        min_capacity = attrs.get("typical_capacity_range_min")
        max_capacity = attrs.get("typical_capacity_range_max")

        if min_capacity and max_capacity and min_capacity > max_capacity:
            raise serializers.ValidationError("Minimum capacity cannot be greater than maximum capacity")

        # Installation years validation
        first_year = attrs.get("first_installation_year")
        last_year = attrs.get("last_installation_year")

        if first_year and last_year and first_year > last_year:
            raise serializers.ValidationError("First installation year cannot be after last installation year")

        return attrs


class RideModelFilterInputSerializer(serializers.Serializer):
    """Input serializer for ride model filtering and search."""

    # Search
    search = serializers.CharField(required=False, allow_blank=True)

    # Category filter
    category = serializers.MultipleChoiceField(choices=ModelChoices.get_ride_category_choices(), required=False)

    # Manufacturer filter
    manufacturer_id = serializers.IntegerField(required=False)
    manufacturer_slug = serializers.CharField(required=False, allow_blank=True)

    # Market filter
    target_market = serializers.MultipleChoiceField(
        choices=ModelChoices.get_target_market_choices(),
        required=False,
    )

    # Status filter
    is_discontinued = serializers.BooleanField(required=False)

    # Year filters
    first_installation_year_min = serializers.IntegerField(required=False)
    first_installation_year_max = serializers.IntegerField(required=False)

    # Installation count filter
    min_installations = serializers.IntegerField(required=False, min_value=0)

    # Height filters
    min_height_ft = serializers.DecimalField(max_digits=6, decimal_places=2, required=False)
    max_height_ft = serializers.DecimalField(max_digits=6, decimal_places=2, required=False)

    # Speed filters
    min_speed_mph = serializers.DecimalField(max_digits=5, decimal_places=2, required=False)
    max_speed_mph = serializers.DecimalField(max_digits=5, decimal_places=2, required=False)

    # Ordering
    ordering = serializers.ChoiceField(
        choices=[
            "name",
            "-name",
            "manufacturer__name",
            "-manufacturer__name",
            "first_installation_year",
            "-first_installation_year",
            "total_installations",
            "-total_installations",
            "created_at",
            "-created_at",
        ],
        required=False,
        default="manufacturer__name,name",
    )


# === RIDE MODEL VARIANT SERIALIZERS ===


class RideModelVariantCreateInputSerializer(serializers.Serializer):
    """Input serializer for creating ride model variants."""

    ride_model_id = serializers.IntegerField()
    name = serializers.CharField(max_length=255)
    description = serializers.CharField(allow_blank=True, default="")

    # Variant-specific specifications
    min_height_ft = serializers.DecimalField(max_digits=6, decimal_places=2, required=False, allow_null=True)
    max_height_ft = serializers.DecimalField(max_digits=6, decimal_places=2, required=False, allow_null=True)
    min_speed_mph = serializers.DecimalField(max_digits=5, decimal_places=2, required=False, allow_null=True)
    max_speed_mph = serializers.DecimalField(max_digits=5, decimal_places=2, required=False, allow_null=True)

    # Distinguishing features
    distinguishing_features = serializers.CharField(allow_blank=True, default="")

    def validate(self, attrs):
        """Cross-field validation."""
        # Height range validation
        min_height = attrs.get("min_height_ft")
        max_height = attrs.get("max_height_ft")

        if min_height and max_height and min_height > max_height:
            raise serializers.ValidationError("Minimum height cannot be greater than maximum height")

        # Speed range validation
        min_speed = attrs.get("min_speed_mph")
        max_speed = attrs.get("max_speed_mph")

        if min_speed and max_speed and min_speed > max_speed:
            raise serializers.ValidationError("Minimum speed cannot be greater than maximum speed")

        return attrs


class RideModelVariantUpdateInputSerializer(serializers.Serializer):
    """Input serializer for updating ride model variants."""

    name = serializers.CharField(max_length=255, required=False)
    description = serializers.CharField(allow_blank=True, required=False)

    # Variant-specific specifications
    min_height_ft = serializers.DecimalField(max_digits=6, decimal_places=2, required=False, allow_null=True)
    max_height_ft = serializers.DecimalField(max_digits=6, decimal_places=2, required=False, allow_null=True)
    min_speed_mph = serializers.DecimalField(max_digits=5, decimal_places=2, required=False, allow_null=True)
    max_speed_mph = serializers.DecimalField(max_digits=5, decimal_places=2, required=False, allow_null=True)

    # Distinguishing features
    distinguishing_features = serializers.CharField(allow_blank=True, required=False)

    def validate(self, attrs):
        """Cross-field validation."""
        # Height range validation
        min_height = attrs.get("min_height_ft")
        max_height = attrs.get("max_height_ft")

        if min_height and max_height and min_height > max_height:
            raise serializers.ValidationError("Minimum height cannot be greater than maximum height")

        # Speed range validation
        min_speed = attrs.get("min_speed_mph")
        max_speed = attrs.get("max_speed_mph")

        if min_speed and max_speed and min_speed > max_speed:
            raise serializers.ValidationError("Minimum speed cannot be greater than maximum speed")

        return attrs


# === RIDE MODEL TECHNICAL SPEC SERIALIZERS ===


class RideModelTechnicalSpecCreateInputSerializer(serializers.Serializer):
    """Input serializer for creating ride model technical specifications."""

    ride_model_id = serializers.IntegerField()
    spec_category = serializers.ChoiceField(choices=ModelChoices.get_technical_spec_category_choices())
    spec_name = serializers.CharField(max_length=100)
    spec_value = serializers.CharField(max_length=255)
    spec_unit = serializers.CharField(max_length=20, allow_blank=True, default="")
    notes = serializers.CharField(allow_blank=True, default="")


class RideModelTechnicalSpecUpdateInputSerializer(serializers.Serializer):
    """Input serializer for updating ride model technical specifications."""

    spec_category = serializers.ChoiceField(
        choices=ModelChoices.get_technical_spec_category_choices(),
        required=False,
    )
    spec_name = serializers.CharField(max_length=100, required=False)
    spec_value = serializers.CharField(max_length=255, required=False)
    spec_unit = serializers.CharField(max_length=20, allow_blank=True, required=False)
    notes = serializers.CharField(allow_blank=True, required=False)


# === RIDE MODEL PHOTO SERIALIZERS ===


class RideModelPhotoCreateInputSerializer(serializers.Serializer):
    """Input serializer for creating ride model photos."""

    ride_model_id = serializers.IntegerField()
    image = serializers.ImageField()
    caption = serializers.CharField(max_length=500, allow_blank=True, default="")
    alt_text = serializers.CharField(max_length=255, allow_blank=True, default="")
    photo_type = serializers.ChoiceField(
        choices=ModelChoices.get_photo_type_choices(),
        default="PROMOTIONAL",
    )
    is_primary = serializers.BooleanField(default=False)
    photographer = serializers.CharField(max_length=255, allow_blank=True, default="")
    source = serializers.CharField(max_length=255, allow_blank=True, default="")
    copyright_info = serializers.CharField(max_length=255, allow_blank=True, default="")


class RideModelPhotoUpdateInputSerializer(serializers.Serializer):
    """Input serializer for updating ride model photos."""

    caption = serializers.CharField(max_length=500, allow_blank=True, required=False)
    alt_text = serializers.CharField(max_length=255, allow_blank=True, required=False)
    photo_type = serializers.ChoiceField(
        choices=ModelChoices.get_photo_type_choices(),
        required=False,
    )
    is_primary = serializers.BooleanField(required=False)
    photographer = serializers.CharField(max_length=255, allow_blank=True, required=False)
    source = serializers.CharField(max_length=255, allow_blank=True, required=False)
    copyright_info = serializers.CharField(max_length=255, allow_blank=True, required=False)


# === RIDE MODEL STATS SERIALIZERS ===


class RideModelStatsOutputSerializer(serializers.Serializer):
    """Output serializer for ride model statistics."""

    total_models = serializers.IntegerField()
    total_installations = serializers.IntegerField()
    active_manufacturers = serializers.IntegerField()
    discontinued_models = serializers.IntegerField()
    by_category = serializers.DictField(child=serializers.IntegerField(), help_text="Model counts by category")
    by_target_market = serializers.DictField(
        child=serializers.IntegerField(), help_text="Model counts by target market"
    )
    by_manufacturer = serializers.DictField(child=serializers.IntegerField(), help_text="Model counts by manufacturer")
    recent_models = serializers.IntegerField(help_text="Models created in the last 30 days")
