"""
API serializers for the ride ranking system.
"""

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

from apps.rides.models import RankingSnapshot, RideRanking


@extend_schema_serializer(
    examples=[
        OpenApiExample(
            "Ride Ranking Example",
            summary="Example ranking response",
            description="A ride ranking with all metrics",
            value={
                "id": 1,
                "rank": 1,
                "ride": {
                    "id": 123,
                    "name": "Steel Vengeance",
                    "slug": "steel-vengeance",
                    "park": {"id": 45, "name": "Cedar Point", "slug": "cedar-point"},
                    "category": "RC",
                },
                "wins": 523,
                "losses": 87,
                "ties": 45,
                "winning_percentage": 0.8234,
                "mutual_riders_count": 1250,
                "comparison_count": 655,
                "average_rating": 9.2,
                "last_calculated": "2024-01-15T02:00:00Z",
                "rank_change": 2,
                "previous_rank": 3,
            },
        )
    ]
)
class RideRankingSerializer(serializers.ModelSerializer):
    """Serializer for ride rankings."""

    ride = serializers.SerializerMethodField()
    rank_change = serializers.SerializerMethodField()
    previous_rank = serializers.SerializerMethodField()

    class Meta:
        model = RideRanking
        fields = [
            "id",
            "rank",
            "ride",
            "wins",
            "losses",
            "ties",
            "winning_percentage",
            "mutual_riders_count",
            "comparison_count",
            "average_rating",
            "last_calculated",
            "rank_change",
            "previous_rank",
        ]

    @extend_schema_field(serializers.DictField())
    def get_ride(self, obj):
        """Get ride details."""
        return {
            "id": obj.ride.id,
            "name": obj.ride.name,
            "slug": obj.ride.slug,
            "park": {
                "id": obj.ride.park.id,
                "name": obj.ride.park.name,
                "slug": obj.ride.park.slug,
            },
            "category": obj.ride.category,
        }

    @extend_schema_field(serializers.IntegerField(allow_null=True))
    def get_rank_change(self, obj):
        """Calculate rank change from previous snapshot."""
        from apps.rides.models import RankingSnapshot

        latest_snapshots = RankingSnapshot.objects.filter(ride=obj.ride).order_by("-snapshot_date")[:2]

        if len(latest_snapshots) >= 2:
            return latest_snapshots[0].rank - latest_snapshots[1].rank
        return None

    @extend_schema_field(serializers.IntegerField(allow_null=True))
    def get_previous_rank(self, obj):
        """Get previous rank."""
        from apps.rides.models import RankingSnapshot

        latest_snapshots = RankingSnapshot.objects.filter(ride=obj.ride).order_by("-snapshot_date")[:2]

        if len(latest_snapshots) >= 2:
            return latest_snapshots[1].rank
        return None


class RideRankingDetailSerializer(serializers.ModelSerializer):
    """Detailed serializer for a specific ride's ranking."""

    ride = serializers.SerializerMethodField()
    head_to_head_comparisons = serializers.SerializerMethodField()
    ranking_history = serializers.SerializerMethodField()

    class Meta:
        model = RideRanking
        fields = [
            "id",
            "rank",
            "ride",
            "wins",
            "losses",
            "ties",
            "winning_percentage",
            "mutual_riders_count",
            "comparison_count",
            "average_rating",
            "last_calculated",
            "calculation_version",
            "head_to_head_comparisons",
            "ranking_history",
        ]

    @extend_schema_field(serializers.DictField())
    def get_ride(self, obj):
        """Get detailed ride information."""
        ride = obj.ride
        return {
            "id": ride.id,
            "name": ride.name,
            "slug": ride.slug,
            "description": ride.description,
            "park": {
                "id": ride.park.id,
                "name": ride.park.name,
                "slug": ride.park.slug,
                "location": {
                    "city": (ride.park.location.city if hasattr(ride.park, "location") else None),
                    "state": (ride.park.location.state if hasattr(ride.park, "location") else None),
                    "country": (ride.park.location.country if hasattr(ride.park, "location") else None),
                },
            },
            "category": ride.category,
            "manufacturer": (
                {"id": ride.manufacturer.id, "name": ride.manufacturer.name} if ride.manufacturer else None
            ),
            "opening_date": ride.opening_date,
            "status": ride.status,
        }

    @extend_schema_field(serializers.ListField(child=serializers.DictField()))
    def get_head_to_head_comparisons(self, obj):
        """Get top head-to-head comparisons."""
        from django.db.models import Q

        from apps.rides.models import RidePairComparison

        comparisons = (
            RidePairComparison.objects.filter(Q(ride_a=obj.ride) | Q(ride_b=obj.ride))
            .select_related("ride_a", "ride_b")
            .order_by("-mutual_riders_count")[:10]
        )

        results = []
        for comp in comparisons:
            if comp.ride_a == obj.ride:
                opponent = comp.ride_b
                wins = comp.ride_a_wins
                losses = comp.ride_b_wins
            else:
                opponent = comp.ride_a
                wins = comp.ride_b_wins
                losses = comp.ride_a_wins

            result = "win" if wins > losses else "loss" if losses > wins else "tie"

            results.append(
                {
                    "opponent": {
                        "id": opponent.id,
                        "name": opponent.name,
                        "slug": opponent.slug,
                        "park": opponent.park.name,
                    },
                    "wins": wins,
                    "losses": losses,
                    "ties": comp.ties,
                    "result": result,
                    "mutual_riders": comp.mutual_riders_count,
                }
            )

        return results

    @extend_schema_field(serializers.ListField(child=serializers.DictField()))
    def get_ranking_history(self, obj):
        """Get recent ranking history."""
        from apps.rides.models import RankingSnapshot

        history = RankingSnapshot.objects.filter(ride=obj.ride).order_by("-snapshot_date")[:30]

        return [
            {
                "date": snapshot.snapshot_date,
                "rank": snapshot.rank,
                "winning_percentage": float(snapshot.winning_percentage),
            }
            for snapshot in history
        ]


class RankingSnapshotSerializer(serializers.ModelSerializer):
    """Serializer for ranking history snapshots."""

    ride_name = serializers.CharField(source="ride.name", read_only=True)
    park_name = serializers.CharField(source="ride.park.name", read_only=True)

    class Meta:
        model = RankingSnapshot
        fields = [
            "id",
            "ride",
            "ride_name",
            "park_name",
            "rank",
            "winning_percentage",
            "snapshot_date",
        ]


class RankingStatsSerializer(serializers.Serializer):
    """Serializer for ranking system statistics."""

    total_ranked_rides = serializers.IntegerField()
    total_comparisons = serializers.IntegerField()
    last_calculation_time = serializers.DateTimeField()
    calculation_duration = serializers.FloatField()
    top_rated_ride = serializers.DictField()
    most_compared_ride = serializers.DictField()
    biggest_rank_change = serializers.DictField()
