from rest_framework import serializers

from authenticate import conf, validators as authenticate_validators
from authenticate.models import User
from payment.models import UserBalanceHistory
from utils import validators as main_validators


class UserSerializerForAuthenticateAndCollaboratorsAndInstitute(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ['first_name', 'last_name', 'username', 'email', 'poster', 'phone', 'recovery_phone', 'image', 'image_thumbnail', 'info']


class PublicUserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ['first_name', 'last_name', 'image_thumbnail']


class SendAVerificationCodeInputSerializer(serializers.Serializer):
    email = serializers.CharField(max_length=254, validators=[
        authenticate_validators.email_validator], required=False)
    phone = serializers.CharField(required=False)
    username = serializers.CharField(required=False)

    def validate_phone(self, value):
        value = authenticate_validators.phone_validator(value)
        return value

    def validate(self, data):
        authenticate_validators.make_email_or_phone_or_username_required_validator(data)
        return data


class UserSerializerForCollaborators(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ['first_name', 'last_name', 'image', 'image_thumbnail', 'email', 'phone']


class InputLoginOrVerificationCodeCheckSerializer(serializers.Serializer):
    email = serializers.CharField(max_length=254, validators=[
        authenticate_validators.email_validator], required=False)
    phone = serializers.CharField(required=False)
    code = serializers.CharField(validators=[authenticate_validators.code_validator])

    def validate_phone(self, value):
        value = authenticate_validators.phone_validator(value)
        return value

    def validate(self, data):
        authenticate_validators.make_email_or_phone_required_validator(data)
        return data


class InputRegisterUserSerializer(serializers.Serializer):
    username = serializers.CharField(required=False)
    email = serializers.CharField(max_length=254, validators=[
        authenticate_validators.email_validator], required=False)
    phone = serializers.CharField(required=False)
    password = serializers.CharField(
        validators=[authenticate_validators.password_validator], required=False)
    code = serializers.CharField(
        validators=[authenticate_validators.code_validator])
    first_name = serializers.CharField(allow_null=False)
    last_name = serializers.CharField(allow_null=False)
    image = serializers.ImageField(required=False)

    def validate_username(self, value):
        main_validators.name_validator(
            name=value, min_length=3, max_length=100)
        return value

    def validate_first_name(self, value):
        main_validators.name_validator(name=value, min_length=3, max_length=46)
        return value

    def validate_last_name(self, value):
        main_validators.name_validator(name=value, min_length=3, max_length=46)
        return value

    def validate_image(self, value):
        main_validators.image_validetor(image=value, image_size_as_MB=conf.maximum_profile_image_size_MG,
                                        format=conf.allowed_formats_for_authenticate_profile_image,
                                        max_side=conf.maximum_side_size_for_authenticate_image)

        return value

    def validate_phone(self, value):
        value = authenticate_validators.phone_validator(value)
        return value

    def validate(self, data):
        authenticate_validators.make_email_or_phone_required_validator(data)
        return data


class InputLoginWithPasswordSerializer(serializers.Serializer):
    """
    This serializer class takes email and password from user
    and passed it to LoginAPIView to do some works on them.
    """
    username = serializers.CharField(required=False)
    email = serializers.CharField(max_length=254, validators=[
        authenticate_validators.email_validator], required=False)
    phone = serializers.CharField(required=False)
    # don't put password validators in login API
    password = serializers.CharField()

    def validate_phone(self, value):
        value = authenticate_validators.phone_validator(value)
        return value

    def validate(self, data):
        authenticate_validators.make_email_or_phone_or_username_required_validator(data)
        return data


class InputChangeUserPasswordSerializer(serializers.Serializer):
    """
    This serializer class takes password and code from user
    and passed it to ChangePasswordAPIView to do some works on them.
    """
    field_type = serializers.CharField(required=False)
    old_password = serializers.CharField(
        validators=[authenticate_validators.password_validator])
    new_password = serializers.CharField(
        validators=[authenticate_validators.password_validator])

    def validate_field_type(self, value):
        if value not in ['email', 'phone']:
            raise serializers.ValidationError('Enter a valid field_type')
        return value


class InputForgetUserPasswordSerializer(serializers.Serializer):
    """
    This serializer class takes email, password and code from user
    and passed it to ForgetPasswordAPIView to do some works on them.
    """
    email = serializers.CharField(max_length=254, validators=[
        authenticate_validators.email_validator], required=False)
    phone = serializers.CharField(required=False)
    username = serializers.CharField(required=False)
    new_password = serializers.CharField(validators=[authenticate_validators.password_validator])
    code = serializers.CharField(validators=[authenticate_validators.code_validator])

    def validate_phone(self, value):
        value = authenticate_validators.phone_validator(value)
        return value

    def validate(self, data):
        authenticate_validators.make_email_or_phone_or_username_required_validator(data)
        return data


class InputEditUserSerializer(serializers.Serializer):
    first_name = serializers.CharField(allow_blank=True, required=False)
    last_name = serializers.CharField(allow_blank=True, required=False)
    info = serializers.JSONField(validators=[authenticate_validators.info_validator], required=False)
    image = serializers.ImageField(required=False)
    poster = serializers.ImageField(required=False)
    delete_image = serializers.BooleanField(default=False)
    delete_poster = serializers.BooleanField(default=False)

    def validate_image(self, value):
        main_validators.image_validetor(image=value, image_size_as_MB=conf.maximum_profile_image_size_MG,
                                        format=conf.allowed_formats_for_authenticate_profile_image,
                                        max_side=conf.maximum_side_size_for_authenticate_image)
        return value

    def validate_poster(self, value):
        main_validators.image_validetor(image=value, image_size_as_MB=conf.maximum_size_for_authenticate_poster_MG,
                                        format=conf.allowed_formats_for_authenticate_poster,
                                        max_side=conf.maximum_side_size_for_authenticate_poster)

        return value

    def validate_first_name(self, value):
        main_validators.name_validator(name=value, min_length=3, max_length=46)
        return value

    def validate_last_name(self, value):
        main_validators.name_validator(name=value, min_length=3, max_length=46)
        return value


class InputUserProfileSerializer(serializers.Serializer):
    """
    This serializer class takes user_id  from user
    and passed it to ProfileAPIView to do some works on it.
    """
    user_id = serializers.CharField(max_length=36)


class InputUserGoogleLoginSerializer(serializers.Serializer):
    """
    This serializer class takes a g_id_token from user
    and passed it to GoogleLoginAPIView to do some works on it.
    """
    g_id_token = serializers.CharField()


class InputUserFacebookLoginSerializer(serializers.Serializer):
    """
    This serializer class takes a fb_code from user
    and passed it to FacebookLoginAPIView to do some works on it.
    """
    fb_code = serializers.CharField()


class UserBalanceSerializer(serializers.ModelSerializer):
    class Meta:
        model = UserBalanceHistory
        fields = ['remaining_balance']
