# -*- coding: utf-8 -*-
"""
Channel Management API Serializers

This module provides Django REST Framework serializers for channel management
models including channels, zones, codecs, EPG programs, jingles, and schedules.
"""

from rest_framework import serializers
from rest_framework.fields import SerializerMethodField
from django.utils.translation import gettext_lazy as _
from django.contrib.auth import get_user_model
from django.utils import timezone

from ...models import (
    Channel, ChannelZone, ChannelCodec, ChannelZoneRelation,
    EPGProgram, Jingle, JingleDetection, ChannelSchedule,
    VPNConfiguration, IPSecConfiguration, OpenVPNConfiguration, WireGuardConfiguration
)

User = get_user_model()


# ============================================================================
# Base Serializers
# ============================================================================

class TimestampedModelSerializer(serializers.ModelSerializer):
    """
    Base serializer for models with timestamp fields.
    """
    created_at = serializers.DateTimeField(read_only=True)
    updated_at = serializers.DateTimeField(read_only=True)


class MetadataModelSerializer(TimestampedModelSerializer):
    """
    Base serializer for models with metadata fields.
    """
    metadata = serializers.JSONField(required=False, allow_null=True)


# ============================================================================
# Core Model Serializers
# ============================================================================

class ChannelCodecSerializer(TimestampedModelSerializer):
    """
    Serializer for ChannelCodec model.
    """
    channel_count = SerializerMethodField()
    
    class Meta:
        model = ChannelCodec
        fields = [
            'id', 'name', 'description', 'codec_type', 'parameters',
            'is_active', 'channel_count', 'created_at', 'updated_at'
        ]
        read_only_fields = ['id', 'created_at', 'updated_at', 'channel_count']
    
    def get_channel_count(self, obj):
        """
        Get the number of channels using this codec.
        """
        return obj.channels.count()


class ChannelZoneSerializer(TimestampedModelSerializer):
    """
    Serializer for ChannelZone model.
    """
    channel_count = SerializerMethodField()
    
    class Meta:
        model = ChannelZone
        fields = [
            'id', 'name', 'description', 'country', 'region', 'timezone',
            'is_active', 'channel_count', 'created_at', 'updated_at'
        ]
        read_only_fields = ['id', 'created_at', 'updated_at', 'channel_count']
    
    def get_channel_count(self, obj):
        """
        Get the number of channels in this zone.
        """
        return obj.channels.count()


class ChannelZoneRelationSerializer(TimestampedModelSerializer):
    """
    Serializer for ChannelZoneRelation model.
    """
    zone_name = SerializerMethodField()
    channel_name = SerializerMethodField()
    vpn_status_display = SerializerMethodField()
    
    class Meta:
        model = ChannelZoneRelation
        fields = [
            'id', 'channel', 'channel_name', 'zone', 'zone_name', 'priority',
            'zone_specific_url', 'vpn_type', 'vpn_status', 'vpn_status_display',
            'last_vpn_test', 'is_active', 'created_at', 'updated_at'
        ]
        read_only_fields = [
            'id', 'vpn_status', 'last_vpn_test', 'created_at', 'updated_at',
            'zone_name', 'channel_name', 'vpn_status_display'
        ]
    
    def get_zone_name(self, obj):
        return obj.zone.name if obj.zone else None
    
    def get_channel_name(self, obj):
        return obj.channel.name if obj.channel else None
    
    def get_vpn_status_display(self, obj):
        """
        Get human-readable VPN status.
        """
        if obj.vpn_type == 'none':
            return 'No VPN'
        return obj.vpn_status or 'Unknown'


class ChannelListSerializer(TimestampedModelSerializer):
    """
    Lightweight serializer for channel list views.
    """
    codec_name = SerializerMethodField()
    zone_count = SerializerMethodField()
    health_status_display = SerializerMethodField()
    
    class Meta:
        model = Channel
        fields = [
            'id', 'name', 'channel_number', 'category', 'status',
            'health_status', 'health_status_display', 'is_hd', 'is_encrypted',
            'language', 'country', 'codec_name', 'zone_count', 'logo',
            'last_health_check', 'created_at', 'updated_at'
        ]
        read_only_fields = [
            'id', 'health_status', 'last_health_check', 'created_at', 'updated_at',
            'codec_name', 'zone_count', 'health_status_display'
        ]
    
    def get_codec_name(self, obj):
        return obj.codec.name if obj.codec else None
    
    def get_zone_count(self, obj):
        return obj.zones.count()
    
    def get_health_status_display(self, obj):
        status_map = {
            'healthy': '✓ Healthy',
            'warning': '⚠ Warning',
            'unhealthy': '✗ Unhealthy'
        }
        return status_map.get(obj.health_status, '? Unknown')


class ChannelDetailSerializer(MetadataModelSerializer):
    """
    Detailed serializer for channel detail views.
    """
    codec = ChannelCodecSerializer(read_only=True)
    codec_id = serializers.IntegerField(write_only=True, required=False)
    zones = ChannelZoneSerializer(many=True, read_only=True)
    zone_relations = ChannelZoneRelationSerializer(many=True, read_only=True, source='channelzonerelation_set')
    health_status_display = SerializerMethodField()
    stream_status = SerializerMethodField()
    statistics = SerializerMethodField()
    
    class Meta:
        model = Channel
        fields = [
            'id', 'name', 'description', 'channel_number', 'category',
            'status', 'health_status', 'health_status_display', 'last_health_check',
            'stream_url', 'backup_stream_url', 'is_hd', 'is_encrypted',
            'encryption_key', 'language', 'country', 'timezone', 'logo',
            'codec', 'codec_id', 'zones', 'zone_relations', 'stream_status',
            'statistics', 'metadata', 'created_at', 'updated_at'
        ]
        read_only_fields = [
            'id', 'health_status', 'last_health_check', 'created_at', 'updated_at',
            'health_status_display', 'stream_status', 'statistics'
        ]
        extra_kwargs = {
            'encryption_key': {'write_only': True}
        }
    
    def get_health_status_display(self, obj):
        status_map = {
            'healthy': '✓ Healthy',
            'warning': '⚠ Warning',
            'unhealthy': '✗ Unhealthy'
        }
        return status_map.get(obj.health_status, '? Unknown')
    
    def get_stream_status(self, obj):
        """
        Get current stream status (would integrate with actual monitoring).
        """
        return {
            'status': 'online',
            'bitrate': '5000 kbps',
            'resolution': '1920x1080' if obj.is_hd else '1280x720',
            'last_checked': timezone.now().isoformat()
        }
    
    def get_statistics(self, obj):
        """
        Get channel statistics.
        """
        return {
            'total_programs': obj.programs.count(),
            'total_jingles': obj.jingles.count(),
            'total_zones': obj.zones.count(),
            'uptime_percentage': 99.5,  # Would be calculated from actual data
            'avg_bitrate': '4800 kbps'
        }


# ============================================================================
# EPG and Program Serializers
# ============================================================================

class EPGProgramListSerializer(MetadataModelSerializer):
    """
    Lightweight serializer for EPG program list views.
    """
    channel_name = SerializerMethodField()
    duration_minutes = SerializerMethodField()
    
    class Meta:
        model = EPGProgram
        fields = [
            'id', 'channel', 'channel_name', 'title', 'category', 'genre',
            'start_time', 'end_time', 'duration', 'duration_minutes',
            'rating', 'language', 'has_subtitles', 'has_ad_breaks',
            'created_at', 'updated_at'
        ]
        read_only_fields = [
            'id', 'created_at', 'updated_at', 'channel_name', 'duration_minutes'
        ]
    
    def get_channel_name(self, obj):
        return obj.channel.name if obj.channel else None
    
    def get_duration_minutes(self, obj):
        if obj.duration:
            return int(obj.duration.total_seconds() / 60)
        return None


class EPGProgramDetailSerializer(MetadataModelSerializer):
    """
    Detailed serializer for EPG program detail views.
    """
    channel = ChannelListSerializer(read_only=True)
    channel_id = serializers.IntegerField(write_only=True)
    duration_minutes = SerializerMethodField()
    is_live = SerializerMethodField()
    
    class Meta:
        model = EPGProgram
        fields = [
            'id', 'channel', 'channel_id', 'title', 'description', 'category',
            'genre', 'start_time', 'end_time', 'duration', 'duration_minutes',
            'rating', 'language', 'director', 'cast', 'year', 'country',
            'episode_number', 'season_number', 'has_subtitles', 'has_ad_breaks',
            'ad_break_positions', 'is_live', 'metadata', 'created_at', 'updated_at'
        ]
        read_only_fields = [
            'id', 'created_at', 'updated_at', 'duration_minutes', 'is_live'
        ]
    
    def get_duration_minutes(self, obj):
        if obj.duration:
            return int(obj.duration.total_seconds() / 60)
        return None
    
    def get_is_live(self, obj):
        """
        Check if the program is currently live.
        """
        now = timezone.now()
        return obj.start_time <= now <= obj.end_time


# ============================================================================
# Jingle and Audio Serializers
# ============================================================================

class JingleListSerializer(MetadataModelSerializer):
    """
    Lightweight serializer for jingle list views.
    """
    channel_name = SerializerMethodField()
    duration_seconds = SerializerMethodField()
    
    class Meta:
        model = Jingle
        fields = [
            'id', 'channel', 'channel_name', 'name', 'jingle_type',
            'duration', 'duration_seconds', 'volume_level', 'play_count',
            'is_active', 'created_at', 'updated_at'
        ]
        read_only_fields = [
            'id', 'play_count', 'created_at', 'updated_at',
            'channel_name', 'duration_seconds'
        ]
    
    def get_channel_name(self, obj):
        return obj.channel.name if obj.channel else None
    
    def get_duration_seconds(self, obj):
        if obj.duration:
            return int(obj.duration.total_seconds())
        return None


class JingleDetailSerializer(MetadataModelSerializer):
    """
    Detailed serializer for jingle detail views.
    """
    channel = ChannelListSerializer(read_only=True)
    channel_id = serializers.IntegerField(write_only=True)
    duration_seconds = SerializerMethodField()
    file_size = SerializerMethodField()
    
    class Meta:
        model = Jingle
        fields = [
            'id', 'channel', 'channel_id', 'name', 'description', 'jingle_type',
            'file', 'file_size', 'duration', 'duration_seconds', 'volume_level',
            'fade_in', 'fade_out', 'fingerprint', 'fingerprint_generated_at',
            'play_count', 'last_played', 'is_active', 'metadata',
            'created_at', 'updated_at'
        ]
        read_only_fields = [
            'id', 'fingerprint', 'fingerprint_generated_at', 'play_count',
            'last_played', 'created_at', 'updated_at', 'duration_seconds', 'file_size'
        ]
    
    def get_duration_seconds(self, obj):
        if obj.duration:
            return int(obj.duration.total_seconds())
        return None
    
    def get_file_size(self, obj):
        """
        Get file size in human-readable format.
        """
        if obj.file:
            try:
                size = obj.file.size
                for unit in ['B', 'KB', 'MB', 'GB']:
                    if size < 1024.0:
                        return f"{size:.1f} {unit}"
                    size /= 1024.0
                return f"{size:.1f} TB"
            except (OSError, ValueError):
                return 'Unknown'
        return None


class JingleDetectionSerializer(TimestampedModelSerializer):
    """
    Serializer for JingleDetection model.
    """
    jingle_name = SerializerMethodField()
    channel_name = SerializerMethodField()
    confidence_percentage = SerializerMethodField()
    
    class Meta:
        model = JingleDetection
        fields = [
            'id', 'jingle', 'jingle_name', 'channel', 'channel_name',
            'detected_at', 'confidence_score', 'confidence_percentage',
            'status', 'created_at', 'updated_at'
        ]
        read_only_fields = [
            'id', 'detected_at', 'created_at', 'updated_at',
            'jingle_name', 'channel_name', 'confidence_percentage'
        ]
    
    def get_jingle_name(self, obj):
        return obj.jingle.name if obj.jingle else None
    
    def get_channel_name(self, obj):
        return obj.channel.name if obj.channel else None
    
    def get_confidence_percentage(self, obj):
        return f"{obj.confidence_score * 100:.1f}%"


# ============================================================================
# Schedule Serializers
# ============================================================================

class ChannelScheduleListSerializer(MetadataModelSerializer):
    """
    Lightweight serializer for channel schedule list views.
    """
    channel_name = SerializerMethodField()
    duration_minutes = SerializerMethodField()
    
    class Meta:
        model = ChannelSchedule
        fields = [
            'id', 'channel', 'channel_name', 'title', 'schedule_type',
            'start_time', 'end_time', 'duration_minutes', 'is_recurring',
            'priority', 'is_active', 'created_at', 'updated_at'
        ]
        read_only_fields = [
            'id', 'created_at', 'updated_at', 'channel_name', 'duration_minutes'
        ]
    
    def get_channel_name(self, obj):
        return obj.channel.name if obj.channel else None
    
    def get_duration_minutes(self, obj):
        if obj.start_time and obj.end_time:
            duration = obj.end_time - obj.start_time
            return int(duration.total_seconds() / 60)
        return None


class ChannelScheduleDetailSerializer(MetadataModelSerializer):
    """
    Detailed serializer for channel schedule detail views.
    """
    channel = ChannelListSerializer(read_only=True)
    channel_id = serializers.IntegerField(write_only=True)
    duration_minutes = SerializerMethodField()
    is_active_now = SerializerMethodField()
    
    class Meta:
        model = ChannelSchedule
        fields = [
            'id', 'channel', 'channel_id', 'title', 'description',
            'schedule_type', 'start_time', 'end_time', 'duration_minutes',
            'is_recurring', 'recurrence_pattern', 'priority', 'is_active',
            'is_active_now', 'metadata', 'created_at', 'updated_at'
        ]
        read_only_fields = [
            'id', 'created_at', 'updated_at', 'duration_minutes', 'is_active_now'
        ]
    
    def get_duration_minutes(self, obj):
        if obj.start_time and obj.end_time:
            duration = obj.end_time - obj.start_time
            return int(duration.total_seconds() / 60)
        return None
    
    def get_is_active_now(self, obj):
        """
        Check if the schedule is currently active.
        """
        if not obj.is_active:
            return False
        
        now = timezone.now()
        return obj.start_time <= now <= obj.end_time


# ============================================================================
# VPN Configuration Serializers
# ============================================================================

class VPNConfigurationBaseSerializer(TimestampedModelSerializer):
    """
    Base serializer for VPN configurations.
    """
    class Meta:
        abstract = True
        read_only_fields = ['id', 'created_at', 'updated_at']
        extra_kwargs = {
            'username': {'write_only': True},
            'password': {'write_only': True},
            'private_key': {'write_only': True},
            'certificate': {'write_only': True}
        }


class IPSecConfigurationSerializer(VPNConfigurationBaseSerializer):
    """
    Serializer for IPSec VPN configurations.
    """
    class Meta:
        model = IPSecConfiguration
        fields = [
            'id', 'name', 'server_address', 'username', 'password',
            'pre_shared_key', 'is_active', 'created_at', 'updated_at'
        ]
        read_only_fields = VPNConfigurationBaseSerializer.Meta.read_only_fields
        extra_kwargs = {
            **VPNConfigurationBaseSerializer.Meta.extra_kwargs,
            'pre_shared_key': {'write_only': True}
        }


class OpenVPNConfigurationSerializer(VPNConfigurationBaseSerializer):
    """
    Serializer for OpenVPN configurations.
    """
    class Meta:
        model = OpenVPNConfiguration
        fields = [
            'id', 'name', 'server_address', 'port', 'protocol',
            'username', 'password', 'certificate', 'private_key',
            'ca_certificate', 'is_active', 'created_at', 'updated_at'
        ]
        read_only_fields = VPNConfigurationBaseSerializer.Meta.read_only_fields
        extra_kwargs = {
            **VPNConfigurationBaseSerializer.Meta.extra_kwargs,
            'ca_certificate': {'write_only': True}
        }


class WireGuardConfigurationSerializer(VPNConfigurationBaseSerializer):
    """
    Serializer for WireGuard VPN configurations.
    """
    class Meta:
        model = WireGuardConfiguration
        fields = [
            'id', 'name', 'server_address', 'port', 'private_key',
            'public_key', 'endpoint', 'allowed_ips', 'dns_servers',
            'is_active', 'created_at', 'updated_at'
        ]
        read_only_fields = VPNConfigurationBaseSerializer.Meta.read_only_fields
        extra_kwargs = {
            **VPNConfigurationBaseSerializer.Meta.extra_kwargs,
            'public_key': {'write_only': True}
        }


# ============================================================================
# Bulk Operation Serializers
# ============================================================================

class BulkChannelActionSerializer(serializers.Serializer):
    """
    Serializer for bulk channel operations.
    """
    channel_ids = serializers.ListField(
        child=serializers.IntegerField(),
        min_length=1,
        max_length=100
    )
    action = serializers.ChoiceField(choices=[
        ('activate', 'Activate'),
        ('deactivate', 'Deactivate'),
        ('health_check', 'Health Check'),
        ('update_metadata', 'Update Metadata')
    ])
    metadata = serializers.JSONField(required=False, allow_null=True)
    
    def validate_channel_ids(self, value):
        """
        Validate that all channel IDs exist.
        """
        existing_ids = set(Channel.objects.filter(id__in=value).values_list('id', flat=True))
        invalid_ids = set(value) - existing_ids
        
        if invalid_ids:
            raise serializers.ValidationError(
                f"Invalid channel IDs: {', '.join(map(str, invalid_ids))}"
            )
        
        return value


class ChannelImportSerializer(serializers.Serializer):
    """
    Serializer for importing channels from external sources.
    """
    source_type = serializers.ChoiceField(choices=[
        ('m3u', 'M3U Playlist'),
        ('xmltv', 'XMLTV Guide'),
        ('json', 'JSON Format'),
        ('csv', 'CSV File')
    ])
    source_url = serializers.URLField(required=False, allow_blank=True)
    source_file = serializers.FileField(required=False)
    import_options = serializers.JSONField(required=False, default=dict)
    
    def validate(self, data):
        """
        Validate that either source_url or source_file is provided.
        """
        if not data.get('source_url') and not data.get('source_file'):
            raise serializers.ValidationError(
                "Either source_url or source_file must be provided."
            )
        
        return data


# ============================================================================
# Statistics and Analytics Serializers
# ============================================================================

class ChannelStatisticsSerializer(serializers.Serializer):
    """
    Serializer for channel statistics and analytics.
    """
    channel_id = serializers.IntegerField()
    channel_name = serializers.CharField()
    total_programs = serializers.IntegerField()
    total_jingles = serializers.IntegerField()
    total_zones = serializers.IntegerField()
    uptime_percentage = serializers.FloatField()
    avg_bitrate = serializers.CharField()
    health_status = serializers.CharField()
    last_health_check = serializers.DateTimeField()
    total_detections = serializers.IntegerField()
    avg_confidence = serializers.FloatField()


class SystemStatisticsSerializer(serializers.Serializer):
    """
    Serializer for system-wide statistics.
    """
    total_channels = serializers.IntegerField()
    active_channels = serializers.IntegerField()
    total_zones = serializers.IntegerField()
    total_codecs = serializers.IntegerField()
    total_programs = serializers.IntegerField()
    total_jingles = serializers.IntegerField()
    total_detections = serializers.IntegerField()
    healthy_channels = serializers.IntegerField()
    warning_channels = serializers.IntegerField()
    unhealthy_channels = serializers.IntegerField()
    avg_uptime = serializers.FloatField()
    last_updated = serializers.DateTimeField()