import random
import string

import django.contrib.auth.models
from django import forms
from django.contrib.auth import get_user_model
from django.contrib.auth.forms import UserCreationForm
from django.core.exceptions import FieldDoesNotExist
from django.db.models.fields import CharField, EmailField
from django.utils.translation import gettext_lazy as _
from wiki.conf import settings


def _get_field(model, field):
    try:
        return model._meta.get_field(field)
    except FieldDoesNotExist:
        return


User = get_user_model()


def check_user_field(user_model):
    return isinstance(_get_field(user_model, user_model.USERNAME_FIELD), CharField)


def check_email_field(user_model):
    return isinstance(_get_field(user_model, user_model.get_email_field_name()), EmailField)


# django parses the ModelForm (and Meta classes) on class creation, which fails with custom models without expected fields.
# We need to check this here, because if this module can't load then system checks can't run.
CustomUser = User \
    if (settings.ACCOUNT_HANDLING and check_user_field(User) and check_email_field(User)) \
    else django.contrib.auth.models.User


class UserCreationForm(UserCreationForm):
    email = forms.EmailField(required=True)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # Add honeypots
        self.honeypot_fieldnames = "address", "phone"
        self.honeypot_class = ''.join(
            random.choice(string.ascii_uppercase + string.digits)
            for __ in range(10))
        self.honeypot_jsfunction = 'f' + ''.join(
            random.choice(string.ascii_uppercase + string.digits)
            for __ in range(10))

        for fieldname in self.honeypot_fieldnames:
            self.fields[fieldname] = forms.CharField(
                widget=forms.TextInput(attrs={'class': self.honeypot_class}),
                required=False,
            )

    def clean(self):
        cd = super().clean()
        for fieldname in self.honeypot_fieldnames:
            if cd[fieldname]:
                raise forms.ValidationError(
                    "Thank you, non-human visitor. Please keep trying to fill in the form.")
        return cd

    class Meta:
        model = CustomUser
        fields = (CustomUser.USERNAME_FIELD, CustomUser.get_email_field_name())


class UserUpdateForm(forms.ModelForm):
    password1 = forms.CharField(label="New password", widget=forms.PasswordInput(), required=False)
    password2 = forms.CharField(label="Confirm password", widget=forms.PasswordInput(), required=False)

    def clean(self):
        cd = super().clean()
        password1 = cd.get('password1')
        password2 = cd.get('password2')

        if password1 and password1 != password2:
            raise forms.ValidationError(_("Passwords don't match"))

        return cd

    class Meta:
        model = CustomUser
        fields = [CustomUser.get_email_field_name()]
