# -*- coding: utf-8 -*-
"""
Core App Forms

This module contains common forms and form utilities for the application.
"""

from django import forms
from django.core.exceptions import ValidationError
from django.contrib.auth import get_user_model
from django.utils import timezone
from django.conf import settings
import re

User = get_user_model()


class BaseForm(forms.Form):
    """
    Base form class with common functionality.
    """
    
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # Add common CSS classes to all form fields
        for field_name, field in self.fields.items():
            if isinstance(field.widget, (forms.TextInput, forms.EmailInput, forms.PasswordInput)):
                field.widget.attrs.update({'class': 'form-control'})
            elif isinstance(field.widget, forms.Textarea):
                field.widget.attrs.update({'class': 'form-control', 'rows': 4})
            elif isinstance(field.widget, forms.Select):
                field.widget.attrs.update({'class': 'form-control'})
            elif isinstance(field.widget, forms.CheckboxInput):
                field.widget.attrs.update({'class': 'form-check-input'})


class ContactForm(BaseForm):
    """
    Contact form for general inquiries.
    """
    
    SUBJECT_CHOICES = [
        ('general', 'General Inquiry'),
        ('support', 'Technical Support'),
        ('billing', 'Billing Question'),
        ('feature', 'Feature Request'),
        ('bug', 'Bug Report'),
        ('other', 'Other'),
    ]
    
    name = forms.CharField(
        max_length=100,
        widget=forms.TextInput(attrs={
            'placeholder': 'Your full name'
        })
    )
    
    email = forms.EmailField(
        widget=forms.EmailInput(attrs={
            'placeholder': 'your.email@example.com'
        })
    )
    
    subject = forms.ChoiceField(
        choices=SUBJECT_CHOICES,
        widget=forms.Select(attrs={
            'class': 'form-control'
        })
    )
    
    message = forms.CharField(
        widget=forms.Textarea(attrs={
            'placeholder': 'Please describe your inquiry in detail...',
            'rows': 6
        })
    )
    
    def clean_message(self):
        """
        Validate message content.
        """
        message = self.cleaned_data.get('message')
        
        if len(message) < 10:
            raise ValidationError('Message must be at least 10 characters long.')
        
        if len(message) > 2000:
            raise ValidationError('Message cannot exceed 2000 characters.')
        
        return message


class FeedbackForm(BaseForm):
    """
    User feedback form.
    """
    
    RATING_CHOICES = [
        (1, '1 - Very Poor'),
        (2, '2 - Poor'),
        (3, '3 - Average'),
        (4, '4 - Good'),
        (5, '5 - Excellent'),
    ]
    
    CATEGORY_CHOICES = [
        ('usability', 'Usability'),
        ('performance', 'Performance'),
        ('features', 'Features'),
        ('design', 'Design'),
        ('documentation', 'Documentation'),
        ('other', 'Other'),
    ]
    
    category = forms.ChoiceField(
        choices=CATEGORY_CHOICES,
        help_text='What aspect of the application is this feedback about?'
    )
    
    rating = forms.ChoiceField(
        choices=RATING_CHOICES,
        widget=forms.RadioSelect,
        help_text='How would you rate this aspect?'
    )
    
    feedback = forms.CharField(
        widget=forms.Textarea(attrs={
            'placeholder': 'Please share your detailed feedback...',
            'rows': 5
        }),
        help_text='Your detailed feedback helps us improve the application.'
    )
    
    email = forms.EmailField(
        required=False,
        widget=forms.EmailInput(attrs={
            'placeholder': 'your.email@example.com (optional)'
        }),
        help_text='Optional: Provide your email if you want us to follow up.'
    )
    
    def clean_feedback(self):
        """
        Validate feedback content.
        """
        feedback = self.cleaned_data.get('feedback')
        
        if len(feedback) < 5:
            raise ValidationError('Feedback must be at least 5 characters long.')
        
        return feedback


class SearchForm(BaseForm):
    """
    Global search form.
    """
    
    SEARCH_TYPE_CHOICES = [
        ('all', 'All'),
        ('campaigns', 'Campaigns'),
        ('advertisers', 'Advertisers'),
        ('channels', 'Channels'),
        ('activities', 'Activities'),
    ]
    
    query = forms.CharField(
        max_length=200,
        widget=forms.TextInput(attrs={
            'placeholder': 'Search...',
            'class': 'form-control search-input'
        })
    )
    
    search_type = forms.ChoiceField(
        choices=SEARCH_TYPE_CHOICES,
        required=False,
        initial='all',
        widget=forms.Select(attrs={
            'class': 'form-control search-type'
        })
    )
    
    def clean_query(self):
        """
        Validate search query.
        """
        query = self.cleaned_data.get('query')
        
        if len(query) < 2:
            raise ValidationError('Search query must be at least 2 characters long.')
        
        # Remove potentially harmful characters
        query = re.sub(r'[<>"\']', '', query)
        
        return query.strip()


class DateRangeForm(BaseForm):
    """
    Date range selection form.
    """
    
    PRESET_CHOICES = [
        ('', 'Custom Range'),
        ('today', 'Today'),
        ('yesterday', 'Yesterday'),
        ('last_7_days', 'Last 7 Days'),
        ('last_30_days', 'Last 30 Days'),
        ('this_month', 'This Month'),
        ('last_month', 'Last Month'),
        ('this_year', 'This Year'),
    ]
    
    preset = forms.ChoiceField(
        choices=PRESET_CHOICES,
        required=False,
        widget=forms.Select(attrs={
            'class': 'form-control date-preset'
        })
    )
    
    start_date = forms.DateField(
        required=False,
        widget=forms.DateInput(attrs={
            'type': 'date',
            'class': 'form-control'
        })
    )
    
    end_date = forms.DateField(
        required=False,
        widget=forms.DateInput(attrs={
            'type': 'date',
            'class': 'form-control'
        })
    )
    
    def clean(self):
        """
        Validate date range.
        """
        cleaned_data = super().clean()
        start_date = cleaned_data.get('start_date')
        end_date = cleaned_data.get('end_date')
        preset = cleaned_data.get('preset')
        
        # If preset is selected, dates are not required
        if preset:
            return cleaned_data
        
        # For custom range, both dates are required
        if not start_date or not end_date:
            raise ValidationError('Both start and end dates are required for custom range.')
        
        # Validate date order
        if start_date > end_date:
            raise ValidationError('Start date must be before end date.')
        
        # Validate date range is not too large
        date_diff = (end_date - start_date).days
        if date_diff > 365:
            raise ValidationError('Date range cannot exceed 365 days.')
        
        # Validate dates are not in the future
        today = timezone.now().date()
        if start_date > today or end_date > today:
            raise ValidationError('Dates cannot be in the future.')
        
        return cleaned_data


class ExportForm(BaseForm):
    """
    Data export form.
    """
    
    FORMAT_CHOICES = [
        ('csv', 'CSV'),
        ('xlsx', 'Excel'),
        ('pdf', 'PDF'),
        ('json', 'JSON'),
    ]
    
    format = forms.ChoiceField(
        choices=FORMAT_CHOICES,
        initial='csv',
        widget=forms.RadioSelect
    )
    
    include_headers = forms.BooleanField(
        required=False,
        initial=True,
        help_text='Include column headers in the export'
    )
    
    date_format = forms.CharField(
        max_length=50,
        initial='%Y-%m-%d',
        help_text='Date format for exported data (e.g., %Y-%m-%d for YYYY-MM-DD)',
        widget=forms.TextInput(attrs={
            'placeholder': '%Y-%m-%d'
        })
    )
    
    def clean_date_format(self):
        """
        Validate date format string.
        """
        date_format = self.cleaned_data.get('date_format')
        
        try:
            # Test the format with a sample date
            test_date = timezone.now().date()
            test_date.strftime(date_format)
        except ValueError:
            raise ValidationError('Invalid date format string.')
        
        return date_format


class BulkActionForm(BaseForm):
    """
    Bulk action form for list views.
    """
    
    ACTION_CHOICES = [
        ('', 'Select Action'),
        ('delete', 'Delete Selected'),
        ('export', 'Export Selected'),
        ('activate', 'Activate Selected'),
        ('deactivate', 'Deactivate Selected'),
    ]
    
    action = forms.ChoiceField(
        choices=ACTION_CHOICES,
        widget=forms.Select(attrs={
            'class': 'form-control bulk-action-select'
        })
    )
    
    selected_items = forms.CharField(
        widget=forms.HiddenInput(),
        required=False
    )
    
    confirm = forms.BooleanField(
        required=False,
        widget=forms.CheckboxInput(attrs={
            'class': 'form-check-input bulk-confirm'
        }),
        help_text='I confirm that I want to perform this action on the selected items.'
    )
    
    def clean(self):
        """
        Validate bulk action form.
        """
        cleaned_data = super().clean()
        action = cleaned_data.get('action')
        selected_items = cleaned_data.get('selected_items')
        confirm = cleaned_data.get('confirm')
        
        if not action:
            raise ValidationError('Please select an action.')
        
        if not selected_items:
            raise ValidationError('No items selected.')
        
        # For destructive actions, require confirmation
        if action in ['delete'] and not confirm:
            raise ValidationError('Please confirm the action by checking the confirmation box.')
        
        return cleaned_data
    
    def clean_selected_items(self):
        """
        Validate selected items.
        """
        selected_items = self.cleaned_data.get('selected_items')
        
        if not selected_items:
            return []
        
        try:
            # Parse comma-separated IDs
            item_ids = [int(id.strip()) for id in selected_items.split(',') if id.strip()]
        except ValueError:
            raise ValidationError('Invalid item IDs.')
        
        if not item_ids:
            raise ValidationError('No valid items selected.')
        
        return item_ids


class SettingsForm(BaseForm):
    """
    Application settings form.
    """
    
    TIMEZONE_CHOICES = [
        ('UTC', 'UTC'),
        ('US/Eastern', 'Eastern Time'),
        ('US/Central', 'Central Time'),
        ('US/Mountain', 'Mountain Time'),
        ('US/Pacific', 'Pacific Time'),
        ('Europe/London', 'London'),
        ('Europe/Paris', 'Paris'),
        ('Asia/Tokyo', 'Tokyo'),
    ]
    
    LANGUAGE_CHOICES = [
        ('en', 'English'),
        ('es', 'Spanish'),
        ('fr', 'French'),
        ('de', 'German'),
    ]
    
    timezone = forms.ChoiceField(
        choices=TIMEZONE_CHOICES,
        initial='UTC',
        help_text='Your preferred timezone for displaying dates and times'
    )
    
    language = forms.ChoiceField(
        choices=LANGUAGE_CHOICES,
        initial='en',
        help_text='Your preferred language for the interface'
    )
    
    email_notifications = forms.BooleanField(
        required=False,
        initial=True,
        help_text='Receive email notifications for important updates'
    )
    
    items_per_page = forms.IntegerField(
        min_value=10,
        max_value=100,
        initial=20,
        help_text='Number of items to display per page in lists'
    )
    
    def clean_items_per_page(self):
        """
        Validate items per page setting.
        """
        items_per_page = self.cleaned_data.get('items_per_page')
        
        if items_per_page % 10 != 0:
            raise ValidationError('Items per page must be a multiple of 10.')
        
        return items_per_page