from rest_framework import serializers
from .models import Teacher, Speciality, SchoolClass, Planning, LEVEL_CHOICES, Discount, Fee, PaymentPlan, PaymentMode
from Auth.models import Profile, ProfileRole
from Subscriptions.models import Student
from Establishment.models import Establishment
from Auth.serializers import ProfileRoleSerializer
from N3wtSchool import settings, bdd
from django.utils import timezone
import pytz

class SpecialitySerializer(serializers.ModelSerializer):
    updated_date_formatted = serializers.SerializerMethodField()

    class Meta:
        model = Speciality
        fields = '__all__'

    def get_updated_date_formatted(self, obj):
        utc_time = timezone.localtime(obj.updated_date) # Convert to local time
        local_tz = pytz.timezone(settings.TZ_APPLI)
        local_time = utc_time.astimezone(local_tz)

        return local_time.strftime("%d-%m-%Y %H:%M")

class TeacherDetailSerializer(serializers.ModelSerializer):
    specialities = SpecialitySerializer(many=True, read_only=True)

    class Meta:
        model = Teacher
        fields = ['id', 'last_name', 'first_name', 'email', 'specialities']

class TeacherSerializer(serializers.ModelSerializer):
    specialities = serializers.PrimaryKeyRelatedField(queryset=Speciality.objects.all(), many=True, required=False)
    specialities_details = serializers.SerializerMethodField()
    updated_date_formatted = serializers.SerializerMethodField()
    role_type = serializers.SerializerMethodField()
    associated_profile_email = serializers.SerializerMethodField()
    profile_role = serializers.PrimaryKeyRelatedField(queryset=ProfileRole.objects.all(), required=False)
    profile_role_data = ProfileRoleSerializer(write_only=True, required=False)

    class Meta:
        model = Teacher
        fields = '__all__'

    def create(self, validated_data):
        specialities_data = validated_data.pop('specialities', None)
        profile_role_data = validated_data.pop('profile_role_data', None)
        profile_role = validated_data.pop('profile_role', None)

        if profile_role_data:
            establishment_id = profile_role_data.pop('establishment').id
            profile_role_data['establishment'] = establishment_id

            # Créer l'instance de ProfileRole
            profile_role_serializer = ProfileRoleSerializer(data=profile_role_data)
            profile_role_serializer.is_valid(raise_exception=True)
            profile_role = profile_role_serializer.save()
        elif profile_role:
            profile_role = ProfileRole.objects.get(id=profile_role.id)

        # Créer l'enseignant avec l'instance de ProfileRole
        teacher = Teacher.objects.create(profile_role=profile_role, **validated_data)
        if specialities_data:
            teacher.specialities.set(specialities_data)
        teacher.save()
        return teacher

    def update(self, instance, validated_data):
        specialities_data = validated_data.pop('specialities', [])
        profile_role_data = validated_data.pop('profile_role_data', None)
        profile_role = validated_data.pop('profile_role', None)

        if profile_role_data:
            establishment_id = profile_role_data.pop('establishment').id
            profile_role_data['establishment'] = establishment_id
            profile_role_serializer = ProfileRoleSerializer(instance.profile_role, data=profile_role_data)
            profile_role_serializer.is_valid(raise_exception=True)
            profile_role_serializer.save()
        elif profile_role:
            instance.profile_role = ProfileRole.objects.get(id=profile_role.id)

        instance.last_name = validated_data.get('last_name', instance.last_name)
        instance.first_name = validated_data.get('first_name', instance.first_name)
        instance.email = validated_data.get('email', instance.email)
        instance.save()
        if specialities_data:
            instance.specialities.set(specialities_data)
        return instance

    def get_updated_date_formatted(self, obj):
        utc_time = timezone.localtime(obj.updated_date) # Convert to local time
        local_tz = pytz.timezone(settings.TZ_APPLI)
        local_time = utc_time.astimezone(local_tz)
        return local_time.strftime("%d-%m-%Y %H:%M")

    def get_role_type(self, obj):
        profile_role = obj.profile_role
        return {'role_type': profile_role.role_type, 'establishment': profile_role.establishment.name}

    def get_specialities_details(self, obj):
        return [{'id': speciality.id, 'name': speciality.name, 'color_code': speciality.color_code} for speciality in obj.specialities.all()]

    def get_associated_profile_email(self, obj):
        if obj.profile_role and obj.profile_role.profile:
            return obj.profile_role.profile.email
        return None

class PlanningSerializer(serializers.ModelSerializer):
    class Meta:
        model = Planning
        fields = ['id', 'level', 'schedule']

    def to_internal_value(self, data):
        internal_value = super().to_internal_value(data)
        internal_value['schedule'] = data.get('schedule', {})
        return internal_value

class SchoolClassSerializer(serializers.ModelSerializer):
    updated_date_formatted = serializers.SerializerMethodField()
    teachers = serializers.PrimaryKeyRelatedField(queryset=Teacher.objects.all(), many=True, required=False)
    establishment = serializers.PrimaryKeyRelatedField(queryset=Establishment.objects.all(), required=False)
    teachers_details = serializers.SerializerMethodField()
    students = serializers.PrimaryKeyRelatedField(queryset=Student.objects.all(), many=True, required=False)

    class Meta:
        model = SchoolClass
        fields = '__all__'

    def create(self, validated_data):
        teachers_data = validated_data.pop('teachers', [])
        levels_data = validated_data.pop('levels', [])
        plannings_data = validated_data.pop('plannings', [])

        school_class = SchoolClass.objects.create(
            atmosphere_name=validated_data.get('atmosphere_name', ''),
            age_range=validated_data.get('age_range', []),
            number_of_students=validated_data.get('number_of_students', 0),
            teaching_language=validated_data.get('teaching_language', ''),
            school_year=validated_data.get('school_year', ''),
            levels=levels_data,
            type=validated_data.get('type', 1),
            time_range=validated_data.get('time_range', ['08:30', '17:30']),
            opening_days=validated_data.get('opening_days', [1, 2, 4, 5]),
            establishment=validated_data.get('establishment', None)
        )

        school_class.teachers.set(teachers_data)

        for planning_data in plannings_data:
            Planning.objects.create(
                school_class=school_class,
                level=planning_data['level'],
                schedule=planning_data.get('schedule', {})
            )

        return school_class

    def update(self, instance, validated_data):
        teachers_data = validated_data.pop('teachers', [])
        levels_data = validated_data.pop('levels', [])
        plannings_data = validated_data.pop('plannings', [])

        instance.atmosphere_name = validated_data.get('atmosphere_name', instance.atmosphere_name)
        instance.age_range = validated_data.get('age_range', instance.age_range)
        instance.number_of_students = validated_data.get('number_of_students', instance.number_of_students)
        instance.teaching_language = validated_data.get('teaching_language', instance.teaching_language)
        instance.school_year = validated_data.get('school_year', instance.school_year)
        instance.levels = levels_data
        instance.type = validated_data.get('type', instance.type)
        instance.time_range = validated_data.get('time_range', instance.time_range)
        instance.opening_days = validated_data.get('opening_days', instance.opening_days)
        instance.establishment = validated_data.get('establishment', instance.establishment)

        instance.save()
        instance.teachers.set(teachers_data)

        existing_plannings = {planning.level: planning for planning in instance.plannings.all()}

        for planning_data in plannings_data:
            level = planning_data['level']
            if level in existing_plannings:
                # Update existing planning
                planning = existing_plannings[level]
                planning.schedule = planning_data.get('schedule', planning.schedule)
                planning.save()
            else:
                # Create new planning if level not existing
                Planning.objects.create(
                    school_class=instance,
                    level=level,
                    schedule=planning_data.get('schedule', {})
                )

        return instance

    def get_teachers_details(self, obj):
        return [{'id': teacher.id, 'last_name': teacher.last_name, 'first_name': teacher.first_name} for teacher in obj.teachers.all()]

    def get_updated_date_formatted(self, obj):
        utc_time = timezone.localtime(obj.updated_date)
        local_tz = pytz.timezone(settings.TZ_APPLI)
        local_time = utc_time.astimezone(local_tz)
        return local_time.strftime("%d-%m-%Y %H:%M")

class DiscountSerializer(serializers.ModelSerializer):
    updated_at_formatted = serializers.SerializerMethodField()
    establishment = serializers.PrimaryKeyRelatedField(queryset=Establishment.objects.all(), required=False)
    class Meta:
        model = Discount
        fields = '__all__'

    def get_updated_at_formatted(self, obj):
        utc_time = timezone.localtime(obj.updated_at)
        local_tz = pytz.timezone(settings.TZ_APPLI)
        local_time = utc_time.astimezone(local_tz)
        return local_time.strftime("%d-%m-%Y %H:%M")

class FeeSerializer(serializers.ModelSerializer):
    updated_at_formatted = serializers.SerializerMethodField()
    establishment = serializers.PrimaryKeyRelatedField(queryset=Establishment.objects.all(), required=False)

    class Meta:
        model = Fee
        fields = '__all__'

    def get_updated_at_formatted(self, obj):
        utc_time = timezone.localtime(obj.updated_at)
        local_tz = pytz.timezone(settings.TZ_APPLI)
        local_time = utc_time.astimezone(local_tz)
        return local_time.strftime("%d-%m-%Y %H:%M")

class PaymentPlanSerializer(serializers.ModelSerializer):
    class Meta:
        model = PaymentPlan
        fields = '__all__'

class PaymentModeSerializer(serializers.ModelSerializer):
    class Meta:
        model = PaymentMode
        fields = '__all__'