from batch_year.serializers import YearListSerializer
from course.models import Course
from course.serializers import CourseSerializer
from rest_framework import serializers
from .models import Routine, RoutineData
from datetime import date
from semester.serializers import SemesterSerializer
from departments.serializers import DepartmentListSerializer
from batch.serializers import BatchSerializer
from status.serializers import StatusSerializer
from teacher_management.models import Teacher
from teacher_management.serializers import TeacherSerializer
from classroom.serializers import ClassroomListSerializer
from status.models import Status
from classroom.models import Classroom
from timeslot.models import TimeSlot
from timeslot.serializers import TimeSlotSerializer
from days.serializers import DaySerializer
from organization.serializers import OrganizationSerializer

class CourseCodeSerializer(CourseSerializer):
    course_code = serializers.CharField(source='code')

    class Meta(CourseSerializer.Meta):
        fields = ('id', 'name', 'course_code', 'credit_hours', 'slug', 'credit', 'created_at', 'updated_at', 'teachers', 'status')

class TeacherCodeSerializer(TeacherSerializer):
    teacher_code = serializers.CharField(source='code')
    name = serializers.SerializerMethodField()

    class Meta(TeacherSerializer.Meta):
        fields = ('teacher_id', 'first_name', 'last_name', 'name', 'teacher_code', 'slug', 'status')

    def get_name(self, obj):
        return f"{obj.first_name} {obj.last_name or ''}".strip()

class SimpleRoutineSerializer(serializers.ModelSerializer):
    batch = BatchSerializer()
    semester = SemesterSerializer()
    class Meta:
        model = Routine
        fields = ('id', 'name', 'slug', 'batch', 'semester')


class RoutineDataListSerializer(serializers.ModelSerializer):
    teacher = TeacherCodeSerializer()
    # routine = SimpleRoutineSerializer()
    status = StatusSerializer()
    course = CourseCodeSerializer()
    room = ClassroomListSerializer()
    day = DaySerializer(source='day_of_week')
    timeslot = TimeSlotSerializer(source='time_slot')
    
    batch = serializers.SerializerMethodField()
    semester = serializers.SerializerMethodField()

    class Meta:
        model = RoutineData
        fields = ('id', 'day', 'timeslot', 'course', 'teacher', 'room', 'status', 'batch', 'semester')

    def get_batch(self, obj):
        if obj.routine and obj.routine.batch:
            return BatchSerializer(obj.routine.batch).data
        return None

    def get_semester(self, obj):
        if obj.routine and obj.routine.semester:
            return SemesterSerializer(obj.routine.semester).data
        return None
        
class RoutineRoomDataSerializer(serializers.ModelSerializer):
    class Meta:
        model = RoutineData
        fields = ('room', )

class RoutineSerializer(serializers.ModelSerializer):
    routine_data = RoutineDataListSerializer(many=True, read_only=True)
    status = serializers.SlugRelatedField(
        queryset=Status.objects.all(),
        slug_field='slug'
    )
    organization = OrganizationSerializer(read_only=True)

    class Meta:
        model = Routine
        fields = ('name', 'department', 'batch', 'year', 'semester', 'status', 'routine_year', 'routine_data', 'effective_from', 'organization')

    def validate(self, data):
        status = data.get('status')
        # If status is not provided in partial update, get it from instance
        if status is None and self.instance:
            status = self.instance.status
            
        effective_from = data.get('effective_from')
        # If effective_from is not provided in partial update, get it from instance
        if effective_from is None and self.instance:
            effective_from = self.instance.effective_from

        if status and status.slug == 'published-routine':
            if not effective_from:
                raise serializers.ValidationError({'effective_from': 'Effective date is required when publishing.'})
            if effective_from <= date.today():
                raise serializers.ValidationError({'effective_from': 'Effective date must be a future date when publishing.'})
        
        return data

class RoutineListSerializer(serializers.ModelSerializer):
    department = DepartmentListSerializer()
    batch = BatchSerializer()
    year = YearListSerializer()
    semester = SemesterSerializer()
    status = StatusSerializer()
    routine_data = RoutineDataListSerializer(many=True, read_only=True)
    organization = OrganizationSerializer(read_only=True)

    all_teachers = serializers.SerializerMethodField()
    all_courses = serializers.SerializerMethodField()

    class Meta:
        model = Routine
        fields = ('name', 'slug', 'department', 'batch', 'year', 'semester', 'status', 'routine_year', 'routine_data', 'created_at', 'updated_at', 'all_teachers', 'all_courses', 'effective_from', 'organization')

    def get_all_teachers(self, obj):
        teachers = set()
        for rd in obj.routine_data.all():
            if rd.teacher:
                teachers.add(rd.teacher)
        return TeacherSerializer(list(teachers), many=True).data

    def get_all_courses(self, obj):
        courses = set()
        for rd in obj.routine_data.all():
            if rd.course:
                courses.add(rd.course)
        return CourseSerializer(list(courses), many=True).data


class SaveRoutineDataSerializer(serializers.ModelSerializer):
    teacher = serializers.SlugRelatedField(
        queryset=Teacher.objects.all(),
        slug_field='slug'
    )
    routine = serializers.SlugRelatedField(
        queryset=Routine.objects.all(),
        slug_field='slug'
    )
    course = serializers.PrimaryKeyRelatedField(
        queryset=Course.objects.all()
    )
    # room = serializers.PrimaryKeyRelatedField(
    #     queryset=Classroom.objects.all(),
    #     required=False,
    #     allow_null=True
    # )

    class Meta:
        model = RoutineData
        fields = ('day_of_week', 'time_slot', 'course', 'teacher', 'routine', 'slot_count')

class UpdateRoomSerializer(serializers.Serializer):
    day_of_week = serializers.IntegerField()
    time_slot = serializers.IntegerField()
    routine = serializers.SlugRelatedField(
        queryset=Routine.objects.all(),
        slug_field='slug'
    )
    room = serializers.PrimaryKeyRelatedField(queryset=Classroom.objects.all(), allow_null=True, required=False)
