from django import forms
from django.core.exceptions import ValidationError
from django.utils import timezone
from datetime import timedelta
from .models import Codec, Zone, Channel, ChannelZone, Jingle, Show, EPGEntry


class CodecForm(forms.ModelForm):
    """
    Form for creating and editing codec configurations.
    
    Provides validation for codec parameters and ensures
    proper bitrate range configuration.
    """
    
    class Meta:
        model = Codec
        fields = [
            'name', 'codec_type', 'description', 'mime_type',
            'bitrate_min', 'bitrate_max', 'is_active'
        ]
        widgets = {
            'description': forms.Textarea(attrs={'rows': 3}),
            'name': forms.TextInput(attrs={'class': 'form-control'}),
            'codec_type': forms.Select(attrs={'class': 'form-control'}),
            'mime_type': forms.TextInput(attrs={'class': 'form-control'}),
            'bitrate_min': forms.NumberInput(attrs={'class': 'form-control', 'min': '1'}),
            'bitrate_max': forms.NumberInput(attrs={'class': 'form-control', 'min': '1'}),
        }
    
    def clean(self):
        """
        Validate that bitrate_max is greater than bitrate_min.
        """
        cleaned_data = super().clean()
        bitrate_min = cleaned_data.get('bitrate_min')
        bitrate_max = cleaned_data.get('bitrate_max')
        
        if bitrate_min and bitrate_max:
            if bitrate_max <= bitrate_min:
                raise ValidationError(
                    'Maximum bitrate must be greater than minimum bitrate.'
                )
        
        return cleaned_data


class ZoneForm(forms.ModelForm):
    """
    Form for creating and editing distribution zones.
    
    Provides validation for zone codes and timezone configuration.
    """
    
    class Meta:
        model = Zone
        fields = [
            'name', 'code', 'description', 'timezone', 'is_active'
        ]
        widgets = {
            'description': forms.Textarea(attrs={'rows': 3}),
            'name': forms.TextInput(attrs={'class': 'form-control'}),
            'code': forms.TextInput(attrs={
                'class': 'form-control',
                'style': 'text-transform: uppercase;'
            }),
            'timezone': forms.Select(attrs={'class': 'form-control'}),
        }
    
    def __init__(self, *args, **kwargs):
        """
        Initialize form with timezone choices.
        """
        super().__init__(*args, **kwargs)
        # Common timezone choices
        timezone_choices = [
            ('UTC', 'UTC'),
            ('America/New_York', 'Eastern Time (US)'),
            ('America/Chicago', 'Central Time (US)'),
            ('America/Denver', 'Mountain Time (US)'),
            ('America/Los_Angeles', 'Pacific Time (US)'),
            ('Europe/London', 'London'),
            ('Europe/Paris', 'Paris'),
            ('Europe/Berlin', 'Berlin'),
            ('Asia/Tokyo', 'Tokyo'),
            ('Asia/Shanghai', 'Shanghai'),
            ('Asia/Kolkata', 'India'),
            ('Australia/Sydney', 'Sydney'),
        ]
        self.fields['timezone'].widget = forms.Select(
            choices=timezone_choices,
            attrs={'class': 'form-control'}
        )
    
    def clean_code(self):
        """
        Validate and format zone code.
        """
        code = self.cleaned_data.get('code')
        if code:
            code = code.upper().strip()
            if not code.replace('_', '').isalnum():
                raise ValidationError(
                    'Zone code must contain only letters, numbers, and underscores.'
                )
        return code


class ChannelForm(forms.ModelForm):
    """
    Form for creating and editing TV channels.
    
    Provides comprehensive channel configuration with
    validation for channel numbers and content ratings.
    """
    
    class Meta:
        model = Channel
        fields = [
            'name', 'slug', 'call_sign', 'channel_number',
            'channel_type', 'description', 'logo', 'website',
            'content_rating', 'language', 'country',
            'is_active', 'is_hd', 'is_4k', 'launch_date'
        ]
        widgets = {
            'description': forms.Textarea(attrs={'rows': 4}),
            'name': forms.TextInput(attrs={'class': 'form-control'}),
            'slug': forms.TextInput(attrs={'class': 'form-control'}),
            'call_sign': forms.TextInput(attrs={
                'class': 'form-control',
                'style': 'text-transform: uppercase;'
            }),
            'channel_number': forms.NumberInput(attrs={
                'class': 'form-control',
                'min': '1',
                'max': '9999'
            }),
            'channel_type': forms.Select(attrs={'class': 'form-control'}),
            'website': forms.URLInput(attrs={'class': 'form-control'}),
            'content_rating': forms.Select(attrs={'class': 'form-control'}),
            'language': forms.TextInput(attrs={'class': 'form-control'}),
            'country': forms.TextInput(attrs={'class': 'form-control'}),
            'launch_date': forms.DateInput(attrs={
                'class': 'form-control',
                'type': 'date'
            }),
        }
    
    def clean_call_sign(self):
        """
        Validate and format call sign.
        """
        call_sign = self.cleaned_data.get('call_sign')
        if call_sign:
            call_sign = call_sign.upper().strip()
        return call_sign
    
    def clean_channel_number(self):
        """
        Validate channel number uniqueness.
        """
        channel_number = self.cleaned_data.get('channel_number')
        if channel_number:
            # Check if channel number is already taken
            existing = Channel.objects.filter(channel_number=channel_number)
            if self.instance.pk:
                existing = existing.exclude(pk=self.instance.pk)
            if existing.exists():
                raise ValidationError(
                    f'Channel number {channel_number} is already in use.'
                )
        return channel_number


class ChannelZoneForm(forms.ModelForm):
    """
    Form for configuring channel distribution in specific zones.
    
    Provides validation for codec compatibility and
    technical parameter configuration.
    """
    
    class Meta:
        model = ChannelZone
        fields = [
            'channel', 'zone', 'video_codec', 'audio_codec',
            'container_format', 'bitrate', 'resolution_width',
            'resolution_height', 'frame_rate', 'is_active',
            'start_date', 'end_date'
        ]
        widgets = {
            'channel': forms.Select(attrs={'class': 'form-control'}),
            'zone': forms.Select(attrs={'class': 'form-control'}),
            'video_codec': forms.Select(attrs={'class': 'form-control'}),
            'audio_codec': forms.Select(attrs={'class': 'form-control'}),
            'container_format': forms.Select(attrs={'class': 'form-control'}),
            'bitrate': forms.NumberInput(attrs={
                'class': 'form-control',
                'min': '100'
            }),
            'resolution_width': forms.NumberInput(attrs={
                'class': 'form-control',
                'min': '320'
            }),
            'resolution_height': forms.NumberInput(attrs={
                'class': 'form-control',
                'min': '240'
            }),
            'frame_rate': forms.NumberInput(attrs={
                'class': 'form-control',
                'step': '0.01',
                'min': '1.0',
                'max': '120.0'
            }),
            'start_date': forms.DateTimeInput(attrs={
                'class': 'form-control',
                'type': 'datetime-local'
            }),
            'end_date': forms.DateTimeInput(attrs={
                'class': 'form-control',
                'type': 'datetime-local'
            }),
        }
    
    def __init__(self, *args, **kwargs):
        """
        Initialize form with filtered codec choices.
        """
        super().__init__(*args, **kwargs)
        # Filter codecs by type
        self.fields['video_codec'].queryset = Codec.objects.filter(
            codec_type='video', is_active=True
        )
        self.fields['audio_codec'].queryset = Codec.objects.filter(
            codec_type='audio', is_active=True
        )
        self.fields['container_format'].queryset = Codec.objects.filter(
            codec_type='container', is_active=True
        )
    
    def clean(self):
        """
        Validate channel-zone configuration.
        """
        cleaned_data = super().clean()
        channel = cleaned_data.get('channel')
        zone = cleaned_data.get('zone')
        start_date = cleaned_data.get('start_date')
        end_date = cleaned_data.get('end_date')
        
        # Check for duplicate channel-zone combination
        if channel and zone:
            existing = ChannelZone.objects.filter(channel=channel, zone=zone)
            if self.instance.pk:
                existing = existing.exclude(pk=self.instance.pk)
            if existing.exists():
                raise ValidationError(
                    f'Configuration for {channel.name} in {zone.name} already exists.'
                )
        
        # Validate date range
        if start_date and end_date:
            if end_date <= start_date:
                raise ValidationError(
                    'End date must be after start date.'
                )
        
        return cleaned_data


class JingleForm(forms.ModelForm):
    """
    Form for creating and editing channel jingles.
    
    Provides validation for media files and duration configuration.
    """
    
    class Meta:
        model = Jingle
        fields = [
            'name', 'jingle_type', 'channel', 'audio_file',
            'video_file', 'duration', 'description',
            'is_active', 'priority'
        ]
        widgets = {
            'description': forms.Textarea(attrs={'rows': 3}),
            'name': forms.TextInput(attrs={'class': 'form-control'}),
            'jingle_type': forms.Select(attrs={'class': 'form-control'}),
            'channel': forms.Select(attrs={'class': 'form-control'}),
            'duration': forms.TextInput(attrs={
                'class': 'form-control',
                'placeholder': 'HH:MM:SS or MM:SS'
            }),
            'priority': forms.NumberInput(attrs={
                'class': 'form-control',
                'min': '1',
                'max': '10'
            }),
        }
    
    def clean(self):
        """
        Validate that at least one media file is provided.
        """
        cleaned_data = super().clean()
        audio_file = cleaned_data.get('audio_file')
        video_file = cleaned_data.get('video_file')
        
        if not audio_file and not video_file:
            raise ValidationError(
                'At least one file (audio or video) must be provided.'
            )
        
        return cleaned_data


class ShowForm(forms.ModelForm):
    """
    Form for creating and editing TV shows.
    
    Provides comprehensive show metadata management with
    validation for production information.
    """
    
    class Meta:
        model = Show
        fields = [
            'title', 'slug', 'show_type', 'description',
            'short_description', 'poster', 'thumbnail',
            'content_rating', 'language', 'country', 'year',
            'duration', 'genre', 'cast', 'director',
            'producer', 'imdb_id', 'is_active'
        ]
        widgets = {
            'description': forms.Textarea(attrs={'rows': 4}),
            'short_description': forms.Textarea(attrs={'rows': 2}),
            'title': forms.TextInput(attrs={'class': 'form-control'}),
            'slug': forms.TextInput(attrs={'class': 'form-control'}),
            'show_type': forms.Select(attrs={'class': 'form-control'}),
            'content_rating': forms.Select(attrs={'class': 'form-control'}),
            'language': forms.TextInput(attrs={'class': 'form-control'}),
            'country': forms.TextInput(attrs={'class': 'form-control'}),
            'year': forms.NumberInput(attrs={
                'class': 'form-control',
                'min': '1900',
                'max': '2030'
            }),
            'duration': forms.TextInput(attrs={
                'class': 'form-control',
                'placeholder': 'HH:MM:SS'
            }),
            'genre': forms.TextInput(attrs={
                'class': 'form-control',
                'placeholder': 'Drama, Comedy, Action (comma-separated)'
            }),
            'cast': forms.Textarea(attrs={'rows': 3}),
            'director': forms.TextInput(attrs={'class': 'form-control'}),
            'producer': forms.TextInput(attrs={'class': 'form-control'}),
            'imdb_id': forms.TextInput(attrs={'class': 'form-control'}),
        }
    
    def clean_year(self):
        """
        Validate production year.
        """
        year = self.cleaned_data.get('year')
        if year:
            current_year = timezone.now().year
            if year > current_year + 5:
                raise ValidationError(
                    f'Year cannot be more than 5 years in the future ({current_year + 5}).'
                )
        return year


class EPGEntryForm(forms.ModelForm):
    """
    Form for creating and editing EPG entries.
    
    Provides validation for scheduling conflicts and
    episode information management.
    """
    
    class Meta:
        model = EPGEntry
        fields = [
            'channel', 'show', 'start_time', 'end_time',
            'episode_title', 'episode_number', 'season_number',
            'episode_description', 'is_premiere', 'is_finale',
            'is_repeat', 'is_live', 'audio_language',
            'subtitle_language'
        ]
        widgets = {
            'episode_description': forms.Textarea(attrs={'rows': 3}),
            'channel': forms.Select(attrs={'class': 'form-control'}),
            'show': forms.Select(attrs={'class': 'form-control'}),
            'start_time': forms.DateTimeInput(attrs={
                'class': 'form-control',
                'type': 'datetime-local'
            }),
            'end_time': forms.DateTimeInput(attrs={
                'class': 'form-control',
                'type': 'datetime-local'
            }),
            'episode_title': forms.TextInput(attrs={'class': 'form-control'}),
            'episode_number': forms.NumberInput(attrs={
                'class': 'form-control',
                'min': '1'
            }),
            'season_number': forms.NumberInput(attrs={
                'class': 'form-control',
                'min': '1'
            }),
            'audio_language': forms.TextInput(attrs={'class': 'form-control'}),
            'subtitle_language': forms.TextInput(attrs={'class': 'form-control'}),
        }
    
    def clean(self):
        """
        Validate EPG entry for scheduling conflicts.
        """
        cleaned_data = super().clean()
        channel = cleaned_data.get('channel')
        start_time = cleaned_data.get('start_time')
        end_time = cleaned_data.get('end_time')
        
        # Validate time range
        if start_time and end_time:
            if end_time <= start_time:
                raise ValidationError(
                    'End time must be after start time.'
                )
            
            # Check for scheduling conflicts
            if channel:
                conflicting_entries = EPGEntry.objects.filter(
                    channel=channel,
                    start_time__lt=end_time,
                    end_time__gt=start_time
                )
                
                if self.instance.pk:
                    conflicting_entries = conflicting_entries.exclude(
                        pk=self.instance.pk
                    )
                
                if conflicting_entries.exists():
                    conflict = conflicting_entries.first()
                    raise ValidationError(
                        f'Schedule conflict with "{conflict.show.title}" '
                        f'({conflict.start_time.strftime("%Y-%m-%d %H:%M")} - '
                        f'{conflict.end_time.strftime("%H:%M")})'
                    )
        
        return cleaned_data


class EPGBulkImportForm(forms.Form):
    """
    Form for bulk importing EPG entries from CSV files.
    
    Provides validation for CSV format and data integrity.
    """
    csv_file = forms.FileField(
        label='CSV File',
        help_text='Upload a CSV file with EPG entries. Required columns: channel, show, start_time, end_time',
        widget=forms.FileInput(attrs={'class': 'form-control', 'accept': '.csv'})
    )
    overwrite_existing = forms.BooleanField(
        required=False,
        label='Overwrite existing entries',
        help_text='Check to overwrite existing EPG entries for the same time slots'
    )
    
    def clean_csv_file(self):
        """
        Validate CSV file format and size.
        """
        csv_file = self.cleaned_data.get('csv_file')
        
        if csv_file:
            # Check file size (max 10MB)
            if csv_file.size > 10 * 1024 * 1024:
                raise ValidationError(
                    'File size cannot exceed 10MB.'
                )
            
            # Check file extension
            if not csv_file.name.endswith('.csv'):
                raise ValidationError(
                    'File must be in CSV format.'
                )
        
        return csv_file


class ChannelSearchForm(forms.Form):
    """
    Form for searching and filtering channels.
    
    Provides advanced search capabilities with multiple filter options.
    """
    search = forms.CharField(
        required=False,
        widget=forms.TextInput(attrs={
            'class': 'form-control',
            'placeholder': 'Search channels...'
        })
    )
    channel_type = forms.ChoiceField(
        required=False,
        choices=[('', 'All Types')] + Channel.CHANNEL_TYPE_CHOICES,
        widget=forms.Select(attrs={'class': 'form-control'})
    )
    content_rating = forms.ChoiceField(
        required=False,
        choices=[('', 'All Ratings')] + Channel.CONTENT_RATING_CHOICES,
        widget=forms.Select(attrs={'class': 'form-control'})
    )
    is_hd = forms.BooleanField(
        required=False,
        label='HD Only'
    )
    is_4k = forms.BooleanField(
        required=False,
        label='4K Only'
    )
    is_active = forms.BooleanField(
        required=False,
        label='Active Only',
        initial=True
    )