"""Forms for Notifications App

This module provides Django forms for notification management,
including channels, templates, and rules.
"""

from django import forms
from django.core.exceptions import ValidationError
from django.contrib.auth.models import User
import json

from .models import NotificationChannel, NotificationTemplate, NotificationRule


class NotificationChannelForm(forms.ModelForm):
    """
    Form for creating and editing notification channels.
    
    Provides validation for channel configuration including
    type-specific validation and JSON configuration handling.
    """
    
    class Meta:
        model = NotificationChannel
        fields = [
            'name', 'channel_type', 'is_active', 'configuration',
            'rate_limit', 'retry_attempts', 'timeout_seconds'
        ]
        
        widgets = {
            'name': forms.TextInput(attrs={
                'class': 'mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-primary-500 focus:border-primary-500',
                'placeholder': 'Enter channel name'
            }),
            'channel_type': forms.Select(attrs={
                'class': 'mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-primary-500 focus:border-primary-500'
            }),
            'is_active': forms.CheckboxInput(attrs={
                'class': 'h-4 w-4 text-primary-600 focus:ring-primary-500 border-gray-300 rounded'
            }),
            'configuration': forms.Textarea(attrs={
                'class': 'mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-primary-500 focus:border-primary-500',
                'rows': 6,
                'placeholder': 'Enter configuration as JSON'
            }),
            'rate_limit': forms.NumberInput(attrs={
                'class': 'mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-primary-500 focus:border-primary-500',
                'min': 1,
                'max': 1000
            }),
            'retry_attempts': forms.NumberInput(attrs={
                'class': 'mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-primary-500 focus:border-primary-500',
                'min': 0,
                'max': 10
            }),
            'timeout_seconds': forms.NumberInput(attrs={
                'class': 'mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-primary-500 focus:border-primary-500',
                'min': 5,
                'max': 300
            }),
        }
        
        help_texts = {
            'name': 'Unique name for the notification channel',
            'channel_type': 'Select the type of notification channel',
            'is_active': 'Whether this channel is currently active',
            'configuration': 'Channel-specific configuration in JSON format',
            'rate_limit': 'Maximum messages per minute (1-1000)',
            'retry_attempts': 'Number of retry attempts for failed deliveries (0-10)',
            'timeout_seconds': 'Timeout for delivery attempts in seconds (5-300)',
        }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        
        # If editing existing channel, format configuration as pretty JSON
        if self.instance and self.instance.pk and self.instance.configuration:
            self.fields['configuration'].initial = json.dumps(
                self.instance.configuration, indent=2
            )

    def clean_configuration(self):
        """Validate and parse JSON configuration."""
        configuration = self.cleaned_data.get('configuration')
        
        if not configuration:
            raise ValidationError('Configuration is required')
        
        try:
            config_dict = json.loads(configuration)
        except json.JSONDecodeError as e:
            raise ValidationError(f'Invalid JSON format: {e}')
        
        # Validate based on channel type
        channel_type = self.cleaned_data.get('channel_type')
        
        if channel_type == 'telegram':
            self._validate_telegram_config(config_dict)
        elif channel_type == 'email':
            self._validate_email_config(config_dict)
        elif channel_type == 'webhook':
            self._validate_webhook_config(config_dict)
        elif channel_type == 'slack':
            self._validate_slack_config(config_dict)
        elif channel_type == 'discord':
            self._validate_discord_config(config_dict)
        elif channel_type == 'sms':
            self._validate_sms_config(config_dict)
        
        return config_dict

    def _validate_telegram_config(self, config):
        """Validate Telegram channel configuration."""
        required_fields = ['bot_token', 'chat_id']
        for field in required_fields:
            if not config.get(field):
                raise ValidationError(f'Telegram channels require "{field}" in configuration')

    def _validate_email_config(self, config):
        """Validate email channel configuration."""
        required_fields = ['recipients']
        for field in required_fields:
            if not config.get(field):
                raise ValidationError(f'Email channels require "{field}" in configuration')
        
        # Validate recipients is a list
        if not isinstance(config['recipients'], list):
            raise ValidationError('Email recipients must be a list of email addresses')

    def _validate_webhook_config(self, config):
        """Validate webhook channel configuration."""
        required_fields = ['url']
        for field in required_fields:
            if not config.get(field):
                raise ValidationError(f'Webhook channels require "{field}" in configuration')

    def _validate_slack_config(self, config):
        """Validate Slack channel configuration."""
        required_fields = ['webhook_url']
        for field in required_fields:
            if not config.get(field):
                raise ValidationError(f'Slack channels require "{field}" in configuration')

    def _validate_discord_config(self, config):
        """Validate Discord channel configuration."""
        required_fields = ['webhook_url']
        for field in required_fields:
            if not config.get(field):
                raise ValidationError(f'Discord channels require "{field}" in configuration')

    def _validate_sms_config(self, config):
        """Validate SMS channel configuration."""
        required_fields = ['api_key', 'phone_numbers']
        for field in required_fields:
            if not config.get(field):
                raise ValidationError(f'SMS channels require "{field}" in configuration')
        
        # Validate phone_numbers is a list
        if not isinstance(config['phone_numbers'], list):
            raise ValidationError('SMS phone_numbers must be a list of phone numbers')


class NotificationTemplateForm(forms.ModelForm):
    """
    Form for creating and editing notification templates.
    """
    
    class Meta:
        model = NotificationTemplate
        fields = [
            'name', 'template_type', 'subject_template', 'message_template',
            'variables', 'channel_types', 'is_active'
        ]
        
        widgets = {
            'name': forms.TextInput(attrs={
                'class': 'mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-primary-500 focus:border-primary-500',
                'placeholder': 'Enter template name'
            }),
            'template_type': forms.TextInput(attrs={
                'class': 'mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-primary-500 focus:border-primary-500',
                'placeholder': 'e.g., jingle_detected, stream_error'
            }),
            'subject_template': forms.TextInput(attrs={
                'class': 'mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-primary-500 focus:border-primary-500',
                'placeholder': 'Subject template with variables like {{variable_name}}'
            }),
            'message_template': forms.Textarea(attrs={
                'class': 'mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-primary-500 focus:border-primary-500',
                'rows': 4,
                'placeholder': 'Message template with variables like {{variable_name}}'
            }),
            'variables': forms.Textarea(attrs={
                'class': 'mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-primary-500 focus:border-primary-500',
                'rows': 3,
                'placeholder': 'JSON array of variable names: ["variable1", "variable2"]'
            }),
            'channel_types': forms.CheckboxSelectMultiple(),
            'is_active': forms.CheckboxInput(attrs={
                'class': 'h-4 w-4 text-primary-600 focus:ring-primary-500 border-gray-300 rounded'
            }),
        }

    def clean_variables(self):
        """Validate and parse variables JSON."""
        variables = self.cleaned_data.get('variables')
        
        if not variables:
            return []
        
        try:
            variables_list = json.loads(variables)
            if not isinstance(variables_list, list):
                raise ValidationError('Variables must be a JSON array')
            return variables_list
        except json.JSONDecodeError as e:
            raise ValidationError(f'Invalid JSON format: {e}')


class NotificationRuleForm(forms.ModelForm):
    """
    Form for creating and editing notification rules.
    """
    
    class Meta:
        model = NotificationRule
        fields = [
            'name', 'event_type', 'channel', 'template',
            'conditions', 'is_active', 'priority'
        ]
        
        widgets = {
            'name': forms.TextInput(attrs={
                'class': 'mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-primary-500 focus:border-primary-500',
                'placeholder': 'Enter rule name'
            }),
            'event_type': forms.TextInput(attrs={
                'class': 'mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-primary-500 focus:border-primary-500',
                'placeholder': 'e.g., jingle_detected, stream_error'
            }),
            'channel': forms.Select(attrs={
                'class': 'mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-primary-500 focus:border-primary-500'
            }),
            'template': forms.Select(attrs={
                'class': 'mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-primary-500 focus:border-primary-500'
            }),
            'conditions': forms.Textarea(attrs={
                'class': 'mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-primary-500 focus:border-primary-500',
                'rows': 3,
                'placeholder': 'JSON conditions for rule triggering'
            }),
            'priority': forms.Select(attrs={
                'class': 'mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-primary-500 focus:border-primary-500'
            }),
            'is_active': forms.CheckboxInput(attrs={
                'class': 'h-4 w-4 text-primary-600 focus:ring-primary-500 border-gray-300 rounded'
            }),
        }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        
        # Filter active channels and templates
        self.fields['channel'].queryset = NotificationChannel.objects.filter(is_active=True)
        self.fields['template'].queryset = NotificationTemplate.objects.filter(is_active=True)

    def clean_conditions(self):
        """Validate and parse conditions JSON."""
        conditions = self.cleaned_data.get('conditions')
        
        if not conditions:
            return {}
        
        try:
            conditions_dict = json.loads(conditions)
            return conditions_dict
        except json.JSONDecodeError as e:
            raise ValidationError(f'Invalid JSON format: {e}')