"""
Parks domain serializers for ThrillWiki API v1.

This module contains all serializers related to parks, park areas, park locations,
and park search 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 apps.core.services.media_url_service import MediaURLService
from config.django import base as settings

from .shared import CompanyOutputSerializer, LocationOutputSerializer, ModelChoices

# === PARK SERIALIZERS ===


@extend_schema_serializer(
    examples=[
        OpenApiExample(
            "Park List Example",
            summary="Example park list response",
            description="A typical park in the list view",
            value={
                "id": 1,
                "name": "Cedar Point",
                "slug": "cedar-point",
                "status": "OPERATING",
                "description": "America's Roller Coast",
                "average_rating": 4.5,
                "coaster_count": 17,
                "ride_count": 70,
                "location": {
                    "city": "Sandusky",
                    "state": "Ohio",
                    "country": "United States",
                },
                "operator": {"id": 1, "name": "Cedar Fair", "slug": "cedar-fair"},
            },
        )
    ]
)
class ParkListOutputSerializer(serializers.Serializer):
    """Output serializer for park list view."""

    id = serializers.IntegerField()
    name = serializers.CharField()
    slug = serializers.CharField()
    status = RichChoiceFieldSerializer(choice_group="statuses", domain="parks")
    description = serializers.CharField()

    # Statistics
    average_rating = serializers.DecimalField(max_digits=3, decimal_places=2, allow_null=True)
    coaster_count = serializers.IntegerField(allow_null=True)
    ride_count = serializers.IntegerField(allow_null=True)

    # Location (simplified for list view)
    location = LocationOutputSerializer(allow_null=True)

    # Operator info
    operator = CompanyOutputSerializer()

    # 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 park."""
        return f"{settings.FRONTEND_DOMAIN}/parks/{obj.slug}/"


@extend_schema_serializer(
    examples=[
        OpenApiExample(
            "Park Detail Example",
            summary="Example park detail response",
            description="A complete park detail response",
            value={
                "id": 1,
                "name": "Cedar Point",
                "slug": "cedar-point",
                "status": "OPERATING",
                "description": "America's Roller Coast",
                "opening_date": "1870-01-01",
                "website": "https://cedarpoint.com",
                "size_acres": 364.0,
                "average_rating": 4.5,
                "coaster_count": 17,
                "ride_count": 70,
                "location": {
                    "latitude": 41.4793,
                    "longitude": -82.6833,
                    "city": "Sandusky",
                    "state": "Ohio",
                    "country": "United States",
                },
                "operator": {"id": 1, "name": "Cedar Fair", "slug": "cedar-fair"},
                "photos": [
                    {
                        "id": 456,
                        "image_url": "https://imagedelivery.net/account-hash/def789ghi012/public",
                        "image_variants": {
                            "thumbnail": "https://imagedelivery.net/account-hash/def789ghi012/thumbnail",
                            "medium": "https://imagedelivery.net/account-hash/def789ghi012/medium",
                            "large": "https://imagedelivery.net/account-hash/def789ghi012/large",
                            "public": "https://imagedelivery.net/account-hash/def789ghi012/public",
                        },
                        "caption": "Beautiful park entrance",
                        "is_primary": True,
                    }
                ],
                "primary_photo": {
                    "id": 456,
                    "image_url": "https://imagedelivery.net/account-hash/def789ghi012/public",
                    "image_variants": {
                        "thumbnail": "https://imagedelivery.net/account-hash/def789ghi012/thumbnail",
                        "medium": "https://imagedelivery.net/account-hash/def789ghi012/medium",
                        "large": "https://imagedelivery.net/account-hash/def789ghi012/large",
                        "public": "https://imagedelivery.net/account-hash/def789ghi012/public",
                    },
                    "caption": "Beautiful park entrance",
                },
            },
        )
    ]
)
class ParkDetailOutputSerializer(serializers.Serializer):
    """Output serializer for park detail view."""

    id = serializers.IntegerField()
    name = serializers.CharField()
    slug = serializers.CharField()
    status = RichChoiceFieldSerializer(choice_group="statuses", domain="parks")
    description = serializers.CharField()

    # Details
    opening_date = serializers.DateField(allow_null=True)
    closing_date = serializers.DateField(allow_null=True)
    operating_season = serializers.CharField()
    size_acres = serializers.DecimalField(max_digits=10, decimal_places=2, allow_null=True)
    website = serializers.URLField()

    # Statistics
    average_rating = serializers.DecimalField(max_digits=3, decimal_places=2, allow_null=True)
    coaster_count = serializers.IntegerField(allow_null=True)
    ride_count = serializers.IntegerField(allow_null=True)

    # Location (full details)
    location = LocationOutputSerializer(allow_null=True)

    # Companies
    operator = CompanyOutputSerializer()
    property_owner = CompanyOutputSerializer(allow_null=True)

    # Areas
    areas = serializers.SerializerMethodField()

    # Photos
    photos = serializers.SerializerMethodField()
    primary_photo = serializers.SerializerMethodField()
    banner_image = serializers.SerializerMethodField()
    card_image = serializers.SerializerMethodField()

    # URL
    url = serializers.SerializerMethodField()

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

    @extend_schema_field(serializers.ListField(child=serializers.DictField()))
    def get_areas(self, obj):
        """Get simplified area information."""
        if hasattr(obj, "areas"):
            return [
                {
                    "id": area.id,
                    "name": area.name,
                    "slug": area.slug,
                    "description": area.description,
                }
                for area in obj.areas.all()
            ]
        return []

    @extend_schema_field(serializers.ListField(child=serializers.DictField()))
    def get_photos(self, obj):
        """Get all approved photos for this park."""
        from apps.parks.models import ParkPhoto

        photos = ParkPhoto.objects.filter(park=obj, is_approved=True).order_by("-is_primary", "-created_at")[
            :10
        ]  # Limit to 10 photos

        return [
            {
                "id": photo.pk,
                "image_url": MediaURLService.get_cloudflare_url_with_fallback(photo.image, "public"),
                "image_variants": {
                    "thumbnail": MediaURLService.get_cloudflare_url_with_fallback(photo.image, "thumbnail"),
                    "medium": MediaURLService.get_cloudflare_url_with_fallback(photo.image, "medium"),
                    "large": MediaURLService.get_cloudflare_url_with_fallback(photo.image, "large"),
                    "public": MediaURLService.get_cloudflare_url_with_fallback(photo.image, "public"),
                },
                "friendly_urls": {
                    "thumbnail": MediaURLService.generate_park_photo_url(
                        obj.slug, photo.caption, photo.pk, "thumbnail"
                    ),
                    "medium": MediaURLService.generate_park_photo_url(obj.slug, photo.caption, photo.pk, "medium"),
                    "large": MediaURLService.generate_park_photo_url(obj.slug, photo.caption, photo.pk, "large"),
                    "public": MediaURLService.generate_park_photo_url(obj.slug, photo.caption, photo.pk, "public"),
                },
                "caption": photo.caption,
                "alt_text": photo.alt_text,
                "is_primary": photo.is_primary,
            }
            for photo in photos
        ]

    @extend_schema_field(serializers.DictField(allow_null=True))
    def get_primary_photo(self, obj):
        """Get the primary photo for this park."""
        from apps.parks.models import ParkPhoto

        try:
            photo = ParkPhoto.objects.filter(park=obj, is_primary=True, is_approved=True).first()

            if photo and photo.image:
                return {
                    "id": photo.pk,
                    "image_url": MediaURLService.get_cloudflare_url_with_fallback(photo.image, "public"),
                    "image_variants": {
                        "thumbnail": MediaURLService.get_cloudflare_url_with_fallback(photo.image, "thumbnail"),
                        "medium": MediaURLService.get_cloudflare_url_with_fallback(photo.image, "medium"),
                        "large": MediaURLService.get_cloudflare_url_with_fallback(photo.image, "large"),
                        "public": MediaURLService.get_cloudflare_url_with_fallback(photo.image, "public"),
                    },
                    "friendly_urls": {
                        "thumbnail": MediaURLService.generate_park_photo_url(
                            obj.slug, photo.caption, photo.pk, "thumbnail"
                        ),
                        "medium": MediaURLService.generate_park_photo_url(obj.slug, photo.caption, photo.pk, "medium"),
                        "large": MediaURLService.generate_park_photo_url(obj.slug, photo.caption, photo.pk, "large"),
                        "public": MediaURLService.generate_park_photo_url(obj.slug, photo.caption, photo.pk, "public"),
                    },
                    "caption": photo.caption,
                    "alt_text": photo.alt_text,
                }
        except Exception:
            pass

        return None

    @extend_schema_field(serializers.DictField(allow_null=True))
    def get_banner_image(self, obj):
        """Get the banner image for this park with fallback to latest photo."""
        # First try the explicitly set banner image
        if obj.banner_image and obj.banner_image.image:
            return {
                "id": obj.banner_image.pk,
                "image_url": MediaURLService.get_cloudflare_url_with_fallback(obj.banner_image.image, "public"),
                "image_variants": {
                    "thumbnail": MediaURLService.get_cloudflare_url_with_fallback(obj.banner_image.image, "thumbnail"),
                    "medium": MediaURLService.get_cloudflare_url_with_fallback(obj.banner_image.image, "medium"),
                    "large": MediaURLService.get_cloudflare_url_with_fallback(obj.banner_image.image, "large"),
                    "public": MediaURLService.get_cloudflare_url_with_fallback(obj.banner_image.image, "public"),
                },
                "friendly_urls": {
                    "thumbnail": MediaURLService.generate_park_photo_url(
                        obj.slug, obj.banner_image.caption, obj.banner_image.pk, "thumbnail"
                    ),
                    "medium": MediaURLService.generate_park_photo_url(
                        obj.slug, obj.banner_image.caption, obj.banner_image.pk, "medium"
                    ),
                    "large": MediaURLService.generate_park_photo_url(
                        obj.slug, obj.banner_image.caption, obj.banner_image.pk, "large"
                    ),
                    "public": MediaURLService.generate_park_photo_url(
                        obj.slug, obj.banner_image.caption, obj.banner_image.pk, "public"
                    ),
                },
                "caption": obj.banner_image.caption,
                "alt_text": obj.banner_image.alt_text,
            }

        # Fallback to latest approved photo
        from apps.parks.models import ParkPhoto

        try:
            latest_photo = (
                ParkPhoto.objects.filter(park=obj, is_approved=True, image__isnull=False)
                .order_by("-created_at")
                .first()
            )

            if latest_photo and latest_photo.image:
                return {
                    "id": latest_photo.pk,
                    "image_url": MediaURLService.get_cloudflare_url_with_fallback(latest_photo.image, "public"),
                    "image_variants": {
                        "thumbnail": MediaURLService.get_cloudflare_url_with_fallback(latest_photo.image, "thumbnail"),
                        "medium": MediaURLService.get_cloudflare_url_with_fallback(latest_photo.image, "medium"),
                        "large": MediaURLService.get_cloudflare_url_with_fallback(latest_photo.image, "large"),
                        "public": MediaURLService.get_cloudflare_url_with_fallback(latest_photo.image, "public"),
                    },
                    "friendly_urls": {
                        "thumbnail": MediaURLService.generate_park_photo_url(
                            obj.slug, latest_photo.caption, latest_photo.pk, "thumbnail"
                        ),
                        "medium": MediaURLService.generate_park_photo_url(
                            obj.slug, latest_photo.caption, latest_photo.pk, "medium"
                        ),
                        "large": MediaURLService.generate_park_photo_url(
                            obj.slug, latest_photo.caption, latest_photo.pk, "large"
                        ),
                        "public": MediaURLService.generate_park_photo_url(
                            obj.slug, latest_photo.caption, latest_photo.pk, "public"
                        ),
                    },
                    "caption": latest_photo.caption,
                    "alt_text": latest_photo.alt_text,
                    "is_fallback": True,
                }
        except Exception:
            pass

        return None

    @extend_schema_field(serializers.DictField(allow_null=True))
    def get_card_image(self, obj):
        """Get the card image for this park with fallback to latest photo."""
        # First try the explicitly set card image
        if obj.card_image and obj.card_image.image:
            return {
                "id": obj.card_image.pk,
                "image_url": MediaURLService.get_cloudflare_url_with_fallback(obj.card_image.image, "public"),
                "image_variants": {
                    "thumbnail": MediaURLService.get_cloudflare_url_with_fallback(obj.card_image.image, "thumbnail"),
                    "medium": MediaURLService.get_cloudflare_url_with_fallback(obj.card_image.image, "medium"),
                    "large": MediaURLService.get_cloudflare_url_with_fallback(obj.card_image.image, "large"),
                    "public": MediaURLService.get_cloudflare_url_with_fallback(obj.card_image.image, "public"),
                },
                "friendly_urls": {
                    "thumbnail": MediaURLService.generate_park_photo_url(
                        obj.slug, obj.card_image.caption, obj.card_image.pk, "thumbnail"
                    ),
                    "medium": MediaURLService.generate_park_photo_url(
                        obj.slug, obj.card_image.caption, obj.card_image.pk, "medium"
                    ),
                    "large": MediaURLService.generate_park_photo_url(
                        obj.slug, obj.card_image.caption, obj.card_image.pk, "large"
                    ),
                    "public": MediaURLService.generate_park_photo_url(
                        obj.slug, obj.card_image.caption, obj.card_image.pk, "public"
                    ),
                },
                "caption": obj.card_image.caption,
                "alt_text": obj.card_image.alt_text,
            }

        # Fallback to latest approved photo
        from apps.parks.models import ParkPhoto

        try:
            latest_photo = (
                ParkPhoto.objects.filter(park=obj, is_approved=True, image__isnull=False)
                .order_by("-created_at")
                .first()
            )

            if latest_photo and latest_photo.image:
                return {
                    "id": latest_photo.pk,
                    "image_url": MediaURLService.get_cloudflare_url_with_fallback(latest_photo.image, "public"),
                    "image_variants": {
                        "thumbnail": MediaURLService.get_cloudflare_url_with_fallback(latest_photo.image, "thumbnail"),
                        "medium": MediaURLService.get_cloudflare_url_with_fallback(latest_photo.image, "medium"),
                        "large": MediaURLService.get_cloudflare_url_with_fallback(latest_photo.image, "large"),
                        "public": MediaURLService.get_cloudflare_url_with_fallback(latest_photo.image, "public"),
                    },
                    "friendly_urls": {
                        "thumbnail": MediaURLService.generate_park_photo_url(
                            obj.slug, latest_photo.caption, latest_photo.pk, "thumbnail"
                        ),
                        "medium": MediaURLService.generate_park_photo_url(
                            obj.slug, latest_photo.caption, latest_photo.pk, "medium"
                        ),
                        "large": MediaURLService.generate_park_photo_url(
                            obj.slug, latest_photo.caption, latest_photo.pk, "large"
                        ),
                        "public": MediaURLService.generate_park_photo_url(
                            obj.slug, latest_photo.caption, latest_photo.pk, "public"
                        ),
                    },
                    "caption": latest_photo.caption,
                    "alt_text": latest_photo.alt_text,
                    "is_fallback": True,
                }
        except Exception:
            pass

        return None

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


class ParkImageSettingsInputSerializer(serializers.Serializer):
    """Input serializer for setting park banner and card images."""

    banner_image_id = serializers.IntegerField(required=False, allow_null=True)
    card_image_id = serializers.IntegerField(required=False, allow_null=True)

    def validate_banner_image_id(self, value):
        """Validate that the banner image belongs to the same park."""
        if value is not None:
            from apps.parks.models import ParkPhoto

            try:
                ParkPhoto.objects.get(id=value)
                # The park will be validated in the view
                return value
            except ParkPhoto.DoesNotExist:
                raise serializers.ValidationError("Photo not found") from None
        return value

    def validate_card_image_id(self, value):
        """Validate that the card image belongs to the same park."""
        if value is not None:
            from apps.parks.models import ParkPhoto

            try:
                ParkPhoto.objects.get(id=value)
                # The park will be validated in the view
                return value
            except ParkPhoto.DoesNotExist:
                raise serializers.ValidationError("Photo not found") from None
        return value


class ParkCreateInputSerializer(serializers.Serializer):
    """Input serializer for creating parks."""

    name = serializers.CharField(max_length=255)
    description = serializers.CharField(allow_blank=True, default="")
    status = serializers.ChoiceField(choices=ModelChoices.get_park_status_choices(), default="OPERATING")

    # Optional details
    opening_date = serializers.DateField(required=False, allow_null=True)
    closing_date = serializers.DateField(required=False, allow_null=True)
    operating_season = serializers.CharField(max_length=255, required=False, allow_blank=True)
    size_acres = serializers.DecimalField(max_digits=10, decimal_places=2, required=False, allow_null=True)
    website = serializers.URLField(required=False, allow_blank=True)

    # Required operator
    operator_id = serializers.IntegerField()

    # Optional property owner
    property_owner_id = serializers.IntegerField(required=False, allow_null=True)

    def validate(self, attrs):
        """Cross-field validation."""
        opening_date = attrs.get("opening_date")
        closing_date = attrs.get("closing_date")

        if opening_date and closing_date and closing_date < opening_date:
            raise serializers.ValidationError("Closing date cannot be before opening date")

        return attrs


class ParkUpdateInputSerializer(serializers.Serializer):
    """Input serializer for updating parks."""

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

    # Optional details
    opening_date = serializers.DateField(required=False, allow_null=True)
    closing_date = serializers.DateField(required=False, allow_null=True)
    operating_season = serializers.CharField(max_length=255, required=False, allow_blank=True)
    size_acres = serializers.DecimalField(max_digits=10, decimal_places=2, required=False, allow_null=True)
    website = serializers.URLField(required=False, allow_blank=True)

    # Companies
    operator_id = serializers.IntegerField(required=False)
    property_owner_id = serializers.IntegerField(required=False, allow_null=True)

    def validate(self, attrs):
        """Cross-field validation."""
        opening_date = attrs.get("opening_date")
        closing_date = attrs.get("closing_date")

        if opening_date and closing_date and closing_date < opening_date:
            raise serializers.ValidationError("Closing date cannot be before opening date")

        return attrs


class ParkFilterInputSerializer(serializers.Serializer):
    """Input serializer for park filtering and search."""

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

    # Status filter
    status = serializers.MultipleChoiceField(
        choices=[],
        required=False,  # Choices set dynamically
    )

    # Location filters
    country = serializers.CharField(required=False, allow_blank=True)
    state = serializers.CharField(required=False, allow_blank=True)
    city = serializers.CharField(required=False, allow_blank=True)

    # Rating filter
    min_rating = serializers.DecimalField(
        max_digits=3,
        decimal_places=2,
        required=False,
        min_value=1,
        max_value=10,
    )

    # Size filter
    min_size_acres = serializers.DecimalField(max_digits=10, decimal_places=2, required=False, min_value=0)
    max_size_acres = serializers.DecimalField(max_digits=10, decimal_places=2, required=False, min_value=0)

    # Company filters
    operator_id = serializers.IntegerField(required=False)
    property_owner_id = serializers.IntegerField(required=False)

    # Ordering
    ordering = serializers.ChoiceField(
        choices=[
            "name",
            "-name",
            "opening_date",
            "-opening_date",
            "average_rating",
            "-average_rating",
            "coaster_count",
            "-coaster_count",
            "created_at",
            "-created_at",
        ],
        required=False,
        default="name",
    )


# === PARK AREA SERIALIZERS ===


@extend_schema_serializer(
    examples=[
        OpenApiExample(
            "Park Area Example",
            summary="Example park area response",
            description="A themed area within a park",
            value={
                "id": 1,
                "name": "Tomorrowland",
                "slug": "tomorrowland",
                "description": "A futuristic themed area",
                "park": {"id": 1, "name": "Magic Kingdom", "slug": "magic-kingdom"},
                "opening_date": "1971-10-01",
                "closing_date": None,
            },
        )
    ]
)
class ParkAreaDetailOutputSerializer(serializers.Serializer):
    """Output serializer for park areas."""

    id = serializers.IntegerField()
    name = serializers.CharField()
    slug = serializers.CharField()
    description = serializers.CharField()
    opening_date = serializers.DateField(allow_null=True)
    closing_date = serializers.DateField(allow_null=True)

    # Park info
    park = serializers.SerializerMethodField()

    @extend_schema_field(serializers.DictField())
    def get_park(self, obj) -> dict:
        return {
            "id": obj.park.id,
            "name": obj.park.name,
            "slug": obj.park.slug,
        }


class ParkAreaCreateInputSerializer(serializers.Serializer):
    """Input serializer for creating park areas."""

    name = serializers.CharField(max_length=255)
    description = serializers.CharField(allow_blank=True, default="")
    park_id = serializers.IntegerField()
    opening_date = serializers.DateField(required=False, allow_null=True)
    closing_date = serializers.DateField(required=False, allow_null=True)

    def validate(self, attrs):
        """Cross-field validation."""
        opening_date = attrs.get("opening_date")
        closing_date = attrs.get("closing_date")

        if opening_date and closing_date and closing_date < opening_date:
            raise serializers.ValidationError("Closing date cannot be before opening date")

        return attrs


class ParkAreaUpdateInputSerializer(serializers.Serializer):
    """Input serializer for updating park areas."""

    name = serializers.CharField(max_length=255, required=False)
    description = serializers.CharField(allow_blank=True, required=False)
    opening_date = serializers.DateField(required=False, allow_null=True)
    closing_date = serializers.DateField(required=False, allow_null=True)

    def validate(self, attrs):
        """Cross-field validation."""
        opening_date = attrs.get("opening_date")
        closing_date = attrs.get("closing_date")

        if opening_date and closing_date and closing_date < opening_date:
            raise serializers.ValidationError("Closing date cannot be before opening date")

        return attrs


# === PARK LOCATION SERIALIZERS ===


class ParkLocationOutputSerializer(serializers.Serializer):
    """Output serializer for park locations."""

    id = serializers.IntegerField()
    latitude = serializers.FloatField(allow_null=True)
    longitude = serializers.FloatField(allow_null=True)
    address = serializers.CharField()
    city = serializers.CharField()
    state = serializers.CharField()
    country = serializers.CharField()
    postal_code = serializers.CharField()
    formatted_address = serializers.CharField()

    # Park info
    park = serializers.SerializerMethodField()

    @extend_schema_field(serializers.DictField())
    def get_park(self, obj) -> dict:
        return {
            "id": obj.park.id,
            "name": obj.park.name,
            "slug": obj.park.slug,
        }


class ParkLocationCreateInputSerializer(serializers.Serializer):
    """Input serializer for creating park locations."""

    park_id = serializers.IntegerField()
    latitude = serializers.FloatField(required=False, allow_null=True)
    longitude = serializers.FloatField(required=False, allow_null=True)
    address = serializers.CharField(max_length=255, allow_blank=True, default="")
    city = serializers.CharField(max_length=100)
    state = serializers.CharField(max_length=100)
    country = serializers.CharField(max_length=100)
    postal_code = serializers.CharField(max_length=20, allow_blank=True, default="")


class ParkLocationUpdateInputSerializer(serializers.Serializer):
    """Input serializer for updating park locations."""

    latitude = serializers.FloatField(required=False, allow_null=True)
    longitude = serializers.FloatField(required=False, allow_null=True)
    address = serializers.CharField(max_length=255, allow_blank=True, required=False)
    city = serializers.CharField(max_length=100, required=False)
    state = serializers.CharField(max_length=100, required=False)
    country = serializers.CharField(max_length=100, required=False)
    postal_code = serializers.CharField(max_length=20, allow_blank=True, required=False)


# === PARKS SEARCH SERIALIZERS ===


class ParkSuggestionSerializer(serializers.Serializer):
    """Serializer for park search suggestions."""

    id = serializers.IntegerField()
    name = serializers.CharField()
    slug = serializers.CharField()
    location = serializers.CharField()
    status = serializers.CharField()
    coaster_count = serializers.IntegerField()


class ParkSuggestionOutputSerializer(serializers.Serializer):
    """Output serializer for park suggestions."""

    results = ParkSuggestionSerializer(many=True)
    query = serializers.CharField()
    count = serializers.IntegerField()
