"""Serializers for account web"""
from django.conf import settings
from django.contrib.auth import password_validation as password_validators
from rest_framework import serializers

from account import models, tasks
from utils import exceptions as utils_exceptions
from utils.methods import username_validator


class PasswordResetSerializer(serializers.Serializer):
    """Serializer from model PasswordReset"""
    username_or_email = serializers.CharField(required=False,
                                              write_only=True,)

    @property
    def request(self):
        """Get request from context"""
        return self.context.get('request')

    def validate(self, attrs):
        """Override validate method"""
        user = self.request.user
        username_or_email = attrs.get('username_or_email')

        if not user.is_authenticated:
            if not username_or_email:
                raise utils_exceptions.UserNotFoundError()

            filters = {}
            if username_validator(username_or_email):
                filters.update({'username__icontains': username_or_email})
            else:
                filters.update({'email__icontains': username_or_email})

            if filters:
                filters.update({'is_active': True})
                user_qs = models.User.objects.filter(**filters)
                if user_qs.exists():
                    user = user_qs.first()
        attrs['user'] = user
        return attrs


class PasswordResetConfirmSerializer(serializers.ModelSerializer):
    """Serializer for model User"""

    password = serializers.CharField(write_only=True)

    class Meta:
        """Meta class"""
        model = models.User
        fields = ('password', )

    def validate_password(self, value):
        """Password validation method."""
        try:
            # Compare new password with the old ones
            if self.instance.check_password(raw_password=value):
                raise utils_exceptions.PasswordsAreEqual()
            # Validate password
            password_validators.validate_password(password=value)
        except serializers.ValidationError as e:
            raise serializers.ValidationError(str(e))
        return value

    def update(self, instance, validated_data):
        """Override update method"""
        # Update user password from instance
        instance.set_password(validated_data.get('password'))
        instance.save()
        if settings.USE_CELERY:
            tasks.send_password_changed_email(
                user_id=instance.id,
                country_code=self.context.get('request').country_code)
        else:
            tasks.send_password_changed_email(
                user_id=instance.id,
                country_code=self.context.get('request').country_code)
        return instance
