from django import forms
from .models import DatingPartnerProfile, DatingInterest, DatingPartnerPhoto

from django.contrib.auth import get_user_model
from django.core.exceptions import ValidationError
from common.choices import SRI_LANKA_CITY_CHOICES, SRI_LANKA_DISTRICT_CHOICES, COUNTRY_CHOICES
from django.contrib.auth.forms import PasswordResetForm

User = get_user_model()



class DatingPasswordResetForm(PasswordResetForm):
    """
    Only allows password reset emails for active users
    who have a DatingPartnerProfile.
    """

    def get_users(self, email):
        active_users = super().get_users(email)
        for user in active_users:
            if hasattr(user, 'dating_profile'):
                yield user


class DatingPartnerProfileEditForm(forms.ModelForm):
    class Meta:
        model = DatingPartnerProfile
        fields = [
            'full_name',
            'display_name',
            'gender',
            'date_of_birth',
            'city',
            'district',
            'country',
            'short_intro',
            'about_me',
            'relationship_goal',
            'marital_status',
            'religion',
            'profession',
            'languages_spoken',
            'education',
            'height',
            'hobbies',
            'expectations',
            'email',
            'phone_number',
            'whatsapp_number',
            'passport_ready',
            'willing_to_relocate',
            'willing_video_call',
            'is_public',
        ]
        widgets = {
            'date_of_birth': forms.DateInput(attrs={'type': 'date'}),
            'city': forms.Select(),
            'district': forms.Select(),
            'country': forms.Select(),
            'about_me': forms.Textarea(attrs={'rows': 4}),
            'hobbies': forms.Textarea(attrs={'rows': 3}),
            'expectations': forms.Textarea(attrs={'rows': 4}),
            'short_intro': forms.TextInput(attrs={'maxlength': 255}),
        }
        labels = {
            'is_public': 'Show my profile in public listings',
        }
        help_texts = {
            'is_public': 'If checked, your profile may appear in public dating partner listings after admin approval. If unchecked, your profile will remain private.',
        }

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

        self.fields['city'].choices = [('', 'Select city')] + list(SRI_LANKA_CITY_CHOICES)
        self.fields['district'].choices = [('', 'Select district')] + list(SRI_LANKA_DISTRICT_CHOICES)
        self.fields['country'].choices = [('', 'Select country')] + list(COUNTRY_CHOICES)

        for field in self.fields.values():
            css = 'form-control'
            if isinstance(field.widget, forms.CheckboxInput):
                css = 'form-check-input'
            elif isinstance(field.widget, forms.Select):
                css = 'form-select'
            field.widget.attrs.setdefault('class', css)

    def clean_full_name(self):
        full_name = self.cleaned_data.get('full_name', '').strip()
        if not full_name:
            raise ValidationError("Full name is required.")
        return full_name

    def clean_email(self):
        email = self.cleaned_data['email'].strip().lower()
        qs = User.objects.filter(email__iexact=email)
        if self.instance.user:
            qs = qs.exclude(pk=self.instance.user.pk)
        if qs.exists():
            raise ValidationError("This email is already used by another account.")
        return email

    def save(self, commit=True):
        partner = super().save(commit=False)

        if partner.user:
            # Split full name into first and last
            full_name = self.cleaned_data.get('full_name', '').strip()
            parts = full_name.split(' ', 1)
            partner.user.first_name = parts[0]
            partner.user.last_name = parts[1] if len(parts) > 1 else ''

            partner.user.email = self.cleaned_data['email']
            if commit:
                partner.user.save()

        if commit:
            partner.save()

        return partner


class DatingPartnerProfileImageForm(forms.ModelForm):
    class Meta:
        model = DatingPartnerProfile
        fields = ['profile_photo']

    def clean_profile_photo(self):
        image = self.cleaned_data.get('profile_photo')
        if not image:
            return image

        allowed_content_types = ['image/jpeg', 'image/png', 'image/webp']
        if hasattr(image, 'content_type') and image.content_type not in allowed_content_types:
            raise ValidationError("Only JPG, PNG, or WEBP images are allowed.")

        return image


class UsernameChangeForm(forms.ModelForm):
    class Meta:
        model = User
        fields = ['username']

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

        for field in self.fields.values():
            css = 'form-control'
            if isinstance(field.widget, forms.CheckboxInput):
                css = 'form-check-input'
            field.widget.attrs.setdefault('class', css)

    def clean_username(self):
        username = self.cleaned_data['username'].strip()
        qs = User.objects.filter(username__iexact=username)
        if self.user:
            qs = qs.exclude(pk=self.user.pk)
        if qs.exists():
            raise ValidationError("This username is already taken.")
        return username



class DatingPartnerRegistrationForm(forms.ModelForm):
    class Meta:
        model = DatingPartnerProfile
        fields = [
            'full_name',
            'display_name',
            'gender',
            'date_of_birth',
            'city',
            'district',
            'profile_photo',
            'short_intro',
            'about_me',
            'relationship_goal',
            'marital_status',
            'religion',
            'profession',
            'languages_spoken',
            'education',
            'height',
            'hobbies',
            'expectations',
            'email',
            'phone_number',
            'whatsapp_number',
            'passport_ready',
            'willing_to_relocate',
            'willing_video_call',
            'is_public',
            'agreed_to_terms',
        ]
        widgets = {
            'date_of_birth': forms.DateInput(attrs={'type': 'date'}),
            'city': forms.Select(),
            'district': forms.Select(),
            'about_me': forms.Textarea(attrs={'rows': 4}),
            'hobbies': forms.Textarea(attrs={'rows': 3}),
            'expectations': forms.Textarea(attrs={'rows': 3}),
 
        }
        labels = {
            'is_public': 'Show my profile in public listings',
            'agreed_to_terms': "I agree to Ensolanka’s Terms & Conditions and Privacy Policy",
        }
        
        help_texts = {
            'is_public': 'If checked, your profile may appear in public dating partner listings after admin approval. If unchecked, your profile will remain private.',
        }

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

        self.fields['city'].choices = [('', 'Select city')] + list(SRI_LANKA_CITY_CHOICES)
        self.fields['district'].choices = [('', 'Select district')] + list(SRI_LANKA_DISTRICT_CHOICES)

        for name, field in self.fields.items():
            if isinstance(field.widget, forms.CheckboxInput):
                field.widget.attrs.update({'class': 'form-check-input'})
            elif isinstance(field.widget, forms.Select):
                field.widget.attrs.update({'class': 'form-select'})
            elif isinstance(field.widget, forms.FileInput):
                field.widget.attrs.update({'class': 'form-control'})
            else:
                field.widget.attrs.update({'class': 'form-control'})

    def clean_agreed_to_terms(self):
        agreed = self.cleaned_data.get('agreed_to_terms')
        if not agreed:
            raise forms.ValidationError("You must agree to the terms and privacy policy.")
        return agreed

class DatingInterestForm(forms.ModelForm):
    class Meta:
        model = DatingInterest
        fields = ['message']
        widgets = {
            'message': forms.Textarea(attrs={
                'rows': 4,
                'placeholder': 'Write a short message or note about your interest...'
            }),
        }


class DatingPartnerPhotoForm(forms.ModelForm):
    class Meta:
        model = DatingPartnerPhoto
        fields = ['image', 'caption', 'is_public']
        widgets = {
            'image': forms.ClearableFileInput(attrs={
                'class': 'form-control custom-file-input',
                'accept': '.jpg,.jpeg,.png,.webp',
            }),
            'caption': forms.TextInput(attrs={
                'class': 'form-control',
                'placeholder': 'Optional short caption',
            }),
            'is_public': forms.CheckboxInput(attrs={
                'class': 'form-check-input',
            }),
        }
        help_texts = {
            'image': 'Upload JPG, PNG, or WEBP image.',
            'caption': 'Optional short note for this photo.',
            'is_public': 'If checked, this photo can appear publicly after approval.',
        }
        labels = {
            'image': 'Choose Image',
            'caption': 'Caption',
            'is_public': 'Public Photo',
        }

    def __init__(self, *args, **kwargs):
        self.partner = kwargs.pop('partner', None)
        super().__init__(*args, **kwargs)

        if self.partner:
            self.instance.profile = self.partner

        self.fields['caption'].required = False
        self.fields['is_public'].required = False

    def clean(self):
        cleaned_data = super().clean()

        if self.partner and not self.instance.pk:
            existing_count = self.partner.additional_photos.count()
            if existing_count >= 5:
                raise forms.ValidationError("Maximum 5 additional photos are allowed.")

        return cleaned_data

    def clean_image(self):
        image = self.cleaned_data.get('image')

        if not image:
            raise forms.ValidationError("Please choose an image.")

        allowed_types = ['image/jpeg', 'image/png', 'image/webp']
        if hasattr(image, 'content_type') and image.content_type not in allowed_types:
            raise forms.ValidationError("Only JPG, PNG, or WEBP images are allowed.")

        max_size_mb = 8
        if image.size > max_size_mb * 1024 * 1024:
            raise forms.ValidationError(f"Image size must be under {max_size_mb} MB.")

        return image