from rest_framework import serializers
from .models import (
    AcademicYear,
    AcademicClass,
    Standard,
    Section,
    Subject,
    AcademicTerm,
    ClassSubject,
    SubjectCategory,
    SubjectGroup,
    StudentSubjectGroup,
    StudentEnrollment,
    StudentSubject,
    SubjectTeacher,
)
from people.models import Teacher, Student
from datetime import date
import os

class TeacherSimpleSerializer(serializers.ModelSerializer):
    """Simple serializer for Teacher model"""

    class Meta:
        model = Teacher
        fields = [
            "id",
            "external_user_id",
            "first_name",
            "last_name",
            "full_name",
            "email",
            "phone",
        ]


class StandardSerializer(serializers.ModelSerializer):
    class Meta:
        model = Standard
        fields = "__all__"


class SectionSerializer(serializers.ModelSerializer):
    class Meta:
        model = Section
        fields = "__all__"


class AcademicYearSerializer(serializers.ModelSerializer):
    """Serializer for Academic Year model"""

    is_current = serializers.SerializerMethodField()
    duration_days = serializers.SerializerMethodField()

    class Meta:
        model = AcademicYear
        fields = [
            "id",
            "name",
            "code",
            "start_date",
            "end_date",
            "terms_count",
            "fee_due_date",
            "is_active",
            "is_frozen",
            "admissions_open",
            "is_current",
            "duration_days",
            "created_at",
            "updated_at",
        ]
        read_only_fields = ["created_at", "updated_at"]

    def get_is_current(self, obj):
        from datetime import date

        today = date.today()
        return obj.start_date <= today <= obj.end_date

    def get_duration_days(self, obj):
        return (obj.end_date - obj.start_date).days


def validate(self, data):
    """
    Validate that end_date is after start_date.
    """
    start_date = data.get("start_date")
    end_date = data.get("end_date")

    if start_date and end_date:
        if end_date <= start_date:
            raise serializers.ValidationError(
                {"end_date": "End date must be after start date."}
            )
    return data



class AcademicClassSerializer(serializers.ModelSerializer):
    """Serializer for Academic Class model"""

    class_name = serializers.CharField(read_only=True)
    available_seats = serializers.IntegerField(read_only=True)
    gender_composition = serializers.DictField(read_only=True)
    class_teacher_details = TeacherSimpleSerializer(
        source="class_teacher", read_only=True
    )
    assistant_teacher_details = TeacherSimpleSerializer(
        source="assistant_teacher", read_only=True
    )
    standard_details = StandardSerializer(source="standard", read_only=True)
    section_details = SectionSerializer(source="section", read_only=True)
    academic_year_details = AcademicYearSerializer(
        source="academic_year", read_only=True
    )

    class Meta:
        model = AcademicClass
        fields = [
            "id",
            "academic_year",
            "standard",
            "section",
            "class_name",
            "class_teacher",
            "assistant_teacher",
            "room_number",
            "timetable_document",
            "current_strength",
            "max_strength",
            "boys_count",
            "girls_count",
            "annual_fee",
            "passing_percentage",
            "min_attendance_percentage",
            "is_active",
            "is_frozen",
            "notes",
            "available_seats",
            "gender_composition",
            "class_teacher_details",
            "assistant_teacher_details",
            "standard_details",
            "section_details",
            "academic_year_details",
            "created_at",
            "updated_at",
        ]
        read_only_fields = [
            "created_at",
            "updated_at",
            "current_strength",
            "boys_count",
            "girls_count",
            "created_by",
        ]

    def validate(self, data):
        """
        Validate academic class data.
        """
        # First, check if required fields are present
        required_fields = ['academic_year', 'standard', 'section']
        missing_fields = []
        for field in required_fields:
            if field not in data or not data.get(field):
                missing_fields.append(field)
        
        if missing_fields:
            raise serializers.ValidationError({
                'non_field_errors': f'Missing required fields: {", ".join(missing_fields)}. Please provide academic_year, standard, and section.'
            })
        
        # Check if class already exists for this year-standard-section combination
        if self.instance is None:  # Creating new
            if AcademicClass.objects.filter(
                academic_year=data.get("academic_year"),
                standard=data.get("standard"),
                section=data.get("section"),
            ).exists():
                raise serializers.ValidationError(
                    {
                        "non_field_errors": "A class with this academic year, standard, and section already exists."
                    }
                )
        else:  # Updating existing
            # Check if the combination would conflict with another class (excluding current instance)
            if AcademicClass.objects.filter(
                academic_year=data.get("academic_year"),
                standard=data.get("standard"),
                section=data.get("section"),
            ).exclude(id=self.instance.id).exists():
                raise serializers.ValidationError(
                    {
                        "non_field_errors": "Cannot update: A class with this academic year, standard, and section already exists."
                    }
                )

        # Validate strength
        current_strength = data.get("current_strength")
        max_strength = data.get("max_strength")
        
        if current_strength is not None and max_strength is not None:
            if current_strength > max_strength:
                raise serializers.ValidationError(
                    {"current_strength": "Current strength cannot exceed maximum strength."}
                )

        return data



class SubjectSerializer(serializers.ModelSerializer):
    """
    Serializer for Subject model.
    """

    standard_name = serializers.CharField(source="standard.name", read_only=True)
    standard_code = serializers.CharField(source="standard.code", read_only=True)
    category_name = serializers.CharField(source="category.name", read_only=True)
    category_code = serializers.CharField(source="category.code", read_only=True)
    subject_group_name = serializers.CharField(
        source="subject_group.name", read_only=True, allow_null=True
    )

    book_document_url = serializers.SerializerMethodField(read_only=True)
    book_document_name = serializers.SerializerMethodField(read_only=True)

    class Meta:
        model = Subject
        fields = [
            "id",
            "name",
            "code",
            "standard",
            "standard_name",
            "standard_code",
            "category",
            "category_name",
            "category_code",
            "subject_group",
            "subject_group_name",
            "subject_type",
            "is_active",
            "book_document",  # Add this field
            "book_document_url",  # URL for downloading
            "book_document_name",
        ]
        read_only_fields = ["id"]
        extra_kwargs = {"book_document": {"required": False, "allow_null": True}}

    def validate_name(self, value):
        """
        Validate subject name.
        """
        if len(value.strip()) < 2:
            raise serializers.ValidationError(
                "Subject name must be at least 2 characters long."
            )
        if len(value.strip()) > 100:
            raise serializers.ValidationError(
                "Subject name cannot exceed 100 characters."
            )
        return value.strip()

    def get_book_document_url(self, obj):
        """Get the full URL for the book document"""
        if obj.book_document:
            request = self.context.get("request")
            if request:
                return request.build_absolute_uri(obj.book_document.url)
            return obj.book_document.url
        return None

    def get_book_document_name(self, obj):
        """Get the filename of the book document"""
        if obj.book_document:
            return obj.book_document.name.split("/")[-1]
        return None

    def validate_code(self, value):
        """
        Validate subject code.
        """
        if len(value.strip()) < 2:
            raise serializers.ValidationError(
                "Subject code must be at least 2 characters long."
            )
        if len(value.strip()) > 20:
            raise serializers.ValidationError(
                "Subject code cannot exceed 20 characters."
            )

        # Ensure code contains only uppercase letters and numbers
        code = value.strip().upper()
        if not code.isalnum():
            raise serializers.ValidationError(
                "Subject code can only contain letters and numbers."
            )

        return code

    def validate_subject_group(self, value):
        """
        Validate subject group.
        """
        # If subject_group is provided, ensure it belongs to the same standard
        if value and "standard" in self.initial_data:
            try:
                standard = Standard.objects.get(id=self.initial_data["standard"])
                if value.standard != standard:
                    raise serializers.ValidationError(
                        f"Subject group '{value.name}' does not belong to standard '{standard.name}'."
                    )
            except Standard.DoesNotExist:
                pass  # Standard validation will catch this

        return value

    def validate_book_document(self, value):
        """
        Validate the uploaded book document.
        """
        if value:
            # Check file size (e.g., 50MB limit)
            if value.size > 50 * 1024 * 1024:  # 50MB
                raise serializers.ValidationError(
                    "File size must not exceed 50MB."
                )
            
            # Check file extension
            allowed_extensions = ['.pdf', '.doc', '.docx', '.txt', '.epub']
            file_extension = os.path.splitext(value.name)[1].lower()
            
            if file_extension not in allowed_extensions:
                raise serializers.ValidationError(
                    f"Unsupported file format. Allowed formats: {', '.join(allowed_extensions)}"
                )
            
            # Check content type (optional, for better security)
            if hasattr(value, 'content_type'):
                allowed_content_types = [
                    'application/pdf',
                    'application/msword',
                    'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
                    'text/plain',
                    'application/epub+zip'
                ]
                if value.content_type not in allowed_content_types:
                    raise serializers.ValidationError(
                        "Invalid file type. Only PDF, DOC, DOCX, TXT, and EPUB files are allowed."
                    )
        
        return value

    def validate(self, data):
        """
        Additional validation for unique constraint and business rules.
        """
        standard = data.get("standard")
        code = data.get("code")
        subject_group = data.get("subject_group")
        subject_type = data.get("subject_type")

        # Check unique constraint: standard + code must be unique
        queryset = Subject.objects.filter(standard=standard, code=code)

        if self.instance is not None:
            queryset = queryset.exclude(pk=self.instance.pk)

        if queryset.exists():
            raise serializers.ValidationError(
                {"code": ["A subject with this code already exists for this standard."]}
            )

        # Business rule validation
        if subject_group:
            # Subject group should only be for higher secondary
            if standard.standard_type != "higher_secondary":
                raise serializers.ValidationError(
                    {
                        "subject_group": [
                            "Subject groups are only allowed for higher secondary standards."
                        ]
                    }
                )

            # Ensure subject_group belongs to the same standard
            if subject_group.standard != standard:
                raise serializers.ValidationError(
                    {
                        "subject_group": [
                            "Subject group does not belong to the selected standard."
                        ]
                    }
                )

        # Language subjects typically don't have subject groups
        if subject_type == "language" and subject_group:
            raise serializers.ValidationError(
                {"subject_type": ["Language subjects should not have subject groups."]}
            )

        return data

    def to_representation(self, instance):
        """
        Custom representation including calculated fields.
        """
        representation = super().to_representation(instance)

        # Add display name
        representation["display_name"] = f"{instance.name} ({instance.code})"

        return representation


class AcademicTermSerializer(serializers.ModelSerializer):
    """Serializer for Academic Term model"""

    duration_days = serializers.IntegerField(read_only=True)

    class Meta:
        model = AcademicTerm
        fields = "__all__"

    def validate(self, data):
        # Validate term dates are within academic year
        if data.get("start_date") and data.get("end_date"):
            academic_year = data.get("academic_year")
            if academic_year:
                if data["start_date"] < academic_year.start_date:
                    raise serializers.ValidationError(
                        {
                            "start_date": "Term start date cannot be before academic year start date."
                        }
                    )
                if data["end_date"] > academic_year.end_date:
                    raise serializers.ValidationError(
                        {
                            "end_date": "Term end date cannot be after academic year end date."
                        }
                    )

        return data


class ClassSubjectSerializer(serializers.ModelSerializer):
    """Serializer for Class Subject model"""

    teacher_details = TeacherSimpleSerializer(source="teacher", read_only=True)
    subject_details = SubjectSerializer(source="subject", read_only=True)
    academic_class_details = AcademicClassSerializer(
        source="academic_class", read_only=True
    )

    class Meta:
        model = ClassSubject
        fields = "__all__"


class SubjectCategorySerializer(serializers.ModelSerializer):
    """
    Serializer for SubjectCategory model.
    """

    class Meta:
        model = SubjectCategory
        fields = ["id", "name", "code"]
        read_only_fields = ["id"]

    def validate_name(self, value):
        """
        Validate category name.
        """
        if len(value.strip()) < 2:
            raise serializers.ValidationError(
                "Category name must be at least 2 characters long."
            )
        if len(value.strip()) > 50:
            raise serializers.ValidationError(
                "Category name cannot exceed 50 characters."
            )
        return value.strip()

    def validate_code(self, value):
        """
        Validate category code.
        """
        if len(value.strip()) < 2:
            raise serializers.ValidationError(
                "Category code must be at least 2 characters long."
            )
        if len(value.strip()) > 20:
            raise serializers.ValidationError(
                "Category code cannot exceed 20 characters."
            )

        # Ensure code contains only uppercase letters and numbers
        code = value.strip().upper()
        if not code.isalnum():
            raise serializers.ValidationError(
                "Category code can only contain letters and numbers."
            )

        return code

    def to_representation(self, instance):
        """
        Custom representation including calculated fields.
        """
        representation = super().to_representation(instance)

        # Add additional fields if needed
        representation["display_name"] = f"{instance.name} ({instance.code})"

        return representation


class SubjectGroupSerializer(serializers.ModelSerializer):
    """
    Serializer for SubjectGroup model.
    """

    standard_name = serializers.CharField(source="standard.name", read_only=True)
    standard_code = serializers.CharField(source="standard.code", read_only=True)

    class Meta:
        model = SubjectGroup
        fields = [
            "id",
            "name",
            "code",
            "standard",
            "standard_name",
            "standard_code",
            "is_active",
        ]
        read_only_fields = ["id"]

    def validate_name(self, value):
        """
        Validate group name.
        """
        if len(value.strip()) < 2:
            raise serializers.ValidationError(
                "Group name must be at least 2 characters long."
            )
        if len(value.strip()) > 100:
            raise serializers.ValidationError(
                "Group name cannot exceed 100 characters."
            )
        return value.strip()

    def validate_code(self, value):
        """
        Validate group code.
        """
        if len(value.strip()) < 2:
            raise serializers.ValidationError(
                "Group code must be at least 2 characters long."
            )
        if len(value.strip()) > 20:
            raise serializers.ValidationError("Group code cannot exceed 20 characters.")

        # Ensure code contains only uppercase letters and numbers
        code = value.strip().upper()
        if not code.isalnum():
            raise serializers.ValidationError(
                "Group code can only contain letters and numbers."
            )

        return code

    def validate_standard(self, value):
        """
        Validate that standard is higher secondary.
        """
        if value.standard_type != "higher_secondary":
            raise serializers.ValidationError(
                "Subject groups can only be created for higher secondary standards (11th & 12th)."
            )
        return value

    def validate(self, data):
        """
        Additional validation for unique constraint.
        """
        # For create operation
        if self.instance is None:
            if SubjectGroup.objects.filter(
                name=data.get("name"), standard=data.get("standard")
            ).exists():
                raise serializers.ValidationError(
                    {
                        "non_field_errors": [
                            "A subject group with this name already exists for this standard."
                        ]
                    }
                )

            if SubjectGroup.objects.filter(code=data.get("code")).exists():
                raise serializers.ValidationError(
                    {"code": ["A subject group with this code already exists."]}
                )
        # For update operation
        else:
            if (
                SubjectGroup.objects.filter(
                    name=data.get("name"), standard=data.get("standard")
                )
                .exclude(pk=self.instance.pk)
                .exists()
            ):
                raise serializers.ValidationError(
                    {
                        "non_field_errors": [
                            "Another subject group with this name already exists for this standard."
                        ]
                    }
                )

            if (
                SubjectGroup.objects.filter(code=data.get("code"))
                .exclude(pk=self.instance.pk)
                .exists()
            ):
                raise serializers.ValidationError(
                    {"code": ["Another subject group with this code already exists."]}
                )

        return data

    def to_representation(self, instance):
        """
        Custom representation including calculated fields.
        """
        representation = super().to_representation(instance)

        # Add display name
        representation["display_name"] = (
            f"{instance.name} ({instance.code}) - {instance.standard.name}"
        )

        return representation


class ClassSubjectSerializer(serializers.ModelSerializer):
    """
    Serializer for ClassSubject model.
    """

    academic_class_display = serializers.SerializerMethodField()
    subject_display = serializers.SerializerMethodField()
    standard_name = serializers.CharField(
        source="academic_class.standard.name", read_only=True
    )
    section_code = serializers.CharField(
        source="academic_class.section.code", read_only=True
    )
    academic_year_name = serializers.CharField(
        source="academic_class.academic_year.name", read_only=True
    )
    subject_name = serializers.CharField(source="subject.name", read_only=True)
    subject_code = serializers.CharField(source="subject.code", read_only=True)
    subject_category_name = serializers.CharField(
        source="subject.category.name", read_only=True
    )
    subject_type = serializers.CharField(source="subject.subject_type", read_only=True)
    subject_group_name = serializers.CharField(
        source="subject.subject_group.name", read_only=True, allow_null=True
    )

    class Meta:
        model = ClassSubject
        fields = [
            "id",
            "academic_class",
            "academic_class_display",
            "subject",
            "subject_display",
            "standard_name",
            "section_code",
            "academic_year_name",
            "subject_name",
            "subject_code",
            "subject_category_name",
            "subject_type",
            "subject_group_name",
        ]
        read_only_fields = ["id"]

    def get_academic_class_display(self, obj):
        """Get display name for academic class."""
        if obj.academic_class:
            return f"{obj.academic_class.standard.name} - {obj.academic_class.section.code}"
        return ""

    def get_subject_display(self, obj):
        """Get display name for subject."""
        if obj.subject:
            return f"{obj.subject.name} ({obj.subject.code})"
        return ""

    def validate(self, data):
        """
        Validate class-subject assignment.
        """
        academic_class = data.get("academic_class")
        subject = data.get("subject")

        # Check if both fields are provided
        if not academic_class or not subject:
            raise serializers.ValidationError(
                "Both academic class and subject are required."
            )

        # Check if academic class exists
        if not AcademicClass.objects.filter(
            id=academic_class.id, is_active=True
        ).exists():
            raise serializers.ValidationError(
                {"academic_class": ["Academic class not found or is not active."]}
            )

        # Check if subject exists and is active
        if not Subject.objects.filter(id=subject.id, is_active=True).exists():
            raise serializers.ValidationError(
                {"subject": ["Subject not found or is not active."]}
            )

        # Check if subject belongs to the same standard as the class
        if subject.standard != academic_class.standard:
            raise serializers.ValidationError(
                {
                    "subject": [
                        f"Subject '{subject.name}' does not belong to standard '{academic_class.standard.name}'."
                    ]
                }
            )

        # Check for duplicate assignment (only for create)
        if self.instance is None:
            if ClassSubject.objects.filter(
                academic_class=academic_class, subject=subject
            ).exists():
                raise serializers.ValidationError(
                    {
                        "non_field_errors": [
                            "This subject is already assigned to this class."
                        ]
                    }
                )

        return data

    def create(self, validated_data):
        """
        Create class-subject assignment.
        """
        return ClassSubject.objects.create(**validated_data)

    def update(self, instance, validated_data):
        """
        Update class-subject assignment.
        """
        instance.academic_class = validated_data.get(
            "academic_class", instance.academic_class
        )
        instance.subject = validated_data.get("subject", instance.subject)
        instance.save()
        return instance


class ClassSubjectCreateSerializer(serializers.ModelSerializer):
    """
    Simplified serializer for creating class subjects.
    """

    class Meta:
        model = ClassSubject
        fields = ["academic_class", "subject"]

    def validate(self, data):
        """
        Validate creation of class-subject.
        """
        academic_class = data.get("academic_class")
        subject = data.get("subject")

        # Check for duplicate
        if ClassSubject.objects.filter(
            academic_class=academic_class, subject=subject
        ).exists():
            raise serializers.ValidationError(
                {
                    "non_field_errors": [
                        "This subject is already assigned to this class."
                    ]
                }
            )

        # Check if subject belongs to the same standard
        if subject.standard != academic_class.standard:
            raise serializers.ValidationError(
                {
                    "subject": [
                        f"Subject does not belong to standard '{academic_class.standard.name}'."
                    ]
                }
            )

        return data


class ClassSubjectBulkSerializer(serializers.Serializer):
    """
    Serializer for bulk assignment of subjects to classes.
    """

    academic_class = serializers.PrimaryKeyRelatedField(
        queryset=AcademicClass.objects.filter(is_active=True)
    )
    subjects = serializers.ListField(
        child=serializers.PrimaryKeyRelatedField(
            queryset=Subject.objects.filter(is_active=True)
        ),
        min_length=1,
    )

    def validate(self, data):
        """
        Validate bulk assignments.
        """
        academic_class = data["academic_class"]
        subjects = data["subjects"]

        # Check if all subjects belong to the same standard
        for subject in subjects:
            if subject.standard != academic_class.standard:
                raise serializers.ValidationError(
                    {
                        "subjects": [
                            f"Subject '{subject.name}' does not belong to standard '{academic_class.standard.name}'."
                        ]
                    }
                )

        return data

    def create(self, validated_data):
        """
        Create multiple class-subject assignments.
        """
        academic_class = validated_data["academic_class"]
        subjects = validated_data["subjects"]

        created = []
        errors = []
        existing_count = 0

        for subject in subjects:
            # Check if assignment already exists
            if ClassSubject.objects.filter(
                academic_class=academic_class, subject=subject
            ).exists():
                existing_count += 1
                continue

            try:
                class_subject = ClassSubject.objects.create(
                    academic_class=academic_class, subject=subject
                )
                created.append(class_subject)
            except Exception as e:
                errors.append(f"Failed to assign {subject.name}: {str(e)}")

        return {
            "created": len(created),
            "existing": existing_count,
            "errors": errors,
            "assignments": (
                ClassSubjectSerializer(created, many=True).data if created else []
            ),
        }


class SimpleStudentSerializer(serializers.ModelSerializer):
    """Simplified student serializer for dropdowns"""

    full_name = serializers.SerializerMethodField()
    current_class_info = serializers.SerializerMethodField()

    class Meta:
        model = Student
        fields = [
            "id",
            "first_name",
            "last_name",
            "full_name",
            "admission_number",
            "roll_number",
            "current_class_info",
            "photo",
        ]

    def get_full_name(self, obj):
        return f"{obj.first_name} {obj.last_name}"

    def get_current_class_info(self, obj):
        if obj.current_class and obj.current_class.academic_class_details:
            return {
                "class_name": obj.current_class.academic_class_details.class_name,
                "standard": obj.current_class.academic_class_details.standard_details.name,
                "standard_id": obj.current_class.academic_class_details.standard,
                "section": obj.current_class.academic_class_details.section_details.code,
                "academic_year": obj.current_class.academic_class_details.academic_year_details.name,
            }
        return None


class SimpleSubjectGroupSerializer(serializers.ModelSerializer):
    """Simplified subject group serializer for dropdowns"""

    class Meta:
        model = SubjectGroup
        fields = ["id", "name", "code", "group_type", "description", "is_active"]


class StudentSubjectGroupSerializer(serializers.ModelSerializer):
    """Main serializer for Student Subject Groups"""

    student_name = serializers.SerializerMethodField()
    student_photo = serializers.ImageField(source="student.photo", read_only=True)
    admission_number = serializers.CharField(
        source="student.admission_number", read_only=True
    )
    roll_number = serializers.CharField(source="student.roll_number", read_only=True)

    subject_group_name = serializers.CharField(
        source="subject_group.name", read_only=True
    )
    subject_group_code = serializers.CharField(
        source="subject_group.code", read_only=True
    )
    group_type = serializers.CharField(
        source="subject_group.group_type", read_only=True
    )
    subject_count = serializers.SerializerMethodField()

    class_name = serializers.SerializerMethodField()
    standard = serializers.SerializerMethodField()
    section = serializers.SerializerMethodField()
    academic_year = serializers.SerializerMethodField()

    class Meta:
        model = StudentSubjectGroup
        fields = [
            "id",
            "student",
            "student_name",
            "student_photo",
            "admission_number",
            "roll_number",
            "subject_group",
            "subject_group_name",
            "subject_group_code",
            "group_type",
            "subject_count",
            "class_name",
            "standard",
            "section",
            "academic_year",
        ]

    def get_student_name(self, obj):
        """Get student's full name"""
        if obj.student:
            return f"{obj.student.first_name} {obj.student.last_name}"
        return None

    def get_subject_count(self, obj):
        """Count of subjects in the subject group"""
        return obj.subject_group.subjects.count() if obj.subject_group else 0

    def get_class_name(self, obj):
        """Get student's current class name"""
        if (
            obj.student.current_class
            and obj.student.current_class.academic_class_details
        ):
            return obj.student.current_class.academic_class_details.class_name
        return None

    def get_standard(self, obj):
        """Get student's current standard"""
        if (
            obj.student.current_class
            and obj.student.current_class.academic_class_details
        ):
            return (
                obj.student.current_class.academic_class_details.standard_details.name
            )
        return None

    def get_section(self, obj):
        """Get student's section"""
        if (
            obj.student.current_class
            and obj.student.current_class.academic_class_details
        ):
            return obj.student.current_class.academic_class_details.section_details.code
        return None

    def get_academic_year(self, obj):
        """Get student's academic year"""
        if (
            obj.student.current_class
            and obj.student.current_class.academic_class_details
        ):
            return (
                obj.student.current_class.academic_class_details.academic_year_details.name
            )
        return None

    def validate(self, data):
        """Custom validation"""
        student = data.get("student")
        subject_group = data.get("subject_group")

        # Check if student is in higher secondary (11th or 12th)
        if student:
            current_class = student.current_class
            if current_class and current_class.academic_class_details:
                standard = current_class.academic_class_details.standard_details

                # Check if standard is 11th or 12th
                if standard.name not in ["11", "12", "XI", "XII"]:
                    raise serializers.ValidationError(
                        {
                            "student": "Subject groups can only be assigned to higher secondary students (11th & 12th standards)"
                        }
                    )
            else:
                raise serializers.ValidationError(
                    {
                        "student": "Student does not have a valid current class assignment"
                    }
                )

        # Check if subject group is active
        if subject_group and not subject_group.is_active:
            raise serializers.ValidationError(
                {"subject_group": "Cannot assign inactive subject group"}
            )

        return data


class StudentSubjectGroupCreateUpdateSerializer(serializers.ModelSerializer):
    """Serializer for create/update operations"""

    class Meta:
        model = StudentSubjectGroup
        fields = ["student", "subject_group"]


class StudentEnrollmentSerializer(serializers.ModelSerializer):
    # Make student_id readable and writable
    student_id = serializers.PrimaryKeyRelatedField(
        queryset=Student.objects.all(),
        source="student",
        write_only=False,  # This makes it readable (not write_only)
    )

    student_name = serializers.SerializerMethodField()
    student_admission_no = serializers.CharField(
        source="student.admission_number", read_only=True
    )
    student_roll_no = serializers.CharField(
        source="student.roll_number", read_only=True
    )

    # Academic class field - readable and writable
    academic_class_id = serializers.PrimaryKeyRelatedField(
        queryset=AcademicClass.objects.all(),
        source="academic_class",
        write_only=False,
    )

    # Read-only display fields
    academic_class_name = serializers.CharField(
        source="academic_class.name", read_only=True
    )
    academic_class_standard = serializers.CharField(
        source="academic_class.standard.name", read_only=True
    )
    academic_class_section = serializers.CharField(
        source="academic_class.section.name", read_only=True
    )

    class Meta:
        model = StudentEnrollment
        fields = [
            "id",
            "student_id",  # Now this will appear in both request and response
            "student_name",
            "student_admission_no",
            "student_roll_no",
            "academic_class_id",
            "academic_class_name",
            "academic_class_standard",
            "academic_class_section",
            "roll_number",
            "admission_date",
            "is_active",
            "created_at",
        ]
        read_only_fields = ["created_at"]

    def get_student_name(self, obj):
        """Get student's full name from Student model"""
        if obj.student:
            # Try different name field combinations based on your Student model
            if hasattr(obj.student, "full_name"):
                return obj.student.full_name
            elif hasattr(obj.student, "first_name") and hasattr(
                obj.student, "last_name"
            ):
                return f"{obj.student.first_name or ''} {obj.student.last_name or ''}".strip()
            elif hasattr(obj.student, "name"):
                return obj.student.name
            else:
                return f"Student {obj.student.id}"
        return ""

    def to_representation(self, instance):
        """Customize the output representation"""
        data = super().to_representation(instance)

        # Ensure student_id is the actual ID value
        if instance.student:
            data["student_id"] = instance.student.id

        # Ensure academic_class_id is the actual ID value
        if instance.academic_class:
            data["academic_class_id"] = instance.academic_class.id

        return data

    def validate(self, data):
        # Check if student is already enrolled in this class
        student = data.get("student")
        academic_class = data.get("academic_class")

        if student and academic_class:
            existing_enrollment = (
                StudentEnrollment.objects.filter(
                    student=student, academic_class=academic_class
                )
                .exclude(id=self.instance.id if self.instance else None)
                .first()
            )

            if existing_enrollment:
                raise serializers.ValidationError(
                    f"Student is already enrolled in this class (Enrollment ID: {existing_enrollment.id})"
                )

            # Check if roll number is unique within the class
            roll_number = data.get("roll_number")
            if roll_number:
                existing_roll = (
                    StudentEnrollment.objects.filter(
                        academic_class=academic_class, roll_number=roll_number
                    )
                    .exclude(id=self.instance.id if self.instance else None)
                    .first()
                )

                if existing_roll:
                    raise serializers.ValidationError(
                        f"Roll number {roll_number} is already assigned to another student in this class"
                    )

        return data


class StudentEnrollmentCreateSerializer(serializers.Serializer):
    student_ids = serializers.ListField(
        child=serializers.IntegerField(), write_only=True
    )
    academic_class_id = serializers.IntegerField(write_only=True)
    admission_date = serializers.DateField(required=False)
    enrollments = StudentEnrollmentSerializer(many=True, read_only=True)


class StudentEnrollmentBulkUpdateSerializer(serializers.Serializer):
    enrollment_ids = serializers.ListField(
        child=serializers.IntegerField(), write_only=True
    )
    is_active = serializers.BooleanField(write_only=True)


class TransferToNextYearSerializer(serializers.Serializer):
    """Serializer for transferring class to next academic year"""

    source_class_id = serializers.IntegerField()
    target_academic_year_id = serializers.IntegerField()
    target_class_id = serializers.IntegerField(required=False, allow_null=True)
    transfer_date = serializers.DateField(required=False, default=date.today)
    copy_class_details = serializers.BooleanField(default=True)
    copy_students = serializers.BooleanField(default=True)
    keep_original_active = serializers.BooleanField(default=False)

    def validate(self, data):
        try:
            # Get source class
            source_class = AcademicClass.objects.get(id=data["source_class_id"])

            # Get target academic year
            target_academic_year = AcademicYear.objects.get(
                id=data["target_academic_year_id"]
            )

            # Check if target academic year is actually after source academic year
            if target_academic_year.start_date <= source_class.academic_year.start_date:
                raise serializers.ValidationError(
                    {
                        "target_academic_year_id": "Target academic year must be after source academic year"
                    }
                )

            # Check if target class exists
            target_class = None
            if data.get("target_class_id"):
                try:
                    target_class = AcademicClass.objects.get(id=data["target_class_id"])

                    # Check if target class is in the correct academic year
                    if target_class.academic_year != target_academic_year:
                        raise serializers.ValidationError(
                            {
                                "target_class_id": "Target class must belong to the selected academic year"
                            }
                        )

                    # Check if target class has same standard and section
                    if (
                        target_class.standard != source_class.standard
                        or target_class.section != source_class.section
                    ):
                        raise serializers.ValidationError(
                            {
                                "target_class_id": "Target class must have same standard and section"
                            }
                        )

                except AcademicClass.DoesNotExist:
                    raise serializers.ValidationError(
                        {"target_class_id": "Target class not found"}
                    )

            # Add objects to validated data for use in view
            data["source_class"] = source_class
            data["target_academic_year"] = target_academic_year
            data["target_class"] = target_class

            return data

        except AcademicClass.DoesNotExist:
            raise serializers.ValidationError(
                {"source_class_id": "Academic class not found"}
            )
        except AcademicYear.DoesNotExist:
            raise serializers.ValidationError(
                {"target_academic_year_id": "Academic year not found"}
            )


class StudentSubjectGroupSerializer(serializers.ModelSerializer):
    """Serializer for Student Subject Group model"""

    enrollment_id = serializers.PrimaryKeyRelatedField(
        queryset=StudentEnrollment.objects.all(), source="enrollment", write_only=True
    )
    enrollment_details = serializers.SerializerMethodField()

    subject_group_id = serializers.PrimaryKeyRelatedField(
        queryset=SubjectGroup.objects.all(), source="subject_group", write_only=True
    )
    subject_group_details = serializers.SerializerMethodField()

    student_name = serializers.SerializerMethodField()
    student_admission_no = serializers.CharField(
        source="enrollment.student.admission_number", read_only=True
    )
    class_name = serializers.SerializerMethodField()
    standard_name = serializers.SerializerMethodField()
    section_name = serializers.SerializerMethodField()

    class Meta:
        model = StudentSubjectGroup
        fields = [
            "id",
            "enrollment_id",
            "enrollment_details",
            "subject_group_id",
            "subject_group_details",
            "student_name",
            "student_admission_no",
            "class_name",
            "standard_name",
            "section_name",
            "is_active",
            "created_at",
        ]
        read_only_fields = ["created_at"]

    def get_student_name(self, obj):
        """Get student's full name"""
        if obj.enrollment and obj.enrollment.student:
            return f"{obj.enrollment.student.first_name} {obj.enrollment.student.last_name}".strip()
        return ""

    def get_class_name(self, obj):
        """Get class name"""
        if obj.enrollment and obj.enrollment.academic_class:
            return f"{obj.enrollment.academic_class.standard.name} - {obj.enrollment.academic_class.section.name}"
        return ""

    def get_standard_name(self, obj):
        """Get standard name"""
        if (
            obj.enrollment
            and obj.enrollment.academic_class
            and obj.enrollment.academic_class.standard
        ):
            return obj.enrollment.academic_class.standard.name
        return ""

    def get_section_name(self, obj):
        """Get section name"""
        if (
            obj.enrollment
            and obj.enrollment.academic_class
            and obj.enrollment.academic_class.section
        ):
            return obj.enrollment.academic_class.section.name
        return ""

    def get_enrollment_details(self, obj):
        """Get enrollment details"""
        from .serializers import StudentEnrollmentSerializer

        return (
            StudentEnrollmentSerializer(obj.enrollment).data if obj.enrollment else None
        )

    def get_subject_group_details(self, obj):
        """Get subject group details"""
        from .serializers import SubjectGroupSerializer

        return (
            SubjectGroupSerializer(obj.subject_group).data
            if obj.subject_group
            else None
        )


def validate(self, data):
    """Validate that student is not already assigned to the same subject group"""
    enrollment = data.get("enrollment")
    subject_group = data.get("subject_group")

    # For partial updates, fall back to instance values if not provided
    if self.instance:
        enrollment = enrollment or self.instance.enrollment
        subject_group = subject_group or self.instance.subject_group

    if self.instance is None:  # Creating new
        if enrollment and subject_group:
            if StudentSubjectGroup.objects.filter(
                enrollment=enrollment, subject_group=subject_group
            ).exists():
                raise serializers.ValidationError(
                    "Student is already assigned to this subject group"
                )

    # Only validate standard match if both are present
    if enrollment and subject_group:
        if enrollment.academic_class.standard != subject_group.standard:
            raise serializers.ValidationError(
                "Subject group does not belong to the same standard as the student's class"
            )

    return data


class StudentSubjectGroupBulkCreateSerializer(serializers.Serializer):
    """Serializer for bulk creating student subject groups"""

    enrollment_ids = serializers.ListField(
        child=serializers.IntegerField(), min_length=1
    )
    subject_group_id = serializers.IntegerField()
    is_active = serializers.BooleanField(default=True)

    def validate(self, data):
        # Check if subject group exists
        try:
            subject_group = SubjectGroup.objects.get(id=data["subject_group_id"])
            data["subject_group"] = subject_group
        except SubjectGroup.DoesNotExist:
            raise serializers.ValidationError(
                {"subject_group_id": "Subject group not found"}
            )

        # Validate each enrollment
        enrollments = []
        for enrollment_id in data["enrollment_ids"]:
            try:
                enrollment = StudentEnrollment.objects.get(id=enrollment_id)

                # FIXED: Compare standard instead of academic_class
                if enrollment.academic_class.standard != subject_group.standard:
                    raise serializers.ValidationError(
                        f"Enrollment {enrollment_id} does not belong to the same standard as subject group"
                    )

                # Check if already assigned
                if StudentSubjectGroup.objects.filter(
                    enrollment=enrollment, subject_group=subject_group
                ).exists():
                    raise serializers.ValidationError(
                        f"Student in enrollment {enrollment_id} is already assigned to this subject group"
                    )

                enrollments.append(enrollment)
            except StudentEnrollment.DoesNotExist:
                raise serializers.ValidationError(
                    {"enrollment_ids": f"Enrollment {enrollment_id} not found"}
                )

        data["enrollments"] = enrollments
        return data

    def create(self, validated_data):
        """Create multiple student subject group assignments"""
        enrollments = validated_data["enrollments"]
        subject_group = validated_data["subject_group"]
        is_active = validated_data["is_active"]

        created_assignments = []
        with transaction.atomic():
            for enrollment in enrollments:
                assignment = StudentSubjectGroup.objects.create(
                    enrollment=enrollment,
                    subject_group=subject_group,
                    is_active=is_active,
                )
                created_assignments.append(assignment)

        return created_assignments


class StudentSubjectGroupBulkUpdateSerializer(serializers.Serializer):
    """Serializer for bulk updating student subject groups"""

    student_subject_group_ids = serializers.ListField(
        child=serializers.IntegerField(), min_length=1
    )
    is_active = serializers.BooleanField(required=True)

    def validate(self, data):
        # Check if all student subject group IDs exist
        student_subject_group_ids = data["student_subject_group_ids"]
        existing_ids = set(
            StudentSubjectGroup.objects.filter(
                id__in=student_subject_group_ids
            ).values_list("id", flat=True)
        )

        invalid_ids = set(student_subject_group_ids) - existing_ids
        if invalid_ids:
            raise serializers.ValidationError(
                {
                    "student_subject_group_ids": f"The following IDs do not exist: {list(invalid_ids)}"
                }
            )

        return data

    def update(self, instance, validated_data):
        # This serializer is for bulk update, not single instance update
        # So we don't implement this method
        pass

    def save(self):
        """Bulk update student subject groups"""
        student_subject_group_ids = self.validated_data["student_subject_group_ids"]
        is_active = self.validated_data["is_active"]

        with transaction.atomic():
            updated_count = StudentSubjectGroup.objects.filter(
                id__in=student_subject_group_ids
            ).update(is_active=is_active)

        return {"updated_count": updated_count, "is_active": is_active}


class SimpleStudentSubjectGroupSerializer(serializers.ModelSerializer):
    """Simplified serializer for dropdowns and lists"""

    student_name = serializers.SerializerMethodField()
    subject_group_name = serializers.CharField(
        source="subject_group.name", read_only=True
    )
    class_name = serializers.SerializerMethodField()

    class Meta:
        model = StudentSubjectGroup
        fields = [
            "id",
            "student_name",
            "subject_group_name",
            "class_name",
            "is_active",
            "created_at",
        ]

    def get_student_name(self, obj):
        if obj.enrollment and obj.enrollment.student:
            return f"{obj.enrollment.student.first_name} {obj.enrollment.student.last_name}".strip()
        return ""

    def get_class_name(self, obj):
        if obj.enrollment and obj.enrollment.academic_class:
            return f"{obj.enrollment.academic_class.standard.name} - {obj.enrollment.academic_class.section.name}"
        return ""


class SimpleStudentSubjectSerializer(serializers.ModelSerializer):
    """Simplified serializer for student subjects"""

    student_name = serializers.SerializerMethodField()
    student_admission_no = serializers.SerializerMethodField()
    student_roll_no = serializers.SerializerMethodField()
    subject_name = serializers.CharField(source="subject.name", read_only=True)
    subject_code = serializers.CharField(source="subject.code", read_only=True)
    subject_type = serializers.CharField(source="subject.subject_type", read_only=True)
    subject_type_display = serializers.CharField(
        source="subject.get_subject_type_display", read_only=True
    )
    academic_class_standard = serializers.SerializerMethodField()
    academic_class_section = serializers.SerializerMethodField()

    class Meta:
        model = StudentSubject
        fields = [
            "id",
            "student_name",
            "student_admission_no",
            "student_roll_no",
            "subject_name",
            "subject_code",
            "subject_type",
            "subject_type_display",
            "academic_class_standard",
            "academic_class_section",
            "is_active",
        ]

    def get_student_name(self, obj):
        try:
            if obj.enrollment and obj.enrollment.student:
                student = obj.enrollment.student
                # Check for available name fields
                if hasattr(student, "full_name") and student.full_name:
                    return student.full_name
                elif hasattr(student, "name") and student.name:
                    return student.name
                elif hasattr(student, "first_name"):
                    first_name = student.first_name or ""
                    last_name = getattr(student, "last_name", "") or ""
                    return f"{first_name} {last_name}".strip()
        except:
            pass
        return ""

    def get_student_admission_no(self, obj):
        try:
            if obj.enrollment and obj.enrollment.student:
                return getattr(obj.enrollment.student, "admission_number", "")
        except:
            pass
        return ""

    def get_student_roll_no(self, obj):
        try:
            if obj.enrollment:
                return getattr(obj.enrollment, "roll_number", "")
        except:
            pass
        return ""

    def get_academic_class_standard(self, obj):
        try:
            if obj.enrollment and obj.enrollment.academic_class:
                academic_class = obj.enrollment.academic_class
                if academic_class.standard:
                    return academic_class.standard.name
        except:
            pass
        return ""

    def get_academic_class_section(self, obj):
        try:
            if obj.enrollment and obj.enrollment.academic_class:
                academic_class = obj.enrollment.academic_class
                if academic_class.section:
                    return academic_class.section.code
        except:
            pass
        return ""


class StudentSubjectSerializer(serializers.ModelSerializer):
    """Main serializer for student subjects"""

    student_name = serializers.SerializerMethodField()
    student_admission_no = serializers.SerializerMethodField()
    student_roll_no = serializers.SerializerMethodField()
    subject_name = serializers.CharField(source="subject.name", read_only=True)
    subject_code = serializers.CharField(source="subject.code", read_only=True)
    subject_type = serializers.CharField(source="subject.subject_type", read_only=True)
    subject_type_display = serializers.CharField(
        source="subject.get_subject_type_display", read_only=True
    )
    academic_class_standard = serializers.SerializerMethodField()
    academic_class_section = serializers.SerializerMethodField()
    academic_class_name = serializers.SerializerMethodField()

    class Meta:
        model = StudentSubject
        fields = [
            "id",
            "enrollment",
            "enrollment_id",
            "subject",
            "subject_id",
            "student_name",
            "student_admission_no",
            "student_roll_no",
            "subject_name",
            "subject_code",
            "subject_type",
            "subject_type_display",
            "academic_class_standard",
            "academic_class_section",
            "academic_class_name",
            "is_active",
        ]
        read_only_fields = ["id"]

    def get_student_name(self, obj):
        try:
            if obj.enrollment and obj.enrollment.student:
                student = obj.enrollment.student
                if hasattr(student, "full_name") and student.full_name:
                    return student.full_name
                elif hasattr(student, "first_name"):
                    first_name = student.first_name or ""
                    last_name = getattr(student, "last_name", "") or ""
                    return f"{first_name} {last_name}".strip()
        except:
            pass
        return ""

    def get_student_admission_no(self, obj):
        try:
            if obj.enrollment and obj.enrollment.student:
                return getattr(obj.enrollment.student, "admission_number", "")
        except:
            pass
        return ""

    def get_student_roll_no(self, obj):
        try:
            if obj.enrollment:
                return getattr(obj.enrollment, "roll_number", "")
        except:
            pass
        return ""

    def get_academic_class_standard(self, obj):
        try:
            if obj.enrollment and obj.enrollment.academic_class:
                academic_class = obj.enrollment.academic_class
                if academic_class.standard:
                    return academic_class.standard.name
        except:
            pass
        return ""

    def get_academic_class_section(self, obj):
        try:
            if obj.enrollment and obj.enrollment.academic_class:
                academic_class = obj.enrollment.academic_class
                if academic_class.section:
                    return academic_class.section.code
        except:
            pass
        return ""

    def get_academic_class_name(self, obj):
        try:
            if obj.enrollment and obj.enrollment.academic_class:
                academic_class = obj.enrollment.academic_class
                standard_name = (
                    academic_class.standard.name if academic_class.standard else ""
                )
                section_code = (
                    academic_class.section.code if academic_class.section else ""
                )
                return f"{standard_name} - {section_code}"
        except:
            pass
        return ""

    def validate(self, data):
        """Validate that subject is elective or language"""
        subject = data.get("subject")
        if subject and subject.subject_type not in ["elective", "language"]:
            raise serializers.ValidationError(
                {"subject": "Only elective and language subjects can be assigned"}
            )

        # Check unique constraint
        enrollment = data.get("enrollment")
        if enrollment and subject:
            if StudentSubject.objects.filter(
                enrollment=enrollment, subject=subject
            ).exists():
                raise serializers.ValidationError(
                    {
                        "non_field_errors": "This student is already assigned to this subject"
                    }
                )

        return data


class StudentSubjectCreateSerializer(serializers.ModelSerializer):
    """Simplified serializer for creating student subjects"""

    class Meta:
        model = StudentSubject
        fields = ["enrollment", "subject", "is_active"]

    def validate(self, data):
        """Validate that subject is elective or language"""
        subject = data.get("subject")
        if subject and subject.subject_type not in ["elective", "language"]:
            raise serializers.ValidationError(
                {"subject": "Only elective and language subjects can be assigned"}
            )

        # Check unique constraint
        enrollment = data.get("enrollment")
        if enrollment and subject:
            if StudentSubject.objects.filter(
                enrollment=enrollment, subject=subject
            ).exists():
                raise serializers.ValidationError(
                    {
                        "non_field_errors": "This student is already assigned to this subject"
                    }
                )

        return data


class StudentSubjectBulkCreateSerializer(serializers.Serializer):
    """Serializer for bulk creation of student subjects"""

    enrollment_ids = serializers.ListField(
        child=serializers.IntegerField(), required=True
    )
    subject_id = serializers.IntegerField(required=True)
    is_active = serializers.BooleanField(default=True)

    def validate_subject_id(self, value):
        """Validate that subject exists and is elective/language"""
        try:
            subject = Subject.objects.get(id=value)
            if subject.subject_type not in ["elective", "language"]:
                raise serializers.ValidationError(
                    "Only elective and language subjects can be assigned"
                )
            return value
        except Subject.DoesNotExist:
            raise serializers.ValidationError("Subject not found")

    def validate_enrollment_ids(self, value):
        """Validate that enrollments exist"""
        existing_enrollments = StudentEnrollment.objects.filter(id__in=value).count()

        if existing_enrollments != len(value):
            raise serializers.ValidationError("One or more enrollments not found")

        return value


class StudentSubjectBulkUpdateSerializer(serializers.Serializer):
    """Serializer for bulk update of student subjects"""

    student_subject_ids = serializers.ListField(
        child=serializers.IntegerField(), required=True
    )
    is_active = serializers.BooleanField(required=True)

class SubjectTeacherSerializer(serializers.ModelSerializer):
    """Serializer for Subject Teacher model"""

    # Write-only fields for create/update
    academic_class_id = serializers.PrimaryKeyRelatedField(
        queryset=AcademicClass.objects.all(), source="academic_class", write_only=True
    )
    subject_id = serializers.PrimaryKeyRelatedField(
        queryset=Subject.objects.all(), source="subject", write_only=True
    )
    teacher_id = serializers.PrimaryKeyRelatedField(
        queryset=Teacher.objects.all(), source="teacher", write_only=True
    )

    # Read-only details fields - THESE ARE WHAT YOUR FRONTEND NEEDS
    academic_class_details = serializers.SerializerMethodField()
    subject_details = serializers.SerializerMethodField()
    teacher_details = serializers.SerializerMethodField()

    # Display fields (keeping existing ones)
    academic_class_name = serializers.SerializerMethodField()
    subject_name = serializers.CharField(source="subject.name", read_only=True)
    subject_code = serializers.CharField(source="subject.code", read_only=True)
    teacher_name = serializers.SerializerMethodField()

    class Meta:
        model = SubjectTeacher
        fields = [
            "id",
            "academic_class_id",
            "subject_id",
            "teacher_id",
            "academic_class_details",
            "subject_details",
            "teacher_details",
            "academic_class_name",
            "subject_name",
            "subject_code",
            "teacher_name",
            "is_active",
            "created_at",
        ]
        read_only_fields = ["created_at"]

    def get_academic_class_details(self, obj):
        """Get complete academic class details with nested info"""
        if not obj.academic_class:
            return None
        
        # Return all details frontend expects
        return {
            "id": obj.academic_class.id,
            "standard": obj.academic_class.standard.id if obj.academic_class.standard else None,
            "section": obj.academic_class.section.id if obj.academic_class.section else None,
            "academic_year": obj.academic_class.academic_year.id if obj.academic_class.academic_year else None,
            "standard_details": {
                "id": obj.academic_class.standard.id,
                "name": obj.academic_class.standard.name,
                "code": obj.academic_class.standard.code,
            } if obj.academic_class.standard else None,
            "section_details": {
                "id": obj.academic_class.section.id,
                "name": obj.academic_class.section.name,
                "code": obj.academic_class.section.code,
            } if obj.academic_class.section else None,
            "academic_year_details": {
                "id": obj.academic_class.academic_year.id,
                "name": obj.academic_class.academic_year.name,
                "is_active": obj.academic_class.academic_year.is_active,
            } if obj.academic_class.academic_year else None,
            "room_number": obj.academic_class.room_number,
            "current_strength": obj.academic_class.current_strength,
            "max_strength": obj.academic_class.max_strength,
            "is_active": obj.academic_class.is_active,
        }

    def get_subject_details(self, obj):
        """Get complete subject details"""
        if not obj.subject:
            return None
        
        # Return all details frontend expects
        return {
            "id": obj.subject.id,
            "name": obj.subject.name,
            "code": obj.subject.code,
            # "description": obj.subject.description,
            "subject_type": obj.subject.subject_type,
            "standard": obj.subject.standard.id if obj.subject.standard else None,
            "standard_name": obj.subject.standard.name if obj.subject.standard else None,
            "category": obj.subject.category.id if obj.subject.category else None,
            "category_name": obj.subject.category.name if obj.subject.category else None,
            "is_active": obj.subject.is_active,
        }

    def get_teacher_details(self, obj):
        """Get complete teacher details with full_name"""
        if not obj.teacher:
            return None
        
        first_name = getattr(obj.teacher, 'first_name', '') or ''
        last_name = getattr(obj.teacher, 'last_name', '') or ''
        full_name = f"{first_name} {last_name}".strip()

        profile_image = None
        try:
            if obj.teacher.profile_image and obj.teacher.profile_image.name:
                profile_image = obj.teacher.profile_image.url
        except (ValueError, AttributeError):
            profile_image = None

        user = getattr(obj.teacher, 'user', None)
        email = user.email if user else ''

        return {
            "id": obj.teacher.id,
            "first_name": first_name,
            "last_name": last_name,
            "full_name": full_name or getattr(obj.teacher, 'full_name', ''),
            "employee_id": getattr(obj.teacher, 'employee_id', ''),
            "designation": getattr(obj.teacher, 'designation', ''),
            "profile_image": profile_image,
            "phone": getattr(obj.teacher, 'phone', ''),
            "email": email,
            "is_active": obj.teacher.is_active,
        }
    def get_academic_class_name(self, obj):
        """Get formatted academic class name"""
        if obj.academic_class:
            standard = obj.academic_class.standard
            section = obj.academic_class.section
            academic_year = obj.academic_class.academic_year
            return f"{standard.name} - {section.code} ({academic_year.name})"
        return ""

    def get_teacher_name(self, obj):
        """Get teacher's full name (kept for backward compatibility)"""
        if obj.teacher:
            if hasattr(obj.teacher, "full_name") and obj.teacher.full_name:
                return obj.teacher.full_name
            elif hasattr(obj.teacher, "first_name"):
                first_name = obj.teacher.first_name or ""
                last_name = getattr(obj.teacher, "last_name", "") or ""
                return f"{first_name} {last_name}".strip()
        return ""

    def validate(self, data):
        """Validate subject teacher assignment"""
        academic_class = data.get("academic_class")
        subject = data.get("subject")
        teacher = data.get("teacher")

        # Check if all required fields are provided
        if not all([academic_class, subject, teacher]):
            raise serializers.ValidationError(
                "Academic class, subject, and teacher are all required"
            )

        # Check if academic class is active
        if not academic_class.is_active:
            raise serializers.ValidationError(
                {"academic_class_id": "Cannot assign to inactive academic class"}
            )

        # Check if subject is active
        if not subject.is_active:
            raise serializers.ValidationError(
                {"subject_id": "Cannot assign inactive subject"}
            )

        # Check if teacher is active
        if not teacher.is_active:
            raise serializers.ValidationError(
                {"teacher_id": "Cannot assign inactive teacher"}
            )

        # Check if subject belongs to the same standard as academic class
        if subject.standard != academic_class.standard:
            raise serializers.ValidationError(
                {
                    "subject_id": f"Subject '{subject.name}' does not belong to standard '{academic_class.standard.name}'"
                }
            )

        # Check for duplicate assignment (only for create operation)
        if self.instance is None:  # Creating new
            if SubjectTeacher.objects.filter(
                academic_class=academic_class, subject=subject
            ).exists():
                raise serializers.ValidationError(
                    {
                        "non_field_errors": [
                            "This subject is already assigned to a teacher in this class"
                        ]
                    }
                )
        else:  # Updating existing
            # Check for duplicate excluding current instance
            if (
                SubjectTeacher.objects.filter(
                    academic_class=academic_class, subject=subject
                )
                .exclude(id=self.instance.id)
                .exists()
            ):
                raise serializers.ValidationError(
                    {
                        "non_field_errors": [
                            "This subject is already assigned to another teacher in this class"
                        ]
                    }
                )

        return data

    def create(self, validated_data):
        """Create subject teacher assignment"""
        return SubjectTeacher.objects.create(**validated_data)

    def update(self, instance, validated_data):
        """Update subject teacher assignment"""
        instance.academic_class = validated_data.get(
            "academic_class", instance.academic_class
        )
        instance.subject = validated_data.get("subject", instance.subject)
        instance.teacher = validated_data.get("teacher", instance.teacher)
        instance.is_active = validated_data.get("is_active", instance.is_active)
        instance.save()
        return instance


class SubjectTeacherCreateUpdateSerializer(serializers.ModelSerializer):
    """Simplified serializer for create/update operations"""

    class Meta:
        model = SubjectTeacher
        fields = ["academic_class", "subject", "teacher", "is_active"]


class SubjectTeacherBulkCreateSerializer(serializers.Serializer):
    """Serializer for bulk creating subject teacher assignments"""

    academic_class_id = serializers.IntegerField(required=True)
    teacher_id = serializers.IntegerField(required=True)
    subject_ids = serializers.ListField(
        child=serializers.IntegerField(), min_length=1, required=True
    )
    is_active = serializers.BooleanField(default=True)

    def validate_academic_class_id(self, value):
        """Validate academic class"""
        try:
            academic_class = AcademicClass.objects.get(id=value, is_active=True)
            return academic_class
        except AcademicClass.DoesNotExist:
            raise serializers.ValidationError("Academic class not found or inactive")

    def validate_teacher_id(self, value):
        """Validate teacher"""
        try:
            teacher = Teacher.objects.get(id=value, is_active=True)
            return teacher
        except Teacher.DoesNotExist:
            raise serializers.ValidationError("Teacher not found or inactive")

    def validate_subject_ids(self, value):
        """Validate subjects"""
        subjects = Subject.objects.filter(id__in=value, is_active=True)

        if len(subjects) != len(value):
            raise serializers.ValidationError(
                "One or more subjects not found or inactive"
            )

        return subjects

    def validate(self, data):
        """Validate bulk assignment"""
        academic_class = data[
            "academic_class_id"
        ]  # This is actually the object after validation
        teacher = data["teacher_id"]  # This is actually the object after validation
        subjects = data["subject_ids"]  # This is actually the queryset after validation

        # Check if subjects belong to the same standard as academic class
        for subject in subjects:
            if subject.standard != academic_class.standard:
                raise serializers.ValidationError(
                    {
                        "subject_ids": [
                            f"Subject '{subject.name}' does not belong to standard '{academic_class.standard.name}'"
                        ]
                    }
                )

        # Check for existing assignments
        existing_assignments = SubjectTeacher.objects.filter(
            academic_class=academic_class, subject__in=subjects
        ).values_list("subject_id", flat=True)

        if existing_assignments:
            existing_subject_names = Subject.objects.filter(
                id__in=existing_assignments
            ).values_list("name", flat=True)
            raise serializers.ValidationError(
                {
                    "subject_ids": [
                        f"The following subjects are already assigned to teachers in this class: {', '.join(existing_subject_names)}"
                    ]
                }
            )

        return {
            "academic_class": academic_class,
            "teacher": teacher,
            "subjects": subjects,
            "is_active": data["is_active"],
        }

    def create(self, validated_data):
        """Create multiple subject teacher assignments"""
        academic_class = validated_data["academic_class"]
        teacher = validated_data["teacher"]
        subjects = validated_data["subjects"]
        is_active = validated_data["is_active"]

        created_assignments = []

        with transaction.atomic():
            for subject in subjects:
                assignment = SubjectTeacher.objects.create(
                    academic_class=academic_class,
                    subject=subject,
                    teacher=teacher,
                    is_active=is_active,
                )
                created_assignments.append(assignment)

        return created_assignments

class SimpleSubjectTeacherSerializer(serializers.ModelSerializer):
    """Simplified serializer for dropdowns and lists"""

    teacher_name = serializers.SerializerMethodField()
    teacher_employee_id = serializers.CharField(
        source="teacher.employee_id", read_only=True, allow_null=True
    )
    subject_name = serializers.CharField(source="subject.name", read_only=True)
    subject_code = serializers.CharField(source="subject.code", read_only=True)
    academic_class_name = serializers.SerializerMethodField()
    academic_year_name = serializers.CharField(
        source="academic_class.academic_year.name", read_only=True
    )

    class Meta:
        model = SubjectTeacher
        fields = [
            "id",
            "teacher_name",
            "teacher_employee_id",
            "subject_name",
            "subject_code",
            "academic_class_name",
            "academic_year_name",
            "is_active",
            "created_at",
        ]
        read_only_fields = ["created_at"]

    def get_teacher_name(self, obj):
        """Get teacher's full name"""
        if obj.teacher:
            if hasattr(obj.teacher, "full_name") and obj.teacher.full_name:
                return obj.teacher.full_name
            elif hasattr(obj.teacher, "first_name"):
                first_name = obj.teacher.first_name or ""
                last_name = getattr(obj.teacher, "last_name", "") or ""
                return f"{first_name} {last_name}".strip()
        return ""

    def get_academic_class_name(self, obj):
        """Get formatted academic class name"""
        if obj.academic_class:
            standard = obj.academic_class.standard
            section = obj.academic_class.section
            return f"{standard.name} - {section.code}"
        return ""
