from pathlib import Path

from django import forms
from django.contrib.auth import authenticate
from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth.password_validation import validate_password

from .models import UserProfile


class UnifiedAuthenticationForm(AuthenticationForm):
    username = forms.CharField(
        label="Utilizador ou email",
        widget=forms.TextInput(attrs={"autocomplete": "username", "autofocus": True}),
    )
    password = forms.CharField(
        label="Palavra-passe",
        strip=False,
        widget=forms.PasswordInput(attrs={"autocomplete": "current-password"}),
    )


class OTPTokenForm(forms.Form):
    token = forms.CharField(
        label="Código de autenticação",
        max_length=32,
        widget=forms.TextInput(
            attrs={
                "autocomplete": "one-time-code",
                "inputmode": "numeric",
                "placeholder": "000 000 ou código de recuperação",
            }
        ),
    )


class DisableTwoFactorForm(forms.Form):
    password = forms.CharField(
        label="Palavra-passe atual",
        strip=False,
        widget=forms.PasswordInput(attrs={"autocomplete": "current-password"}),
    )
    token = forms.CharField(
        label="Código atual ou de recuperação",
        max_length=32,
        widget=forms.TextInput(attrs={"autocomplete": "one-time-code"}),
    )

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

    def clean_password(self):
        password = self.cleaned_data["password"]
        if not self.user.check_password(password):
            raise forms.ValidationError("A palavra-passe atual não está correta.")
        return password


class RegenerateRecoveryCodesForm(forms.Form):
    password = forms.CharField(
        label="Palavra-passe atual",
        strip=False,
        widget=forms.PasswordInput(attrs={"autocomplete": "current-password"}),
    )
    token = forms.CharField(
        label="Código da aplicação autenticadora",
        max_length=12,
        widget=forms.TextInput(attrs={"autocomplete": "one-time-code", "inputmode": "numeric"}),
    )

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

    def clean_password(self):
        password = self.cleaned_data["password"]
        if not self.user.check_password(password):
            raise forms.ValidationError("A palavra-passe atual não está correta.")
        return password


class AccountForm(forms.ModelForm):
    first_name = forms.CharField(label="Nome", max_length=150, required=False)
    last_name = forms.CharField(label="Apelido", max_length=150, required=False)
    email = forms.EmailField(label="Email", required=False)

    class Meta:
        model = UserProfile
        fields = ("avatar", "phone", "job_title")
        widgets = {
            "avatar": forms.ClearableFileInput(attrs={"accept": ".png,.jpg,.jpeg,.webp"}),
        }

    def __init__(self, *args, user=None, **kwargs):
        self.user = user
        super().__init__(*args, **kwargs)
        if user:
            self.fields["first_name"].initial = user.first_name
            self.fields["last_name"].initial = user.last_name
            self.fields["email"].initial = user.email

    def clean_avatar(self):
        avatar = self.cleaned_data.get("avatar")
        if not avatar:
            return avatar
        if avatar.size > 3 * 1024 * 1024:
            raise forms.ValidationError("A fotografia não pode ultrapassar 3 MB.")
        if Path(avatar.name).suffix.lower() not in {".png", ".jpg", ".jpeg", ".webp"}:
            raise forms.ValidationError("Utilize uma imagem PNG, JPG ou WEBP.")
        return avatar

    def save(self, commit=True):
        profile = super().save(commit=commit)
        if self.user:
            self.user.first_name = self.cleaned_data.get("first_name", "")
            self.user.last_name = self.cleaned_data.get("last_name", "")
            self.user.email = self.cleaned_data.get("email", "")
            if commit:
                self.user.save(update_fields=["first_name", "last_name", "email"])
        return profile
