# serializers.py
from rest_framework import serializers
from .models import FeeCategory, FeeComponent, ClassFeeStructure, StudentFeeAssignment
from academics.serializers import AcademicClassSerializer, AcademicTermSerializer
from people.serializers import StudentSerializer
from django.utils import timezone


class FeeCategorySerializer(serializers.ModelSerializer):
    """
    Serializer for FeeCategory model
    """

    fee_components_count = serializers.SerializerMethodField()

    class Meta:
        model = FeeCategory
        fields = [
            "id",
            "name",
            "description",
            "is_active",
            "fee_components_count",
            "created_at",
            "updated_at",
        ]
        read_only_fields = ["id", "created_at", "updated_at"]

    def get_fee_components_count(self, obj):
        return obj.fee_components.count()

    def validate_name(self, value):
        if len(value.strip()) < 2:
            raise serializers.ValidationError(
                "Category name must be at least 2 characters long"
            )
        return value.strip()


class FeeComponentSerializer(serializers.ModelSerializer):
    """
    Serializer for FeeComponent model
    """

    category_name = serializers.CharField(source="category.name", read_only=True)

    class Meta:
        model = FeeComponent
        fields = [
            "id",
            "name",
            "code",
            "category",
            "category_name",
            "description",
            "calculation_type",
            "is_mandatory",
            "is_recurring",
            "late_fee_applicable",
            "late_fee_type",
            "late_fee_value",
            "grace_days",
            "is_active",
            "created_at",
            "updated_at",
        ]
        read_only_fields = ["id", "created_at", "updated_at"]

    def validate_code(self, value):
        if not value.isupper():
            raise serializers.ValidationError("Code must be in uppercase letters")
        return value

    def validate(self, data):
        if data.get("late_fee_applicable"):
            if not data.get("late_fee_type"):
                raise serializers.ValidationError(
                    {
                        "late_fee_type": "Late fee type is required when late fee is applicable"
                    }
                )
            if data.get("late_fee_value") is None:
                raise serializers.ValidationError(
                    {
                        "late_fee_value": "Late fee value is required when late fee is applicable"
                    }
                )
            if data.get("late_fee_value", 0) <= 0:
                raise serializers.ValidationError(
                    {"late_fee_value": "Late fee value must be greater than 0"}
                )
        return data


class ClassFeeStructureSerializer(serializers.ModelSerializer):
    """
    Serializer for ClassFeeStructure model
    """

    academic_class_name = serializers.CharField(
        source="academic_class.name", read_only=True
    )
    fee_component_name = serializers.CharField(
        source="fee_component.name", read_only=True
    )
    fee_component_code = serializers.CharField(
        source="fee_component.code", read_only=True
    )
    academic_term_name = serializers.CharField(
        source="academic_term.name", read_only=True
    )

    class Meta:
        model = ClassFeeStructure
        fields = [
            "id",
            "academic_class",
            "academic_class_name",
            "fee_component",
            "fee_component_name",
            "fee_component_code",
            "academic_term",
            "academic_term_name",
            "amount",
            "due_date",
            "late_fee_applicable",
            "notes",
            "is_active",
            "created_at",
            "updated_at",
        ]
        read_only_fields = ["id", "created_at", "updated_at"]

    def validate_amount(self, value):
        if value <= 0:
            raise serializers.ValidationError("Amount must be greater than 0")
        return value

    def validate_due_date(self, value):
        if value < timezone.now().date():
            raise serializers.ValidationError("Due date cannot be in the past")
        return value


class StudentFeeAssignmentSerializer(serializers.ModelSerializer):
    """
    Serializer for StudentFeeAssignment model
    """

    student_name = serializers.CharField(source="student.full_name", read_only=True)
    student_roll_number = serializers.CharField(
        source="student.roll_number", read_only=True
    )
    fee_component_name = serializers.CharField(
        source="class_fee_structure.fee_component.name", read_only=True
    )
    base_amount = serializers.DecimalField(
        source="class_fee_structure.amount",
        max_digits=10,
        decimal_places=2,
        read_only=True,
    )
    final_amount = serializers.SerializerMethodField()

    # New fields for class details
    academic_class_id = serializers.IntegerField(
        source="enrollment.academic_class.id", read_only=True
    )
    academic_class_name = serializers.CharField(
        source="enrollment.academic_class.name", read_only=True
    )
    academic_class_standard = serializers.CharField(
        source="enrollment.academic_class.standard.name", read_only=True
    )
    academic_class_section = serializers.CharField(
        source="enrollment.academic_class.section.name", read_only=True
    )

    class Meta:
        model = StudentFeeAssignment
        fields = [
            "id",
            "student",
            "student_name",
            "student_roll_number",
            "enrollment",
            "class_fee_structure",
            "fee_component_name",
            "base_amount",
            "final_amount",
            "discount_type",
            "discount_value",
            "due_date_override",
            "reason",
            "is_active",
            "created_at",
            "updated_at",
            # New fields
            "academic_class_id",
            "academic_class_name",
            "academic_class_standard",
            "academic_class_section",
        ]
        read_only_fields = ["id", "created_at", "updated_at"]

    def get_final_amount(self, obj):
        return obj.calculate_final_amount()

    def validate_discount_value(self, value):
        if value and value < 0:
            raise serializers.ValidationError("Discount value cannot be negative")
        return value

    def validate(self, data):
        if data.get("discount_type") and not data.get("discount_value"):
            raise serializers.ValidationError(
                {
                    "discount_value": "Discount value is required when discount type is specified"
                }
            )

        if (
            data.get("discount_type") == "percentage"
            and data.get("discount_value", 0) > 100
        ):
            raise serializers.ValidationError(
                {"discount_value": "Percentage discount cannot exceed 100%"}
            )

        return data
