from knox.models import AuthToken
from django.contrib.auth import authenticate
from api.models import User, Atoll, Island
from django.contrib.auth.models import Permission

from rest_framework import serializers


class CustomUserSerializer(serializers.ModelSerializer):
    """serializer for the user object"""

    user_permissions = serializers.SerializerMethodField()

    def get_user_permissions(self, instance):
        # Fetch user's direct permissions
        user_permissions = instance.user_permissions.all()

        # Fetch permissions from groups
        group_permissions = instance.groups.values_list("permissions", flat=True)

        # Combine both permissions
        all_permissions = user_permissions | Permission.objects.filter(
            id__in=group_permissions
        )

        return [
            {"id": permission.id, "name": permission.name}
            for permission in all_permissions.distinct()
        ]

    class Meta:  # type: ignore
        model = User
        fields = (
            "id",
            "username",
            "user_permissions",
            "id_card",
            "wallet_balance",
            "mobile",
            "first_name",
            "last_name",
            "email",
            "last_login",
            "date_joined",
            "is_superuser",
        )


class CustomReadOnlyUserSerializer(serializers.ModelSerializer):
    """serializer for the user object"""

    class Meta:  # type: ignore
        model = User
        # fields = "__all__"
        fields = (
            "id",
            "email",
            "first_name",
            "last_name",
            "username",
            "mobile",
            "address",
            "id_card",
        )


class CustomReadOnlyUserByIDCardSerializer(serializers.ModelSerializer):
    """serializer for the user object"""

    class Meta:  # type: ignore
        model = User
        # fields = "__all__"
        fields = ("id_card",)


class CustomUserByWalletBalanceSerializer(serializers.ModelSerializer):
    """serializer for the user object"""

    class Meta:  # type: ignore
        model = User
        # fields = "__all__"
        fields = ("wallet_balance",)


class UserSerializer(serializers.ModelSerializer):
    """serializer for the user object"""

    class Meta:  # type: ignore
        model = User
        fields = ("username", "password")
        extra_kwargs = {"password": {"write_only": True, "min_length": 5}}

    def create(self, validated_data):
        return User.objects.create_user(**validated_data)


class AuthSerializer(serializers.Serializer):
    """serializer for the user authentication object"""

    username = serializers.CharField()
    password = serializers.CharField(
        style={"input_type": "password"}, trim_whitespace=False
    )

    def validate(self, attrs):
        username = attrs.get("username")
        password = attrs.get("password")

        user = authenticate(
            request=self.context.get("request"), username=username, password=password
        )

        if not user:
            msg = "Unable to authenticate with provided credentials"
            raise serializers.ValidationError(msg, code="authentication")

        attrs["user"] = user
        return user


class KnoxTokenSerializer(serializers.ModelSerializer):
    """serializer for the auth token object"""

    class Meta:  # type: ignore
        model = AuthToken
        fields = "__all__"


class IslandSerializer(serializers.ModelSerializer):
    class Meta:  # type: ignore
        model = Island
        fields = "__all__"


class AtollSerializer(serializers.ModelSerializer):
    islands = IslandSerializer(many=True, read_only=True)

    class Meta:  # type: ignore
        model = Atoll
        fields = "__all__"
        depth = 2