from django.contrib.auth.forms import UserCreationForm, UserChangeForm, PasswordResetForm
from django import forms
from .models import CustomUser
import re  # Import the re module for regular expressions
from .utils.licence_validator import LicenseValidator
from django.core.mail import send_mail
from django.template.loader import render_to_string
from django.utils.http import urlsafe_base64_encode
from django.contrib.auth.tokens import default_token_generator
from django.contrib.sites.shortcuts import get_current_site
from django.utils.encoding import force_bytes
from django.contrib.auth.forms import PasswordChangeForm
from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth import authenticate  # Add this import
import logging

class CustomUserCreationForm(UserCreationForm):
    usable_password = None
    def clean_licence_id(self):
        licence_id = self.cleaned_data.get('licence_id')
        if licence_id:
            licence_id = licence_id.replace(' ', '').strip().upper()
            validator = LicenseValidator(licence_id)
            if validator.validate_license():
                licence_id = validator.computed_licence_id
            else:
                raise forms.ValidationError('Le numéro de licence est invalide, la lettre ne correspond pas.')
        return licence_id

    def clean_email(self):
        email = self.cleaned_data.get('email')
        if email:
            email = email.lower()
            if CustomUser.objects.filter(email__iexact=email).exclude(pk=self.instance.pk).exists():
                raise forms.ValidationError("Cet email est déjà utilisé. Veuillez en choisir un autre :)")
        return email

    def clean_username(self):
        username = self.cleaned_data.get('username')
        if username:
            username = username.lower()
            if CustomUser.objects.filter(username__iexact=username).exclude(pk=self.instance.pk).exists() | CustomUser.objects.filter(email__iexact=username).exclude(pk=self.instance.pk).exists():
                raise forms.ValidationError("Cet identifiant est déjà utilisé. Veuillez en choisir un autre :)")
        return username

    class Meta:
        model = CustomUser
        error_messages = {
            'email': {
                'unique': "Cette adresse email est déjà utilisée.",
            },
            'username': {
                'unique': "Ce nom d'utilisateur est déjà pris.",
            },
            'licence_id': {
                'unique': "Cette licence est déjà utilisée par un autre compte.",
            },

        }

        fields = UserCreationForm.Meta.fields + ('umpire_code', 'clubs', 'phone', 'first_name', 'last_name', 'licence_id', 'country')

class SimpleCustomUserCreationForm(UserCreationForm):
    usable_password = None

    def clean_licence_id(self):
        licence_id = self.cleaned_data.get('licence_id')
        if licence_id:
            licence_id = licence_id.replace(' ', '').strip().upper()
            validator = LicenseValidator(licence_id)
            if validator.validate_license():
                licence_id = validator.computed_licence_id
            else:
                raise forms.ValidationError('Le numéro de licence est invalide, la lettre ne correspond pas.')
        return licence_id

    def clean_phone(self):
        phone = self.cleaned_data.get('phone')
        if phone:
            # Remove all spaces, dots, dashes, and parentheses
            phone = re.sub(r'[\s\.\-\(\)]', '', phone)
            # Basic regex for phone numbers, allowing 6-15 digits for international numbers
            if not re.match(r"^\+?\d{6,15}$", phone):
                raise forms.ValidationError("Entrer un numéro de téléphone valide.")
        return phone

    class Meta:
        model = CustomUser
        fields = UserCreationForm.Meta.fields + ('email', 'phone', 'first_name', 'last_name', 'licence_id', 'country')
        error_messages = {
            'email': {
                'unique': "Cette adresse email est déjà utilisée.",
            },
            'username': {
                'unique': "Ce nom d'utilisateur est déjà pris.",
            },
            'licence_id': {
                'unique': "Cette licence est déjà utilisée par un autre compte.",
            },

        }
        labels = {
            'username': 'Nom d’utilisateur',
            'email': 'E-mail',
            'phone': 'Numéro de téléphone',
            'first_name': 'Prénom',
            'last_name': 'Nom de famille',
            'licence_id': 'Numéro de licence',
            'country': 'Pays',
            'password1': 'Mot de passe',
            'password2': 'Confirmer le mot de passe',
        }

    def clean_email(self):
        email = self.cleaned_data.get('email')
        if email:
            email = email.lower()
            if CustomUser.objects.filter(email__iexact=email).exclude(pk=self.instance.pk).exists():
                raise forms.ValidationError("Cet email est déjà utilisé. Veuillez en choisir un autre :)")
        return email

    def clean_username(self):
        username = self.cleaned_data.get('username')
        if username:
            username = username.lower()
            if CustomUser.objects.filter(username__iexact=username).exclude(pk=self.instance.pk).exists() | CustomUser.objects.filter(email__iexact=username).exclude(pk=self.instance.pk).exists():
                raise forms.ValidationError("Cet identifiant est déjà utilisé. Veuillez en choisir un autre :)")
        return username


class CustomUserChangeForm(UserChangeForm):
    def clean_username(self):
        username = self.cleaned_data.get('username')
        if username:
            username = username.lower()
            if CustomUser.objects.filter(username__iexact=username).exclude(pk=self.instance.pk).exists() | CustomUser.objects.filter(email__iexact=username).exclude(pk=self.instance.pk).exists():
                raise forms.ValidationError("Cet identifiant est déjà utilisé. Veuillez en choisir un autre :)")
        return username

    def clean_licence_id(self):
        licence_id = self.cleaned_data.get('licence_id')
        if licence_id:
            licence_id = licence_id.replace(' ', '').strip().upper()
            validator = LicenseValidator(licence_id)
            if validator.validate_license():
                licence_id = validator.computed_licence_id
            else:
                raise forms.ValidationError('Le numéro de licence est invalide, la lettre ne correspond pas.')
        return licence_id

    class Meta:
        model = CustomUser
        error_messages = {
            'email': {
                'unique': "Cette adresse email est déjà utilisée.",
            },
            'username': {
                'unique': "Ce nom d'utilisateur est déjà pris.",
            },
            'licence_id': {
                'unique': "Cette licence est déjà utilisée par un autre compte.",
            },

        }
        fields = UserCreationForm.Meta.fields + ('umpire_code', 'clubs', 'phone', 'first_name', 'last_name', 'licence_id', 'country')

class SimpleForm(forms.Form):
    # A single field for user input (e.g., a text field)
    name = forms.CharField(label='Enter your name!', max_length=100)

class TournamentRegistrationForm(forms.Form):
    #first_name = forms.CharField(label='Prénom', max_length=50)
    #last_name = forms.CharField(label='Nom', max_length=50)
    email = forms.EmailField(label='E-mail', widget=forms.EmailInput(attrs={'readonly': 'readonly'}))
    mobile_number = forms.CharField(
        label='Téléphone',
        max_length=15,
        required=True
    )

    def clean_mobile_number(self):
        mobile_number = self.cleaned_data.get('mobile_number')
        if mobile_number:
            # Remove spaces, dots, dashes, and parentheses from the number first
            mobile_number = re.sub(r'[\s\.\-\(\)]', '', mobile_number)
            if not re.match(r"^\+?\d{6,15}$", mobile_number):
                raise forms.ValidationError("Entrer un numéro de téléphone valide.")
        return mobile_number

class AddPlayerForm(forms.Form):
    licence_id = forms.CharField(label='Numéro de licence (avec la lettre)', max_length=20, required=False)
    first_name = forms.CharField(label='Prénom', min_length=2, max_length=50, required=False)
    last_name = forms.CharField(label='Nom', min_length=2, max_length=50, required=False)
    first_tournament = False
    user_without_licence = False

    def names_is_valid(self):
        first_name = self.cleaned_data.get('first_name')
        last_name = self.cleaned_data.get('last_name')
        return len(first_name) >= 2 and len(last_name) >= 2

    def clean_licence_id(self):
        licence_id = self.cleaned_data.get('licence_id')
        if licence_id:
            licence_id = licence_id.replace(' ', '').strip().upper()
        return licence_id

    def clean_last_name(self):
        last_name = self.cleaned_data.get('last_name')

        # Convert to uppercase
        last_name = last_name.upper()

        # Update the cleaned_data with the modified licence_id
        self.cleaned_data['last_name'] = last_name
        return last_name

    def clean_first_name(self):
        first_name = self.cleaned_data.get('first_name')

        # Convert to capitalize
        first_name = first_name.capitalize()

        # Update the cleaned_data with the modified licence_id
        self.cleaned_data['first_name'] = first_name
        return first_name

class CustomPasswordResetForm(PasswordResetForm):
    def save(self, *args, **kwargs):
        """
        Override the save method to send a custom email.
        """
        email = self.cleaned_data["email"]
        users = self.get_users(email)

        for user in users:
            # Generate the token for password reset
            token = default_token_generator.make_token(user)
            uid = urlsafe_base64_encode(force_bytes(user.pk))

            # Prepare the context for the email template
            context = {
                "email": user.email,
                "domain": get_current_site(self.request).domain,
                "site_name": "Padel Club",
                "uid": uid,
                "token": token,
                "protocol": "http",  # Use 'https' in production
            }

            # Render the email content from the template
            subject = "Réinitialisation du mot de passe"
            message = render_to_string("registration/password_reset_email.html", context)

            # Send the email
            send_mail(subject, message, None, [user.email])

class ProfileUpdateForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # Remove autofocus from the 'username' field
        self.fields['username'].widget.attrs.pop("autofocus", None)

    def clean_email(self):
        email = self.cleaned_data.get('email')
        if email:
            email = email.lower()
            if CustomUser.objects.filter(email__iexact=email).exclude(pk=self.instance.pk).exists():
                raise forms.ValidationError("Cet email est déjà utilisé. Veuillez en choisir un autre :)")
        return email

    def clean_username(self):
        username = self.cleaned_data.get('username')
        if username:
            username = username.lower()
            if CustomUser.objects.filter(username__iexact=username).exclude(pk=self.instance.pk).exists() | CustomUser.objects.filter(email__iexact=username).exclude(pk=self.instance.pk).exists():
                raise forms.ValidationError("Cet identifiant est déjà utilisé. Veuillez en choisir un autre :)")
        return username

    def clean_licence_id(self):
        licence_id = self.cleaned_data.get('licence_id')
        if licence_id:
            licence_id = licence_id.replace(' ', '').strip().upper()
            validator = LicenseValidator(licence_id)
            if validator.validate_license():
                licence_id = validator.computed_licence_id
            else:
                raise forms.ValidationError('Le numéro de licence est invalide, la lettre ne correspond pas.')
        return licence_id

    def clean_phone(self):
        phone = self.cleaned_data.get('phone')
        if phone:
            # Remove all spaces, dots, dashes, and parentheses
            phone = re.sub(r'[\s\.\-\(\)]', '', phone)
            # Basic regex for phone numbers, allowing 6-15 digits for international numbers
            if not re.match(r"^\+?\d{6,15}$", phone):
                raise forms.ValidationError("Entrer un numéro de téléphone valide.")
        return phone

    class Meta:
        model = CustomUser
        fields = ['first_name', 'last_name', 'licence_id', 'username', 'email', 'phone']
        labels = {
            'username': 'Nom d’utilisateur',
            'email': 'E-mail',
            'phone': 'Numéro de téléphone',
            'first_name': 'Prénom',
            'last_name': 'Nom de famille',
            'licence_id': 'Numéro de licence',
        }
        error_messages = {
            'email': {
                'unique': "Cette adresse email est déjà utilisée.",
            },
            'username': {
                'unique': "Ce nom d'utilisateur est déjà pris.",
            },
            'licence_id': {
                'unique': "Cette licence est déjà utilisée par un autre compte.",
            },
        }

class CustomPasswordChangeForm(PasswordChangeForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # Remove autofocus from all fields in the PasswordChangeForm
        for field in self.fields.values():
            field.widget.attrs.pop("autofocus", None)

logger = logging.getLogger(__name__)

class EmailOrUsernameAuthenticationForm(AuthenticationForm):
    username = forms.CharField(label='Username or Email')

    def clean(self):
        username = self.cleaned_data.get('username')
        password = self.cleaned_data.get('password')

        logger.info(f"Login attempt with username/email: {username}")

        if username and password:
            # Check if user exists first (either by username or email)
            user_exists = None
            try:
                # Try to find user by username first
                user_exists = CustomUser.objects.get(username__iexact=username)
            except CustomUser.DoesNotExist:
                # Try to find user by email
                try:
                    user_exists = CustomUser.objects.get(email__iexact=username)
                except CustomUser.DoesNotExist:
                    pass

            # If user exists but is inactive, provide specific feedback
            if user_exists and not user_exists.is_active:
                # Store the inactive user in session for template use
                if hasattr(self, 'request') and self.request.session:
                    self.request.session['inactive_user_email'] = user_exists.email
                    self.request.session['inactive_user_id'] = str(user_exists.id)

                raise forms.ValidationError(
                    "Votre compte n'est pas encore activé. Veuillez cliquer sur le lien d'activation envoyé à votre adresse e-mail.",
                    code='inactive_account'
                )

            # Try regular authentication
            self.user_cache = authenticate(
                self.request,
                username=username,
                password=password
            )

            if self.user_cache is None:
                logger.warning("Authentication failed")
                raise forms.ValidationError(
                    "Identifiant/E-mail ou mot de passe incorrect. Les champs sont sensibles à la casse.",
                    code='invalid_login'
                )
            else:
                logger.info(f"Authentication successful for user: {self.user_cache}")
                # Clear any inactive user session data on successful login
                if hasattr(self, 'request') and self.request.session:
                    self.request.session.pop('inactive_user_email', None)
                    self.request.session.pop('inactive_user_id', None)
                self.confirm_login_allowed(self.user_cache)

        return self.cleaned_data
