from django import forms
from .models import ForeignerLead, ConsultationRequest, ContactMessage, ForeignerProfile, ForeignerInterest
from decimal import Decimal
from django.contrib.auth import get_user_model
from django.core.exceptions import ValidationError
from common.choices import COUNTRY_CHOICES, NATIONALITY_CHOICES
from django.contrib.auth.forms import PasswordResetForm

from django.utils import timezone

from hosting_app.models import (
    HostEventPackage,
    HostMealPlan,
    HostAddOnService,
    EventType,
    PublicListingStatus,
)

User = get_user_model()


class ForeignerPasswordResetForm(PasswordResetForm):
    """
    Only allows password reset emails for active users
    who have a ForeignerProfile / Guest profile.
    """

    def get_users(self, email):
        active_users = super().get_users(email)

        for user in active_users:
            if hasattr(user, "foreigner_profile"):
                yield user

class ForeignerForgotPasswordForm(forms.Form):
    email = forms.EmailField(
        label="Email Address",
        widget=forms.EmailInput(attrs={
            "class": "form-control",
            "placeholder": "Enter your registered email address"
        })
    )


class ForeignerPasswordResetCodeForm(forms.Form):
    code = forms.CharField(
        label="Verification Code",
        max_length=6,
        widget=forms.TextInput(attrs={
            "class": "form-control",
            "placeholder": "Enter 6-digit code"
        })
    )


class ForeignerSetNewPasswordForm(forms.Form):
    new_password = forms.CharField(
        label="New Password",
        widget=forms.PasswordInput(attrs={
            "class": "form-control",
            "placeholder": "Enter new password"
        })
    )

    confirm_password = forms.CharField(
        label="Confirm Password",
        widget=forms.PasswordInput(attrs={
            "class": "form-control",
            "placeholder": "Confirm new password"
        })
    )

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

        if new_password and confirm_password and new_password != confirm_password:
            raise forms.ValidationError("Passwords do not match.")

        return cleaned_data



class ForeignerProfileEditForm(forms.ModelForm):
    full_name = forms.CharField(max_length=150, required=True)
    email = forms.EmailField(required=True)
    whatsapp_number = forms.CharField(max_length=50, required=False)

    country = forms.ChoiceField(
        choices=[('', 'Select country')] + list(COUNTRY_CHOICES),
        required=True
    )
    nationality = forms.ChoiceField(
        choices=[('', 'Select nationality')] + list(NATIONALITY_CHOICES),
        required=False
    )

    gender = forms.ChoiceField(choices=[], required=False)
    expected_arrival_date = forms.DateField(
        required=False,
        widget=forms.DateInput(attrs={'type': 'date'})
    )
    duration_of_stay = forms.CharField(max_length=100, required=False)
    monthly_budget = forms.ChoiceField(choices=[], required=True)
    remote_worker = forms.BooleanField(required=False)
    message = forms.CharField(widget=forms.Textarea(attrs={'rows': 4}), required=False)

    class Meta:
        model = ForeignerProfile
        fields = []

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

        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)

        lead_model = self.instance.lead.__class__ if self.instance and self.instance.lead else None
        if lead_model:
            self.fields['monthly_budget'].choices = lead_model.BUDGET_CHOICES
            self.fields['gender'].choices = [('', 'Select gender')] + list(lead_model.GENDER_CHOICES)

        if self.instance and self.instance.lead:
            lead = self.instance.lead
            self.fields['full_name'].initial = lead.full_name
            self.fields['email'].initial = lead.email
            self.fields['whatsapp_number'].initial = lead.whatsapp_number
            self.fields['country'].initial = lead.country
            self.fields['nationality'].initial = lead.nationality
            self.fields['gender'].initial = lead.gender
            self.fields['expected_arrival_date'].initial = lead.expected_arrival_date
            self.fields['duration_of_stay'].initial = lead.duration_of_stay
            self.fields['monthly_budget'].initial = lead.monthly_budget
            self.fields['remote_worker'].initial = lead.remote_worker
            self.fields['message'].initial = lead.message

    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).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):
        profile = self.instance
        user = profile.user
        lead = profile.lead

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

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

        if lead:
            lead.full_name = full_name
            lead.email = self.cleaned_data['email']
            lead.whatsapp_number = self.cleaned_data['whatsapp_number']
            lead.country = self.cleaned_data['country']
            lead.nationality = self.cleaned_data['nationality']
            lead.gender = self.cleaned_data['gender']
            lead.expected_arrival_date = self.cleaned_data['expected_arrival_date']
            lead.duration_of_stay = self.cleaned_data['duration_of_stay']
            lead.monthly_budget = self.cleaned_data['monthly_budget']
            lead.remote_worker = self.cleaned_data['remote_worker']
            lead.message = self.cleaned_data['message']
            if commit:
                lead.save()

        if commit:
            profile.save()

        return profile


class ForeignerProfileImageForm(forms.ModelForm):
    class Meta:
        model = ForeignerProfile
        fields = ['profile_image']

    def clean_profile_image(self):
        image = self.cleaned_data.get('profile_image')
        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)

        # Apply Bootstrap styling
        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 ForeignerLeadForm(forms.ModelForm):
    class Meta:
        model = ForeignerLead
        fields = [
            'full_name',
            'email',
            'whatsapp_number',
            'country',
            'nationality',
            'gender',
            'expected_arrival_date',
            'duration_of_stay',
            'monthly_budget',
            'remote_worker',
            'interested_package',
            'message',
            'is_public',
        ]
        widgets = {
            'full_name': forms.TextInput(attrs={
                'class': 'form-control',
                'placeholder': 'Enter your full name'
            }),
            'email': forms.EmailInput(attrs={
                'class': 'form-control',
                'placeholder': 'Enter your email'
            }),
            'whatsapp_number': forms.TextInput(attrs={
                'class': 'form-control',
                'placeholder': 'WhatsApp number'
            }),
            'country': forms.Select(attrs={'class': 'form-select'}),
            'nationality': forms.Select(attrs={'class': 'form-select'}),
            'gender': forms.Select(attrs={'class': 'form-select'}),
            'expected_arrival_date': forms.DateInput(attrs={
                'class': 'form-control',
                'type': 'date'
            }),
            'duration_of_stay': forms.TextInput(attrs={
                'class': 'form-control',
                'placeholder': 'Example: 3 months / 1 year'
            }),
            'monthly_budget': forms.Select(attrs={'class': 'form-select'}),
            'interested_package': forms.Select(attrs={'class': 'form-select'}),
            'remote_worker': forms.CheckboxInput(attrs={'class': 'form-check-input'}),
            'is_public': forms.CheckboxInput(attrs={'class': 'form-check-input'}),
            'message': forms.Textarea(attrs={
                'class': 'form-control',
                'rows': 4,
                'placeholder': 'Tell us more about your plan'
            }),
        }
        labels = {
            'is_public': 'Show my profile in public listings',
        }
        help_texts = {
            'is_public': 'If checked, your profile may appear in public foreigner listings after approval. If unchecked, your profile will remain private.',
        }


class ConsultationRequestForm(forms.ModelForm):
    class Meta:
        model = ConsultationRequest
        fields = ['lead', 'package', 'preferred_contact_method', 'preferred_date', 'notes']
        widgets = {
            'lead': forms.Select(attrs={'class': 'form-select'}),
            'package': forms.Select(attrs={'class': 'form-select'}),
            'preferred_contact_method': forms.Select(attrs={'class': 'form-select'}),
            'preferred_date': forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}),
            'notes': forms.Textarea(attrs={
                'class': 'form-control',
                'rows': 4,
                'placeholder': 'Add any important details about your plan, preferred area, or questions'
            }),
        }


class ContactMessageForm(forms.ModelForm):
    class Meta:
        model = ContactMessage
        fields = ['name', 'email', 'subject', 'message']
        widgets = {
            'name': forms.TextInput(attrs={
                'class': 'form-control',
                'placeholder': 'Enter your name'
            }),
            'email': forms.EmailInput(attrs={
                'class': 'form-control',
                'placeholder': 'Enter your email'
            }),
            'subject': forms.TextInput(attrs={
                'class': 'form-control',
                'placeholder': 'What would you like to ask?'
            }),
            'message': forms.Textarea(attrs={
                'class': 'form-control',
                'rows': 5,
                'placeholder': 'Write your message here'
            }),
        }

class ForeignerInterestForm(forms.ModelForm):
    class Meta:
        model = ForeignerInterest
        fields = ['message']
        widgets = {
            'message': forms.Textarea(attrs={
                'rows': 4,
                'class': 'form-control',
                'placeholder': 'Write a short message about your interest...'
            }),
        }
        labels = {
            'message': 'Message',
        }
        help_texts = {
            'message': 'Optional note to introduce yourself or explain your interest.',
        }

class WalletTopUpForm(forms.Form):
    amount_usd = forms.DecimalField(
        label='Top-up Amount USD',
        min_value=Decimal('5.00'),
        max_digits=10,
        decimal_places=2,
        widget=forms.NumberInput(attrs={
            'class': 'form-control',
            'placeholder': 'Enter amount in USD',
            'step': '0.01',
            'min': '5',
        })
    )

    payment_method = forms.ChoiceField(
        label='Payment Method',
        choices=[
            ('stripe', 'Stripe'),
            ('paypal', 'PayPal'),
        ],
        widget=forms.RadioSelect
    )

    def clean_amount_usd(self):
        amount = self.cleaned_data.get('amount_usd')

        if amount <= Decimal('0.00'):
            raise forms.ValidationError("Top-up amount must be greater than zero.")

        return amount
    
class GuestHostBookingSelectionForm(forms.Form):
    event_type = forms.ChoiceField(
        label='Event Type',
        choices=EventType.choices,
        widget=forms.Select(attrs={
            'class': 'form-select',
        })
    )

    preferred_event_date = forms.DateField(
        label='Preferred Event Date',
        widget=forms.DateInput(attrs={
            'class': 'form-control',
            'type': 'date',
        })
    )

    preferred_start_time = forms.TimeField(
        label='Preferred Start Time',
        required=False,
        widget=forms.TimeInput(attrs={
            'class': 'form-control',
            'type': 'time',
        })
    )

    expected_duration_hours = forms.DecimalField(
        label='Expected Duration Hours',
        required=False,
        max_digits=5,
        decimal_places=2,
        widget=forms.NumberInput(attrs={
            'class': 'form-control',
            'step': '0.5',
            'min': '0.5',
            'placeholder': 'Example: 2.5',
        })
    )

    number_of_guests = forms.IntegerField(
        label='Number of Guests',
        min_value=1,
        initial=2,
        widget=forms.NumberInput(attrs={
            'class': 'form-control',
            'min': '1',
        })
    )

    selected_package = forms.ModelChoiceField(
        label='Event Package',
        queryset=HostEventPackage.objects.none(),
        required=False,
        empty_label='No package / Decide later',
        widget=forms.Select(attrs={
            'class': 'form-select',
        })
    )

    selected_meal_plan = forms.ModelChoiceField(
        label='Meal Plan',
        queryset=HostMealPlan.objects.none(),
        required=False,
        empty_label='No meal plan / Decide later',
        widget=forms.Select(attrs={
            'class': 'form-select',
        })
    )

    selected_add_ons = forms.ModelMultipleChoiceField(
        label='Add-on Services',
        queryset=HostAddOnService.objects.none(),
        required=False,
        widget=forms.CheckboxSelectMultiple(attrs={
            'class': 'form-check-input',
        })
    )

    occasion_title = forms.CharField(
        label='Occasion Title',
        required=False,
        max_length=255,
        widget=forms.TextInput(attrs={
            'class': 'form-control',
            'placeholder': 'Example: Surprise proposal dinner, birthday celebration...',
        })
    )

    occasion_note = forms.CharField(
        label='Occasion Note',
        required=False,
        widget=forms.Textarea(attrs={
            'class': 'form-control',
            'rows': 4,
            'placeholder': 'Share any personal details that help us understand your intended experience.',
        })
    )

    special_requests = forms.CharField(
        label='Special Requests',
        required=False,
        widget=forms.Textarea(attrs={
            'class': 'form-control',
            'rows': 4,
            'placeholder': 'Any special food, decoration, timing, music, photography, or surprise requirements?',
        })
    )

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

        if venue:
            self.fields['selected_package'].queryset = venue.event_packages.filter(
                is_active=True,
                listing_status=PublicListingStatus.APPROVED
            ).order_by('-is_featured', 'title')

            self.fields['selected_meal_plan'].queryset = venue.meal_plans.filter(
                is_active=True,
                listing_status=PublicListingStatus.APPROVED
            ).order_by('-is_featured', 'title')

            self.fields['selected_add_ons'].queryset = venue.add_on_services.filter(
                is_active=True,
                listing_status=PublicListingStatus.APPROVED
            ).order_by('-is_featured', 'title')

    def clean_preferred_event_date(self):
        preferred_event_date = self.cleaned_data.get('preferred_event_date')

        if preferred_event_date and preferred_event_date < timezone.localdate():
            raise forms.ValidationError("Preferred event date cannot be in the past.")

        return preferred_event_date

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

        selected_package = cleaned_data.get('selected_package')
        selected_meal_plan = cleaned_data.get('selected_meal_plan')
        selected_add_ons = cleaned_data.get('selected_add_ons')

        if self.venue:
            if selected_package and selected_package.venue_id != self.venue.id:
                self.add_error('selected_package', "Selected package does not belong to this venue.")

            if selected_meal_plan and selected_meal_plan.venue_id != self.venue.id:
                self.add_error('selected_meal_plan', "Selected meal plan does not belong to this venue.")

            for add_on in selected_add_ons or []:
                if add_on.venue_id != self.venue.id:
                    self.add_error('selected_add_ons', "One or more selected add-ons do not belong to this venue.")
                    break

        if not selected_package and not selected_meal_plan and not selected_add_ons:
            raise forms.ValidationError(
                "Please select at least one package, meal plan, or add-on service."
            )

        return cleaned_data

