from typing import List

from rest_framework import serializers
from rest_framework.renderers import JSONRenderer

from vbv_lernwelt.core.models import Country, Organisation, User
from vbv_lernwelt.course.models import CourseSessionUser
from vbv_lernwelt.course_session_group.models import CourseSessionGroup


def create_json_from_objects(objects, serializer_class, many=True) -> str:
    serializer = serializer_class(objects, many=many)
    return JSONRenderer().render(serializer.data).decode("utf-8")


class CountrySerializer(serializers.ModelSerializer):
    id = serializers.IntegerField(source="country_id", read_only=True)
    name = serializers.SerializerMethodField()

    class Meta:
        model = Country
        fields = ["id", "name"]

    def get_name(self, obj):
        language = self.context.get("langauge")

        if language == "fr":
            return obj.name_fr
        elif language == "it":
            return obj.name_it

        return obj.name_de

    def to_internal_value(self, data):
        country_id = data.get("id")
        if country_id is not None:
            try:
                country = Country.objects.get(country_id=country_id)
                return {"id": country.country_id, "name": self.get_name(country)}
            except Country.DoesNotExist:
                raise serializers.ValidationError({"id": "Invalid country ID"})
        return super().to_internal_value(data)


class UserSerializer(serializers.ModelSerializer):
    course_session_experts = serializers.SerializerMethodField()
    country = CountrySerializer()
    organisation_country = CountrySerializer()

    class Meta:
        model = User
        fields = [
            "id",
            "first_name",
            "last_name",
            "email",
            "username",
            "avatar_url",
            "organisation",
            "is_superuser",
            "course_session_experts",
            "language",
            "invoice_address",
            "street",
            "street_number",
            "postal_code",
            "city",
            "country",
            "organisation_detail_name",
            "organisation_street",
            "organisation_street_number",
            "organisation_postal_code",
            "organisation_city",
            "organisation_country",
        ]
        read_only_fields = [
            "id",
            "is_superuser",
            "first_name",
            "last_name",
            "email",
            "username",
        ]

    def get_course_session_experts(self, obj: User) -> List[str]:
        supervisor_in_session_ids = set(
            CourseSessionGroup.objects.filter(supervisor=obj).values_list(
                "course_session__id", flat=True
            )
        )

        expert_in_session_ids = set(
            CourseSessionUser.objects.filter(
                role=CourseSessionUser.Role.EXPERT, user=obj
            ).values_list("course_session__id", flat=True)
        )

        return [str(_id) for _id in (supervisor_in_session_ids | expert_in_session_ids)]

    def update(self, instance, validated_data):
        country_data = validated_data.pop("country", None)
        organisation_country_data = validated_data.pop("organisation_country", None)

        for attr, value in validated_data.items():
            setattr(instance, attr, value)

        if country_data is not None:
            country_id = country_data.get("id")
            country_instance = Country.objects.filter(country_id=country_id).first()
            instance.country = country_instance

        if organisation_country_data is not None:
            organisation_country_id = organisation_country_data.get("id")
            organisation_country_instance = Country.objects.filter(
                country_id=organisation_country_id
            ).first()
            instance.organisation_country = organisation_country_instance

        instance.save()
        return instance


class OrganisationSerializer(serializers.ModelSerializer):
    id = serializers.IntegerField(source="organisation_id", read_only=True)
    name = serializers.SerializerMethodField()

    class Meta:
        model = Organisation
        fields = ["id", "name"]

    def get_name(self, obj):
        language = self.context.get("langauge")

        if language == "fr":
            return obj.name_fr
        elif language == "it":
            return obj.name_it

        return obj.name_de
