# -*- coding: utf-8 -*-

from django import forms
from django.contrib.auth import get_user_model
from django.contrib.auth.forms import AuthenticationForm, PasswordResetForm
from django.utils.translation import gettext_lazy as _
from django.template.loader import render_to_string

from spirit.core.conf import settings
from spirit.core import tasks
from spirit.user.forms import CleanEmailMixin

User = get_user_model()


class RegistrationForm(CleanEmailMixin, forms.ModelForm):

    email2 = forms.CharField(
        label=_("Email confirmation"),
        widget=forms.EmailInput,
        max_length=254,
        help_text=_("Enter the same email as above, for verification."))
    # todo: add password validator for Django 1.9
    password = forms.CharField(
        label=_("Password"),
        widget=forms.PasswordInput)
    honeypot = forms.CharField(
        label=_("Leave blank"),
        required=False)

    class Meta:
        model = User
        fields = ("username", "email")

    def __init__(self, *args, **kwargs):
        super(RegistrationForm, self).__init__(*args, **kwargs)
        self.fields['email'].required = True  # Django model does not requires it

    def clean_honeypot(self):
        """Check that nothing has been entered into the honeypot."""
        value = self.cleaned_data["honeypot"]

        if value:
            raise forms.ValidationError(
                _("Do not fill this field."))

        return value

    def clean_username(self):
        username = self.cleaned_data["username"]

        if settings.ST_CASE_INSENSITIVE_USERNAMES:
            username = username.lower()

        is_taken = (
            User.objects
            .filter(username=username)
            .exists())
        if is_taken:
            raise forms.ValidationError(
                _("The username is taken."))

        return self.cleaned_data["username"]

    def clean_email2(self):
        email = self.cleaned_data.get("email")
        email2 = self.cleaned_data["email2"]

        if settings.ST_CASE_INSENSITIVE_EMAILS:
            email2 = email2.lower()

        if email and email != email2:
            raise forms.ValidationError(
                _("The two email fields didn't match."))

        return email2

    def save(self, commit=True):
        self.instance.is_active = False
        self.instance.set_password(self.cleaned_data["password"])
        return super(RegistrationForm, self).save(commit)


class LoginForm(AuthenticationForm):

    username = forms.CharField(
        label=_("Username or Email"),
        max_length=254)

    def __init__(self, *args, **kwargs):
        super(LoginForm, self).__init__(*args, **kwargs)
        self.error_messages['invalid_login'] = _("The password is not valid.")

    def _validate_username(self):
        """
        Check the username exists.\
        Show if the username or email is invalid\
        instead of the unclear "username or\
        password is invalid" message.
        """
        username = self.cleaned_data.get("username")

        if not username:
            return

        if settings.ST_CASE_INSENSITIVE_USERNAMES:
            username = username.lower()

        is_found = (
            User.objects
            .filter(username=username)
            .exists())
        if is_found:
            return

        if settings.ST_CASE_INSENSITIVE_EMAILS:
            username = username.lower()

        is_found_email = (
            User.objects
            .filter(email=username)
            .exists())
        if is_found_email:
            return

        raise forms.ValidationError(
            _("No account matches %(username)s.") % {
                'username': username})

    def clean(self):
        self._validate_username()
        return super(LoginForm, self).clean()


class ResendActivationForm(forms.Form):

    email = forms.CharField(
        label=_("Email"),
        widget=forms.EmailInput,
        max_length=254)

    def clean_email(self):
        email = self.cleaned_data["email"]

        if settings.ST_CASE_INSENSITIVE_EMAILS:
            email = email.lower()

        is_existent = (
            User.objects
            .filter(email=email)
            .exists())
        if not is_existent:
            raise forms.ValidationError(
                _("The provided email does not exists."))

        self.user = (
            User.objects
            .filter(
                email=email,
                st__is_verified=False)
            .order_by('-pk')
            .first())
        if not self.user:
            raise forms.ValidationError(
                _("This account is verified, try logging-in."))

        return email

    def get_user(self):
        return self.user


class CustomPasswordResetForm(PasswordResetForm):
    def send_mail(
            self, subject_template_name, email_template_name,
            context, from_email, to_email, html_email_template_name=None):
        subject = render_to_string(subject_template_name, context)
        subject = ''.join(subject.splitlines())
        body = render_to_string(email_template_name, context)
        tasks.send_email(subject, body, [to_email])
