from rest_framework import serializers
from django.db import models
from .models import (
    TransportType,
    TransportVehicle,
    Route,
    Stop,
    StudentTransport,
    TeacherTransport,
)
from academics.models import StudentEnrollment, AcademicYear


class TransportTypeSerializer(serializers.ModelSerializer):
    class Meta:
        model = TransportType
        fields = ["id", "name"]
        read_only_fields = ["id"]


class TransportVehicleSerializer(serializers.ModelSerializer):
    transport_type_name = serializers.CharField(
        source="transport_type.name", read_only=True
    )
    current_occupancy = serializers.SerializerMethodField()
    available_seats = serializers.SerializerMethodField()

    class Meta:
        model = TransportVehicle
        fields = [
            "id",
            "transport_type",
            "transport_type_name",
            "vehicle_number",
            "bus_number",
            "driver_name",
            "driver_phone",
            "capacity",
            "vehicle_photo",
            "registration_certificate",
            "insurance_document",
            "pollution_certificate",
            "permit_document",
            "fitness_certificate",
            "current_occupancy",
            "available_seats",
        ]
        read_only_fields = ["id"]

    def get_current_occupancy(self, obj):
        return (
            StudentTransport.objects.filter(vehicle=obj, is_active=True).count()
            + TeacherTransport.objects.filter(vehicle=obj, is_active=True).count()
        )

    def get_available_seats(self, obj):
        current = self.get_current_occupancy(obj)
        return obj.capacity - current


class StopSerializer(serializers.ModelSerializer):
    class Meta:
        model = Stop
        fields = ["id", "route", "stop_name", "stop_order", "arrival_time", "fee_amount"]
        read_only_fields = ["id"]


class RouteSerializer(serializers.ModelSerializer):
    stops = StopSerializer(many=True, read_only=True)
    vehicle_details = TransportVehicleSerializer(source="vehicle", read_only=True)
    total_stops = serializers.IntegerField(source="stops.count", read_only=True)

    class Meta:
        model = Route
        fields = [
            "id",
            "vehicle",
            "vehicle_details",
            "route_name",
            "start_location",
            "destination",
            "distance_km",
            "stops",
            "total_stops",
        ]
        read_only_fields = ["id"]


class StudentEnrollmentDetailSerializer(serializers.ModelSerializer):
    student_name = serializers.CharField(
        source="student.user.get_full_name", read_only=True
    )
    student_id = serializers.IntegerField(source="student.id", read_only=True)
    class_name = serializers.CharField(
        source="academic_class.standard.name", read_only=True
    )
    section_name = serializers.CharField(
        source="academic_class.section.code", read_only=True
    )
    academic_year_name = serializers.CharField(
        source="academic_class.academic_year.name", read_only=True
    )
    roll_number = serializers.IntegerField(read_only=True)

    class Meta:
        model = StudentEnrollment
        fields = [
            "id",
            "student_id",
            "student_name",
            "roll_number",
            "class_name",
            "section_name",
            "academic_year_name",
        ]


class StudentTransportSerializer(serializers.ModelSerializer):
    """
    Serializer for listing student transport assignments
    """

    # Student fields
    student_name = serializers.SerializerMethodField()
    student_first_name = serializers.CharField(
        source="student.first_name", read_only=True
    )
    student_last_name = serializers.CharField(
        source="student.last_name", read_only=True
    )
    student_admission_no = serializers.CharField(
        source="student.admission_number", read_only=True
    )

    # Enrollment fields
    enrollment_roll_number = serializers.IntegerField(
        source="enrollment.roll_number", read_only=True
    )

    # Class fields
    class_name = serializers.CharField(
        source="enrollment.academic_class.standard.name", read_only=True
    )
    section_name = serializers.CharField(
        source="enrollment.academic_class.section.code", read_only=True
    )
    academic_year_name = serializers.CharField(
        source="enrollment.academic_class.academic_year.name", read_only=True
    )

    # Transport fields
    vehicle_number = serializers.CharField(source="vehicle.bus_number", read_only=True)
    route_name = serializers.CharField(source="route.route_name", read_only=True)
    stop_name = serializers.CharField(source="stop.stop_name", read_only=True)
    is_overdue = serializers.SerializerMethodField()

    class Meta:
        model = StudentTransport
        fields = [
            "id",
            "enrollment",
            "student",
            "student_name",
            "student_first_name",
            "student_last_name",
            "student_admission_no",
            "enrollment_roll_number",
            "vehicle",
            "vehicle_number",
            "route",
            "route_name",
            "stop",
            "stop_name",
            "pickup_point",
            "fee_amount",
            "due_date",
            "is_overdue",
            "is_active",
            "class_name",
            "section_name",
            "academic_year_name",
        ]

    def get_student_name(self, obj):
        if obj.student:
            first = obj.student.first_name or ""
            last = obj.student.last_name or ""
            return f"{first} {last}".strip()
        return None

    def get_is_overdue(self, obj):
        if not obj.due_date:
            return False
        from django.utils import timezone

        return obj.due_date < timezone.now().date()


class StudentTransportCreateUpdateSerializer(serializers.ModelSerializer):
    """
    Serializer for creating and updating student transport assignments
    """

    class Meta:
        model = StudentTransport
        fields = [
            "id",
            "student",
            "enrollment",
            "vehicle",
            "route",
            "stop",
            "pickup_point",
            "fee_amount",
            "due_date",
            "is_active",
        ]

    def validate(self, data):
        # Validate that enrollment belongs to the student
        if "enrollment" in data and "student" in data:
            enrollment = data["enrollment"]
            if enrollment.student_id != data["student"].id:
                raise serializers.ValidationError(
                    {"enrollment": "Enrollment does not belong to the selected student"}
                )

        # Validate that route belongs to vehicle
        if "route" in data and "vehicle" in data:
            route = data["route"]
            if route.vehicle_id != data["vehicle"].id:
                raise serializers.ValidationError(
                    {"route": "Route does not belong to the selected vehicle"}
                )

        # Validate that stop belongs to route
        if "stop" in data and "route" in data and data["stop"]:
            stop = data["stop"]
            if stop.route_id != data["route"].id:
                raise serializers.ValidationError(
                    {"stop": "Stop does not belong to the selected route"}
                )

        # Validate vehicle capacity
        if "vehicle" in data and "is_active" in data and data.get("is_active", True):
            vehicle = data["vehicle"]
            current_assignments = StudentTransport.objects.filter(
                vehicle=vehicle, is_active=True
            ).count()

            if self.instance:
                # Exclude current instance if updating
                current_assignments -= 1

            if current_assignments >= vehicle.capacity:
                raise serializers.ValidationError(
                    {
                        "vehicle": f"Vehicle has reached maximum capacity of {vehicle.capacity}"
                    }
                )

        return data

    def create(self, validated_data):
        # Auto-populate enrollment_number and academic_year
        enrollment = validated_data.get("enrollment")
        if enrollment:
            validated_data["enrollment_number"] = enrollment.roll_number
            if enrollment.academic_class and enrollment.academic_class.academic_year:
                validated_data["academic_year"] = str(
                    enrollment.academic_class.academic_year
                )
        return super().create(validated_data)

    def update(self, instance, validated_data):
        # Update enrollment info if changed
        enrollment = validated_data.get("enrollment")
        if enrollment and instance.enrollment != enrollment:
            validated_data["enrollment_number"] = enrollment.roll_number
            if enrollment.academic_class and enrollment.academic_class.academic_year:
                validated_data["academic_year"] = str(
                    enrollment.academic_class.academic_year
                )
        return super().update(instance, validated_data)


class TeacherTransportSerializer(serializers.ModelSerializer):
    """
    Serializer for listing teacher transport assignments
    """

    # Teacher fields
    teacher_name = serializers.SerializerMethodField()
    teacher_first_name = serializers.CharField(
        source="teacher.first_name", read_only=True
    )
    teacher_last_name = serializers.CharField(
        source="teacher.last_name", read_only=True
    )
    teacher_email = serializers.CharField(source="teacher.email", read_only=True)
    teacher_phone = serializers.CharField(source="teacher.phone_number", read_only=True)
    teacher_employee_id = serializers.CharField(
        source="teacher.employee_id", read_only=True
    )

    # Transport fields
    vehicle_number_display = serializers.CharField(
        source="vehicle.bus_number", read_only=True
    )
    vehicle_plate = serializers.CharField(
        source="vehicle.vehicle_number", read_only=True
    )
    vehicle_capacity = serializers.IntegerField(
        source="vehicle.capacity", read_only=True
    )

    route_name = serializers.CharField(source="route.route_name", read_only=True)
    route_start = serializers.CharField(source="route.start_location", read_only=True)
    route_destination = serializers.CharField(
        source="route.destination", read_only=True
    )

    stop_name = serializers.CharField(
        source="stop.stop_name", read_only=True, allow_null=True
    )
    stop_order = serializers.IntegerField(
        source="stop.stop_order", read_only=True, allow_null=True
    )
    arrival_time = serializers.TimeField(
        source="stop.arrival_time", read_only=True, allow_null=True
    )

    class Meta:
        model = TeacherTransport
        fields = [
            "id",
            "teacher",
            "teacher_name",
            "teacher_first_name",
            "teacher_last_name",
            "teacher_email",
            "teacher_phone",
            "teacher_employee_id",
            "vehicle",
            "vehicle_number_display",
            "vehicle_plate",
            "vehicle_capacity",
            "route",
            "route_name",
            "route_start",
            "route_destination",
            "stop",
            "stop_name",
            "stop_order",
            "arrival_time",
            "pickup_point",
            "is_active",
        ]
        read_only_fields = ["id"]

    def get_teacher_name(self, obj):
        if obj.teacher:
            first = obj.teacher.first_name or ""
            last = obj.teacher.last_name or ""
            return f"{first} {last}".strip()
        return None


class TeacherTransportCreateUpdateSerializer(serializers.ModelSerializer):
    """
    Serializer for creating and updating teacher transport assignments
    """

    class Meta:
        model = TeacherTransport
        fields = [
            "id",
            "teacher",
            "vehicle",
            "route",
            "stop",
            "pickup_point",
            "is_active",
        ]

    def validate(self, data):
        # Validate that route belongs to vehicle
        if "route" in data and "vehicle" in data:
            route = data["route"]
            if route.vehicle_id != data["vehicle"].id:
                raise serializers.ValidationError(
                    {"route": "Route does not belong to the selected vehicle"}
                )

        # Validate that stop belongs to route
        if "stop" in data and "route" in data and data["stop"]:
            stop = data["stop"]
            if stop.route_id != data["route"].id:
                raise serializers.ValidationError(
                    {"stop": "Stop does not belong to the selected route"}
                )

        # Validate vehicle capacity (optional - teachers may not count towards capacity)
        if "vehicle" in data and "is_active" in data and data.get("is_active", True):
            vehicle = data["vehicle"]
            current_assignments = TeacherTransport.objects.filter(
                vehicle=vehicle, is_active=True
            ).count()

            # Optional: Add capacity check if needed
            # if current_assignments >= vehicle.capacity:
            #     raise serializers.ValidationError(
            #         {"vehicle": f"Vehicle has reached maximum capacity of {vehicle.capacity}"}
            #     )

        return data


class TransportDashboardSerializer(serializers.Serializer):
    total_vehicles = serializers.IntegerField()
    total_routes = serializers.IntegerField()
    total_stops = serializers.IntegerField()
    active_students = serializers.IntegerField()
    active_teachers = serializers.IntegerField()
    total_occupied_seats = serializers.IntegerField()
    total_capacity = serializers.IntegerField()
    utilization_percentage = serializers.FloatField()
    vehicles_by_type = serializers.DictField()
    students_by_class = serializers.DictField()
