from rest_framework import serializers

from users.models import User
from users import cons
from tools.tools import decode_uid, encode_uid
from django.contrib.auth.tokens import default_token_generator


class RegisterSerializer(serializers.ModelSerializer):
    password = serializers.CharField(
        write_only=True,
        required=False,
        min_length=8,
        style={"input_type": "password"},
    )
    email = serializers.CharField(
        write_only=True
    )
    first_name = serializers.CharField(
        write_only=True
    )
    last_name = serializers.CharField(
        write_only=True
    )
    #todo
    # avatar = serializers.ImageField(allow_empty_file=True, source="profile.avatar", read_only=True)

    class Meta:
        model = User
        fields = (
            "email",
            "first_name",
            "last_name",
            "password"
        )

class UserSerializer(serializers.ModelSerializer):

    password = serializers.CharField(
        write_only=True,
        required=False,
        min_length=8,
        style={"input_type": "password"},
    )
    #todo
    # avatar = serializers.ImageField(allow_empty_file=True, source="profile.avatar", read_only=True)

    class Meta:
        model = User
        fields = (
            "id",
            "email",
            "first_name",
            "last_name",
            "is_active",
            "password"
        )


class UserPasswordResetSerializer(serializers.Serializer):
    email = serializers.CharField()

    def validate(self, data):
        email = data.get("email")
        user = User.objects.filter(email__iexact=email)
        if not user:
            msg = {"detail": cons.USER_WITH_FOLLOWING_EMAIL_DOES_NOT_EXIST}
            raise serializers.ValidationError(msg)
        self.do_actions(data)
        return data

    def do_actions(self, validated_data):
        return User.objects.reset_password(validated_data)


class UserPasswordResetConfirmSerializer(serializers.Serializer):
    uid = serializers.CharField()
    token = serializers.CharField()
    code = serializers.IntegerField()
    new_password = serializers.CharField()
    repeat_new_password = serializers.CharField()

    def validate(self, attrs):
        token = attrs["token"]
        code = attrs["code"]
        token_generator = default_token_generator
        if not token_generator.check_token(self.user, token):
            raise serializers.ValidationError(cons.INVALID_TOKEN)
        if self.user.reset_code != code:
            raise serializers.ValidationError(cons.INVALID_CODE)
        self.validate_new_passwords(attrs)
        self.do_actions(attrs)
        return attrs

    def validate_uid(self, value):
        try:
            uid = decode_uid(value)
            self.user = User.objects.get(pk=uid)
        except (User.DoesNotExist, ValueError, TypeError, OverflowError):
            raise serializers.ValidationError(cons.INVALID_UID)
        return value

    def validate_new_passwords(self, attrs):
        new_password = attrs["new_password"]
        repeat_new_password = attrs["repeat_new_password"]
        if new_password != repeat_new_password:
            raise serializers.ValidationError(cons.PASSWORDS_ARE_NOT_THE_SAME)
        return attrs

    def do_actions(self, validated_data):
        return User.objects.confirm_reset_password(**validated_data)