"""Channels Admin

This module configures the Django admin interface for channel management.
It provides comprehensive admin functionality for managing channels, zones,
codecs, jingles, and time slots.

Admin Classes:
    - ChannelAdmin: Channel management with inlines
    - ChannelZoneAdmin: Zone management
    - ChannelCodecAdmin: Codec configuration management
    - JingleAdmin: Jingle management with file handling
    - DayTimeAdmin: Time slot management

Features:
- Custom display fields and formatting
- Advanced filtering and search
- Inline editing for related models
- Bulk actions for common operations
- Custom admin actions
- File upload handling
- Read-only fields for computed values
"""

from django.contrib import admin
from django.utils.html import format_html
from django.utils.safestring import mark_safe
from django.urls import reverse
from django.db.models import Count
from django.utils import timezone
from django.contrib.admin import SimpleListFilter

from .models import Channel, ChannelZone, ChannelCodec, Jingle, DayTime


# ============================================================================
# Custom Filters
# ============================================================================

class ProviderFilter(SimpleListFilter):
    """Custom filter for channel providers."""
    title = 'Provider'
    parameter_name = 'provider'
    
    def lookups(self, request, model_admin):
        """Return filter options."""
        return Channel.PROVIDER_CHOICES
    
    def queryset(self, request, queryset):
        """Filter queryset based on selected provider."""
        if self.value():
            return queryset.filter(provider=self.value())
        return queryset


class HasZonesFilter(SimpleListFilter):
    """Filter channels that have zones configured."""
    title = 'Has Zones'
    parameter_name = 'has_zones'
    
    def lookups(self, request, model_admin):
        """Return filter options."""
        return (
            ('yes', 'Has Zones'),
            ('no', 'No Zones'),
        )
    
    def queryset(self, request, queryset):
        """Filter queryset based on zone existence."""
        if self.value() == 'yes':
            return queryset.filter(zones__isnull=False).distinct()
        elif self.value() == 'no':
            return queryset.filter(zones__isnull=True)
        return queryset


class HasJinglesFilter(SimpleListFilter):
    """Filter channels that have jingles."""
    title = 'Has Jingles'
    parameter_name = 'has_jingles'
    
    def lookups(self, request, model_admin):
        """Return filter options."""
        return (
            ('yes', 'Has Jingles'),
            ('no', 'No Jingles'),
        )
    
    def queryset(self, request, queryset):
        """Filter queryset based on jingle existence."""
        if self.value() == 'yes':
            return queryset.filter(jingles__isnull=False).distinct()
        elif self.value() == 'no':
            return queryset.filter(jingles__isnull=True)
        return queryset


class JingleTypeFilter(SimpleListFilter):
    """Filter jingles by type."""
    title = 'Jingle Type'
    parameter_name = 'jingle_type'
    
    def lookups(self, request, model_admin):
        """Return filter options."""
        return (
            ('intro', 'Intro'),
            ('outro', 'Outro'),
            ('transition', 'Transition'),
            ('general', 'General'),
        )
    
    def queryset(self, request, queryset):
        """Filter queryset based on jingle type."""
        if self.value() == 'intro':
            return queryset.filter(is_intro=True)
        elif self.value() == 'outro':
            return queryset.filter(is_outro=True)
        elif self.value() == 'transition':
            return queryset.filter(is_transition=True)
        elif self.value() == 'general':
            return queryset.filter(
                is_intro=False,
                is_outro=False,
                is_transition=False
            )
        return queryset


# ============================================================================
# Inline Admin Classes
# ============================================================================

class ChannelZoneInline(admin.TabularInline):
    """Inline admin for channel zones."""
    model = ChannelZone
    extra = 0
    fields = [
        'zone_name', 'region_name', 'is_primary',
        'broadcast_start_time', 'broadcast_end_time', 'status'
    ]
    readonly_fields = ['created_at', 'updated_at']
    
    def get_queryset(self, request):
        """Optimize queryset for inline display."""
        return super().get_queryset(request).select_related('channel')


class ChannelCodecInline(admin.TabularInline):
    """Inline admin for channel codecs."""
    model = ChannelCodec
    extra = 0
    fields = [
        'quality_level', 'video_codec', 'audio_codec',
        'bitrate', 'resolution', 'is_default', 'status'
    ]
    readonly_fields = ['created_at', 'updated_at']


class JingleInline(admin.TabularInline):
    """Inline admin for jingles."""
    model = Jingle
    extra = 0
    fields = [
        'name', 'duration', 'is_intro', 'is_outro',
        'is_transition', 'play_order', 'status'
    ]
    readonly_fields = ['duration', 'file_size', 'created_at']
    
    def get_queryset(self, request):
        """Optimize queryset for inline display."""
        return super().get_queryset(request).select_related('channel')


# ============================================================================
# Main Admin Classes
# ============================================================================

@admin.register(Channel)
class ChannelAdmin(admin.ModelAdmin):
    """Admin interface for Channel model.
    
    Provides comprehensive management of TV channels with
    inline editing for zones, codecs, and jingles.
    """
    
    list_display = [
        'name', 'channel_code', 'provider_display', 'resolution_display',
        'hd_4k_support', 'zone_count', 'jingle_count', 'status_display',
        'created_at'
    ]
    
    list_filter = [
        ProviderFilter, 'is_hd', 'is_4k', 'default_codec',
        'audio_codec', 'status', HasZonesFilter, HasJinglesFilter,
        'created_at', 'updated_at'
    ]
    
    search_fields = [
        'name', 'channel_code', 'description', 'region',
        'ftp_channel_name', 'language'
    ]
    
    readonly_fields = [
        'id', 'total_zones', 'total_jingles', 'created_at',
        'updated_at', 'created_by', 'updated_by'
    ]
    
    fieldsets = (
        ('Basic Information', {
            'fields': (
                'name', 'channel_code', 'description', 'logo'
            )
        }),
        ('Provider Configuration', {
            'fields': (
                'provider', 'ftp_channel_name'
            )
        }),
        ('Technical Specifications', {
            'fields': (
                ('is_hd', 'is_4k'),
                ('default_codec', 'audio_codec'),
                ('bitrate', 'resolution'),
                ('frame_rate', 'aspect_ratio')
            )
        }),
        ('Localization', {
            'fields': (
                ('language', 'region'),
                'time_zone', 'epg_source'
            )
        }),
        ('Status & Metadata', {
            'fields': (
                'status', 'total_zones', 'total_jingles'
            )
        }),
        ('Audit Information', {
            'fields': (
                ('created_at', 'updated_at'),
                ('created_by', 'updated_by')
            ),
            'classes': ('collapse',)
        })
    )
    
    inlines = [ChannelZoneInline, ChannelCodecInline, JingleInline]
    
    actions = ['activate_channels', 'deactivate_channels', 'export_channels']
    
    def get_queryset(self, request):
        """Optimize queryset with annotations."""
        return super().get_queryset(request).annotate(
            zone_count=Count('zones'),
            jingle_count=Count('jingles')
        )
    
    def provider_display(self, obj):
        """Display provider with icon."""
        provider_icons = {
            'sfr': '📺',
            'bouygues': '📡',
            'orange': '🟠',
            'free': '🆓',
            'canal': '📺',
            'other': '❓'
        }
        icon = provider_icons.get(obj.provider, '❓')
        return f"{icon} {obj.get_provider_display()}"
    provider_display.short_description = 'Provider'
    
    def resolution_display(self, obj):
        """Display resolution with quality indicator."""
        quality_colors = {
            '720x576': '#FFA500',    # Orange for SD
            '1280x720': '#32CD32',   # Green for HD
            '1920x1080': '#1E90FF',  # Blue for Full HD
            '3840x2160': '#FF1493',  # Pink for 4K
            '7680x4320': '#8A2BE2'   # Purple for 8K
        }
        color = quality_colors.get(obj.resolution, '#666666')
        return format_html(
            '<span style="color: {}; font-weight: bold;">{}</span>',
            color, obj.resolution
        )
    resolution_display.short_description = 'Resolution'
    
    def hd_4k_support(self, obj):
        """Display HD/4K support with icons."""
        icons = []
        if obj.is_hd:
            icons.append('🔵 HD')
        if obj.is_4k:
            icons.append('🔴 4K')
        return ' '.join(icons) if icons else '⚪ SD'
    hd_4k_support.short_description = 'Quality Support'
    
    def zone_count(self, obj):
        """Display zone count."""
        count = getattr(obj, 'zone_count', 0)
        if count > 0:
            url = reverse('admin:channels_channelzone_changelist')
            return format_html(
                '<a href="{}?channel__id__exact={}">{} zones</a>',
                url, obj.pk, count
            )
        return '0 zones'
    zone_count.short_description = 'Zones'
    zone_count.admin_order_field = 'zone_count'
    
    def jingle_count(self, obj):
        """Display jingle count."""
        count = getattr(obj, 'jingle_count', 0)
        if count > 0:
            url = reverse('admin:channels_jingle_changelist')
            return format_html(
                '<a href="{}?channel__id__exact={}">{} jingles</a>',
                url, obj.pk, count
            )
        return '0 jingles'
    jingle_count.short_description = 'Jingles'
    jingle_count.admin_order_field = 'jingle_count'
    
    def status_display(self, obj):
        """Display status with color coding."""
        colors = {
            'active': '#28a745',
            'inactive': '#dc3545'
        }
        color = colors.get(obj.status, '#6c757d')
        return format_html(
            '<span style="color: {}; font-weight: bold;">{}</span>',
            color, obj.status.title()
        )
    status_display.short_description = 'Status'
    
    def activate_channels(self, request, queryset):
        """Bulk activate channels."""
        updated = queryset.update(
            status='active',
            updated_by=request.user,
            updated_at=timezone.now()
        )
        self.message_user(
            request,
            f'Successfully activated {updated} channels.'
        )
    activate_channels.short_description = 'Activate selected channels'
    
    def deactivate_channels(self, request, queryset):
        """Bulk deactivate channels."""
        updated = queryset.update(
            status='inactive',
            updated_by=request.user,
            updated_at=timezone.now()
        )
        self.message_user(
            request,
            f'Successfully deactivated {updated} channels.'
        )
    deactivate_channels.short_description = 'Deactivate selected channels'
    
    def export_channels(self, request, queryset):
        """Export selected channels."""
        # This would implement export functionality
        self.message_user(
            request,
            f'Export functionality would export {queryset.count()} channels.'
        )
    export_channels.short_description = 'Export selected channels'


@admin.register(ChannelZone)
class ChannelZoneAdmin(admin.ModelAdmin):
    """Admin interface for ChannelZone model."""
    
    list_display = [
        'zone_name', 'channel_link', 'region_name', 'primary_indicator',
        'broadcast_times', 'time_offset_display', 'status_display'
    ]
    
    list_filter = [
        'channel', 'is_primary', 'status', 'created_at'
    ]
    
    search_fields = [
        'zone_name', 'region_name', 'description',
        'channel__name', 'channel__channel_code'
    ]
    
    readonly_fields = [
        'id', 'duration_minutes', 'created_at', 'updated_at',
        'created_by', 'updated_by'
    ]
    
    fieldsets = (
        ('Zone Information', {
            'fields': (
                'channel', 'zone_name', 'region_name', 'description'
            )
        }),
        ('Configuration', {
            'fields': (
                'ftp_path', 'is_primary'
            )
        }),
        ('Broadcast Schedule', {
            'fields': (
                ('broadcast_start_time', 'broadcast_end_time'),
                'time_offset', 'duration_minutes'
            )
        }),
        ('Status & Audit', {
            'fields': (
                'status', 'created_at', 'updated_at',
                'created_by', 'updated_by'
            )
        })
    )
    
    def channel_link(self, obj):
        """Display channel as clickable link."""
        url = reverse('admin:channels_channel_change', args=[obj.channel.pk])
        return format_html('<a href="{}">{}</a>', url, obj.channel.name)
    channel_link.short_description = 'Channel'
    
    def primary_indicator(self, obj):
        """Display primary zone indicator."""
        return '⭐ Primary' if obj.is_primary else ''
    primary_indicator.short_description = 'Primary'
    
    def broadcast_times(self, obj):
        """Display broadcast time range."""
        if obj.broadcast_start_time and obj.broadcast_end_time:
            return f"{obj.broadcast_start_time} - {obj.broadcast_end_time}"
        return 'Not set'
    broadcast_times.short_description = 'Broadcast Times'
    
    def time_offset_display(self, obj):
        """Display time offset with sign."""
        if obj.time_offset == 0:
            return 'UTC'
        sign = '+' if obj.time_offset > 0 else ''
        hours = obj.time_offset // 60
        minutes = abs(obj.time_offset % 60)
        return f"UTC{sign}{hours}:{minutes:02d}"
    time_offset_display.short_description = 'Time Offset'
    
    def status_display(self, obj):
        """Display status with color coding."""
        colors = {
            'active': '#28a745',
            'inactive': '#dc3545'
        }
        color = colors.get(obj.status, '#6c757d')
        return format_html(
            '<span style="color: {}; font-weight: bold;">{}</span>',
            color, obj.status.title()
        )
    status_display.short_description = 'Status'


@admin.register(ChannelCodec)
class ChannelCodecAdmin(admin.ModelAdmin):
    """Admin interface for ChannelCodec model."""
    
    list_display = [
        'channel_link', 'quality_level', 'codec_info',
        'resolution', 'bitrate_display', 'default_indicator', 'status_display'
    ]
    
    list_filter = [
        'channel', 'quality_level', 'video_codec', 'audio_codec',
        'resolution', 'is_default', 'status'
    ]
    
    search_fields = [
        'channel__name', 'quality_level', 'video_codec', 'audio_codec'
    ]
    
    readonly_fields = [
        'id', 'created_at', 'updated_at', 'created_by', 'updated_by'
    ]
    
    fieldsets = (
        ('Channel & Quality', {
            'fields': (
                'channel', 'quality_level', 'is_default'
            )
        }),
        ('Video Configuration', {
            'fields': (
                'video_codec', 'resolution', 'frame_rate', 'bitrate'
            )
        }),
        ('Audio Configuration', {
            'fields': (
                'audio_codec', 'audio_bitrate', 'audio_sample_rate'
            )
        }),
        ('Status & Audit', {
            'fields': (
                'status', 'created_at', 'updated_at',
                'created_by', 'updated_by'
            )
        })
    )
    
    def channel_link(self, obj):
        """Display channel as clickable link."""
        url = reverse('admin:channels_channel_change', args=[obj.channel.pk])
        return format_html('<a href="{}">{}</a>', url, obj.channel.name)
    channel_link.short_description = 'Channel'
    
    def codec_info(self, obj):
        """Display codec information."""
        return f"{obj.video_codec.upper()} / {obj.audio_codec.upper()}"
    codec_info.short_description = 'Codecs'
    
    def bitrate_display(self, obj):
        """Display bitrate information."""
        return f"{obj.bitrate}k / {obj.audio_bitrate}k"
    bitrate_display.short_description = 'Bitrates (V/A)'
    
    def default_indicator(self, obj):
        """Display default codec indicator."""
        return '⭐ Default' if obj.is_default else ''
    default_indicator.short_description = 'Default'
    
    def status_display(self, obj):
        """Display status with color coding."""
        colors = {
            'active': '#28a745',
            'inactive': '#dc3545'
        }
        color = colors.get(obj.status, '#6c757d')
        return format_html(
            '<span style="color: {}; font-weight: bold;">{}</span>',
            color, obj.status.title()
        )
    status_display.short_description = 'Status'


@admin.register(Jingle)
class JingleAdmin(admin.ModelAdmin):
    """Admin interface for Jingle model."""
    
    list_display = [
        'name', 'channel_link', 'jingle_type_display', 'duration_display',
        'file_info', 'play_order', 'audio_preview', 'status_display'
    ]
    
    list_filter = [
        'channel', JingleTypeFilter, 'audio_format', 'status', 'created_at'
    ]
    
    search_fields = [
        'name', 'description', 'channel__name', 'audio_format'
    ]
    
    readonly_fields = [
        'id', 'duration', 'file_size', 'file_size_mb', 'audio_format',
        'sample_rate', 'bitrate', 'jingle_type', 'created_at', 'updated_at',
        'created_by', 'updated_by'
    ]
    
    fieldsets = (
        ('Jingle Information', {
            'fields': (
                'channel', 'name', 'description', 'audio_file'
            )
        }),
        ('Jingle Type', {
            'fields': (
                ('is_intro', 'is_outro', 'is_transition'),
                'play_order'
            )
        }),
        ('Audio Properties', {
            'fields': (
                ('duration', 'file_size_mb'),
                ('audio_format', 'sample_rate', 'bitrate')
            ),
            'classes': ('collapse',)
        }),
        ('Status & Audit', {
            'fields': (
                'status', 'created_at', 'updated_at',
                'created_by', 'updated_by'
            )
        })
    )
    
    def channel_link(self, obj):
        """Display channel as clickable link."""
        url = reverse('admin:channels_channel_change', args=[obj.channel.pk])
        return format_html('<a href="{}">{}</a>', url, obj.channel.name)
    channel_link.short_description = 'Channel'
    
    def jingle_type_display(self, obj):
        """Display jingle type with icons."""
        types = []
        if obj.is_intro:
            types.append('🎵 Intro')
        if obj.is_outro:
            types.append('🎶 Outro')
        if obj.is_transition:
            types.append('🔄 Transition')
        return ' '.join(types) if types else '🎼 General'
    jingle_type_display.short_description = 'Type'
    
    def duration_display(self, obj):
        """Display duration in readable format."""
        if obj.duration:
            minutes = int(obj.duration // 60)
            seconds = int(obj.duration % 60)
            if minutes > 0:
                return f"{minutes}m {seconds}s"
            return f"{seconds}s"
        return 'Unknown'
    duration_display.short_description = 'Duration'
    
    def file_info(self, obj):
        """Display file information."""
        if obj.audio_file:
            return f"{obj.audio_format.upper()} ({obj.file_size_mb} MB)"
        return 'No file'
    file_info.short_description = 'File Info'
    
    def audio_preview(self, obj):
        """Display audio preview link."""
        if obj.audio_file:
            return format_html(
                '<audio controls style="width: 200px;"><source src="{}" type="audio/{}"></audio>',
                obj.audio_file.url, obj.audio_format
            )
        return 'No audio'
    audio_preview.short_description = 'Preview'
    
    def status_display(self, obj):
        """Display status with color coding."""
        colors = {
            'active': '#28a745',
            'inactive': '#dc3545'
        }
        color = colors.get(obj.status, '#6c757d')
        return format_html(
            '<span style="color: {}; font-weight: bold;">{}</span>',
            color, obj.status.title()
        )
    status_display.short_description = 'Status'


@admin.register(DayTime)
class DayTimeAdmin(admin.ModelAdmin):
    """Admin interface for DayTime model."""
    
    list_display = [
        'name', 'day_display', 'time_range', 'duration_display',
        'priority_display', 'special_indicators', 'status_display'
    ]
    
    list_filter = [
        'day_of_week', 'is_prime_time', 'is_weekend', 'priority', 'status'
    ]
    
    search_fields = ['name', 'description']
    
    readonly_fields = [
        'id', 'duration_minutes', 'created_at', 'updated_at',
        'created_by', 'updated_by'
    ]
    
    fieldsets = (
        ('Time Slot Information', {
            'fields': (
                'name', 'description'
            )
        }),
        ('Schedule', {
            'fields': (
                'day_of_week', ('start_time', 'end_time'), 'duration_minutes'
            )
        }),
        ('Properties', {
            'fields': (
                ('is_prime_time', 'is_weekend'), 'priority'
            )
        }),
        ('Status & Audit', {
            'fields': (
                'status', 'created_at', 'updated_at',
                'created_by', 'updated_by'
            )
        })
    )
    
    def day_display(self, obj):
        """Display day of week."""
        return obj.get_day_of_week_display()
    day_display.short_description = 'Day'
    
    def time_range(self, obj):
        """Display time range."""
        return f"{obj.start_time} - {obj.end_time}"
    time_range.short_description = 'Time Range'
    
    def duration_display(self, obj):
        """Display duration in readable format."""
        minutes = obj.duration_minutes
        if minutes >= 60:
            hours = minutes // 60
            remaining_minutes = minutes % 60
            if remaining_minutes > 0:
                return f"{hours}h {remaining_minutes}m"
            return f"{hours}h"
        return f"{minutes}m"
    duration_display.short_description = 'Duration'
    
    def priority_display(self, obj):
        """Display priority with visual indicator."""
        stars = '⭐' * obj.priority
        return f"{obj.priority} {stars}"
    priority_display.short_description = 'Priority'
    
    def special_indicators(self, obj):
        """Display special time slot indicators."""
        indicators = []
        if obj.is_prime_time:
            indicators.append('🌟 Prime')
        if obj.is_weekend:
            indicators.append('📅 Weekend')
        return ' '.join(indicators)
    special_indicators.short_description = 'Special'
    
    def status_display(self, obj):
        """Display status with color coding."""
        colors = {
            'active': '#28a745',
            'inactive': '#dc3545'
        }
        color = colors.get(obj.status, '#6c757d')
        return format_html(
            '<span style="color: {}; font-weight: bold;">{}</span>',
            color, obj.status.title()
        )
    status_display.short_description = 'Status'


# ============================================================================
# Admin Site Customization
# ============================================================================

# Customize admin site header and title
admin.site.site_header = 'Adtlas Channel Management'
admin.site.site_title = 'Adtlas Channels'
admin.site.index_title = 'Channel Management Dashboard'