from django import forms
from django.contrib.auth.forms import PasswordResetForm
from django.utils.http import urlsafe_base64_encode
from django.utils.encoding import force_bytes
from django.contrib.auth.tokens import default_token_generator
from django.contrib.auth.password_validation import (validate_password, 
                                                     get_password_validators,
                                                    MinimumLengthValidator,
                                                    UserAttributeSimilarityValidator,
                                                    CommonPasswordValidator,
                                                    NumericPasswordValidator,)
from django.conf import settings
from .models import CustomUser
from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _

from at_django_boilerplate.utils.hash_utils import hexdigest
import logging

logger = logging.getLogger(__name__)


class UserSignUpForm(forms.ModelForm):
    password = forms.CharField(widget=forms.PasswordInput)
    confirm_password = forms.CharField(widget=forms.PasswordInput)
    terms_accepted = forms.BooleanField(required=True, label='I accept the terms and conditions')

    class Meta:
        model = CustomUser
        fields = ['first_name', 'last_name', 'email','contact_number','dob','password','confirm_password','terms_accepted']
        widgets = {
            'dob': forms.DateInput(attrs={'type': 'date'}),
            'first_name': forms.TextInput(attrs={'type': 'text'}),
            'last_name': forms.TextInput(attrs={'type': 'text'}),
            'email': forms.EmailInput(attrs={'type': 'email'}),
            'contact_number': forms.TextInput(attrs={'type': 'text'}),
        }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['password'].help_text = self.get_password_requirements()

    def get_password_requirements(self):
        password_validators = get_password_validators(settings.AUTH_PASSWORD_VALIDATORS)
        requirements = []
        for validator in password_validators:
            if isinstance(validator, MinimumLengthValidator):
                requirements.append(f"*Password must be at least {validator.min_length} characters long.<br>")
            elif isinstance(validator, UserAttributeSimilarityValidator):
                requirements.append("*Password cannot be too similar to your other personal information.<br>")
            elif isinstance(validator, CommonPasswordValidator):
                requirements.append("*Password cannot be a commonly used password.<br>")
            elif isinstance(validator, NumericPasswordValidator):
                requirements.append("*Password cannot be entirely numeric.<br>")
        return " ".join(requirements)



    def clean(self):
        cleaned_data = super().clean()
        password = cleaned_data.get("password")
        confirm_password = cleaned_data.get("confirm_password")

        if password and confirm_password:
            try:
                validate_password(password, self.instance)
            except forms.ValidationError as error:
                self.add_error('password', error)
                return cleaned_data

            if password != confirm_password:
                self.add_error('confirm_password', "Passwords do not match")
        
        return cleaned_data



class SigninForm(forms.Form):
    username = forms.CharField(max_length=65)
    password = forms.CharField(max_length=65, widget=forms.PasswordInput)


class CustomPasswordResetForm(PasswordResetForm):

    def get_users(self, email):
        """Given an email, return matching user(s) who should receive a reset."""
        email_hash = hexdigest(email)
        active_custom_users = CustomUser.objects.filter(email_hash=email_hash)
        active_users = [user for user in active_custom_users ]
        valid_users = [u for u in active_users if u.has_usable_password()]
        return valid_users


    def save(self, domain_override=None,
             subject_template_name='reset/password_reset_subject.txt',
             email_template_name='reset/password_reset_email.html',
             use_https=False, token_generator=default_token_generator,
             from_email=None, request=None, html_email_template_name=None,
             extra_email_context=None):
        """
        Generates a one-use only link for resetting password and sends to the user.
        """
        email = self.cleaned_data["email"]
        for user in self.get_users(email):
            context = {
                'email': email,
                'domain': domain_override or request.get_host(),
                'request':request,
                'site_name': 'we-kwick',
                'uid': urlsafe_base64_encode(force_bytes(user.pk)),
                'user': user,
                'token': token_generator.make_token(user),
                'protocol': 'https' if use_https else 'http',
                **(extra_email_context or {}),
            }
            from_email = settings.EMAIL_HOST_USER
            # print('From:',from_email)
            # print('Email Template:',email_template_name)
            # print('HTML Email Template:',html_email_template_name)
            self.send_mail(
                subject_template_name, email_template_name, context, from_email,
                email, html_email_template_name=html_email_template_name,
            )



class ProfileUpdateForm(forms.ModelForm):
    class Meta:
        model = CustomUser
        fields = [ 'contact_number']
        widgets = {
            'dob': forms.DateInput(attrs={'type': 'date'}),
        }

class UpdateProfileForm(forms.ModelForm):
    class Meta:
        model = CustomUser
        fields = [ 'contact_number']
        widgets = {
            'dob': forms.DateInput(attrs={'type': 'date'}),
        }



def validate_image(file):
    valid_mime_types = ['image/jpeg', 'image/png', 'image/gif', 'image/svg+xml']
    valid_file_extensions = ['.jpg', '.jpeg', '.png', '.gif', '.svg','.JPG']
    
    file_mime_type = file.content_type
    if file_mime_type not in valid_mime_types:
        raise ValidationError(_('Unsupported file type. Please upload a JPEG, PNG, GIF, or SVG image.'))
    
    extension = file.name.split('.')[-1].lower()
    if not any(file.name.endswith(ext) for ext in valid_file_extensions):
        raise ValidationError(_('Unsupported file extension.'))

class ProfilePictureUpdateForm(forms.ModelForm):
    profile_photo = forms.ImageField(
        widget=forms.ClearableFileInput(attrs={'accept': 'image/jpeg,image/png,image/gif,image/svg+xml'}),
        validators=[validate_image]
    )
    
    class Meta:
        model = CustomUser
        fields = ['profile_photo']
