"""
REST API Serializers for Streams Application

This module contains Django REST Framework serializers for converting
complex datatypes such as model instances to native Python datatypes
that can then be easily rendered into JSON, XML or other content types.
"""

from rest_framework import serializers
from django.contrib.auth.models import User
from apps.streams.models import Channel, StreamSession, HLSSegment, VideoConfiguration, AudioConfiguration


class UserSerializer(serializers.ModelSerializer):
    """
    Serializer for User model with basic information.
    
    Provides a simple representation of user data for API responses.
    """
    
    class Meta:
        model = User
        fields = ['id', 'username', 'email', 'first_name', 'last_name']
        read_only_fields = ['id']


class VideoConfigurationSerializer(serializers.ModelSerializer):
    """
    Serializer for VideoConfiguration model.
    
    Handles serialization of video encoding configuration parameters
    for API consumption and creation.
    """
    
    class Meta:
        model = VideoConfiguration
        fields = [
            'id', 'name', 'resolution', 'aspect_ratio', 'frame_rate',
            'min_bitrate', 'max_bitrate', 'codec', 'preset', 'profile',
            'level', 'created_at', 'updated_at'
        ]
        read_only_fields = ['id', 'created_at', 'updated_at']

    def validate_resolution(self, value):
        """
        Validate resolution format (WIDTHxHEIGHT).
        
        Args:
            value (str): Resolution string to validate
            
        Returns:
            str: Validated resolution
            
        Raises:
            ValidationError: If resolution format is invalid
        """
        if value:
            parts = value.split('x')
            if len(parts) != 2:
                raise serializers.ValidationError(
                    'Resolution must be in format WIDTHxHEIGHT (e.g., 1920x1080)'
                )
            
            try:
                width, height = int(parts[0]), int(parts[1])
                if width <= 0 or height <= 0:
                    raise ValueError
            except ValueError:
                raise serializers.ValidationError(
                    'Resolution dimensions must be positive integers'
                )
        
        return value


class AudioConfigurationSerializer(serializers.ModelSerializer):
    """
    Serializer for AudioConfiguration model.
    
    Handles serialization of audio encoding configuration parameters
    for API consumption and creation.
    """
    
    class Meta:
        model = AudioConfiguration
        fields = [
            'id', 'name', 'codec', 'bitrate', 'sample_rate',
            'channels', 'normalize', 'created_at', 'updated_at'
        ]
        read_only_fields = ['id', 'created_at', 'updated_at']

    def validate_bitrate(self):
        """
        Validate audio bitrate format.
        
        Returns:
            str: Validated bitrate
            
        Raises:
            ValidationError: If bitrate format is invalid
        """
        bitrate = self.validated_data.get('bitrate')
        
        if bitrate:
            if not bitrate.lower().endswith('k'):
                raise serializers.ValidationError(
                    'Bitrate must end with "k" (e.g., 128k)'
                )
            
            try:
                rate = int(bitrate[:-1])
                if rate <= 0:
                    raise ValueError
            except ValueError:
                raise serializers.ValidationError(
                    'Bitrate must be a positive number followed by "k"'
                )
        
        return bitrate


class ChannelSerializer(serializers.ModelSerializer):
    """
    Serializer for Channel model.
    
    Provides complete channel information including related configurations
    and active session status for comprehensive API responses.
    """
    
    # Read-only fields for related data
    created_by = UserSerializer(read_only=True)
    active_session = serializers.SerializerMethodField()
    total_sessions = serializers.SerializerMethodField()
    
    class Meta:
        model = Channel
        fields = [
            'id', 'name', 'slug', 'hls_url', 'description', 'is_active',
            'output_directory', 'segment_duration', 'max_segments',
            'retry_attempts', 'retry_interval', 'created_by', 'active_session',
            'total_sessions', 'created_at', 'updated_at'
        ]
        read_only_fields = ['id', 'created_by', 'created_at', 'updated_at']

    def get_active_session(self, obj):
        """
        Get active session information for the channel.
        
        Args:
            obj (Channel): Channel instance
            
        Returns:
            dict: Active session data or None
        """
        active_session = obj.get_active_session()
        if active_session:
            return {
                'id': str(active_session.id),
                'status': active_session.status,
                'started_at': active_session.started_at,
                'segments_processed': active_session.segments_processed,
                'errors_count': active_session.errors_count
            }
        return None

    def get_total_sessions(self, obj):
        """
        Get total number of sessions for the channel.
        
        Args:
            obj (Channel): Channel instance
            
        Returns:
            int: Total session count
        """
        return obj.sessions.count()

    def validate_hls_url(self, value):
        """
        Validate HLS URL format.
        
        Args:
            value (str): HLS URL to validate
            
        Returns:
            str: Validated URL
            
        Raises:
            ValidationError: If URL format is invalid
        """
        if value and not value.lower().endswith('.m3u8'):
            raise serializers.ValidationError(
                'HLS URL should end with .m3u8'
            )
        return value


class HLSSegmentSerializer(serializers.ModelSerializer):
    """
    Serializer for HLSSegment model.
    
    Provides segment information with file status and metadata
    for monitoring and debugging purposes.
    """
    
    # Additional computed fields
    file_exists = serializers.SerializerMethodField()
    file_size_human = serializers.SerializerMethodField()
    
    class Meta:
        model = HLSSegment
        fields = [
            'id', 'filename', 'sequence_number', 'duration', 'file_size',
            'file_size_human', 'is_available', 'file_exists', 'processed_at',
            'created_at', 'updated_at'
        ]
        read_only_fields = [
            'id', 'filename', 'file_size', 'processed_at', 'created_at', 'updated_at'
        ]

    def get_file_exists(self, obj):
        """
        Check if the segment file exists on disk.
        
        Args:
            obj (HLSSegment): Segment instance
            
        Returns:
            bool: True if file exists, False otherwise
        """
        return obj.file_exists()

    def get_file_size_human(self, obj):
        """
        Get human-readable file size.
        
        Args:
            obj (HLSSegment): Segment instance
            
        Returns:
            str: Human-readable file size
        """
        if obj.file_size:
            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"
        return "Unknown"


class StreamSessionSerializer(serializers.ModelSerializer):
    """
    Serializer for StreamSession model.
    
    Provides comprehensive session information including channel details,
    configurations, statistics, and recent segments.
    """
    
    # Related data
    channel = ChannelSerializer(read_only=True)
    video_config = VideoConfigurationSerializer(read_only=True)
    audio_config = AudioConfigurationSerializer(read_only=True)
    
    # Computed fields
    duration = serializers.SerializerMethodField()
    is_running = serializers.SerializerMethodField()
    recent_segments = serializers.SerializerMethodField()
    
    class Meta:
        model = StreamSession
        fields = [
            'id', 'channel', 'video_config', 'audio_config', 'status',
            'started_at', 'ended_at', 'duration', 'is_running',
            'segments_processed', 'errors_count', 'last_error',
            'process_id', 'statistics', 'recent_segments',
            'created_at', 'updated_at'
        ]
        read_only_fields = [
            'id', 'segments_processed', 'errors_count', 'last_error',
            'process_id', 'created_at', 'updated_at'
        ]

    def get_duration(self, obj):
        """
        Get session duration in seconds.
        
        Args:
            obj (StreamSession): Session instance
            
        Returns:
            int: Duration in seconds or None
        """
        duration = obj.duration()
        return int(duration.total_seconds()) if duration else None

    def get_is_running(self, obj):
        """
        Check if session is currently running.
        
        Args:
            obj (StreamSession): Session instance
            
        Returns:
            bool: True if running, False otherwise
        """
        return obj.is_running()

    def get_recent_segments(self, obj):
        """
        Get recent segments for the session.
        
        Args:
            obj (StreamSession): Session instance
            
        Returns:
            list: Recent segment data
        """
        recent_segments = obj.segments.order_by('-processed_at')[:5]
        return HLSSegmentSerializer(recent_segments, many=True).data


class StreamStartSerializer(serializers.Serializer):
    """
    Serializer for stream start operation parameters.
    
    Handles validation and serialization of parameters needed
    to start a new stream session.
    """
    
    video_config_id = serializers.UUIDField(required=False, allow_null=True)
    audio_config_id = serializers.UUIDField(required=False, allow_null=True)
    
    def validate_video_config_id(self, value):
        """
        Validate video configuration exists.
        
        Args:
            value (UUID): Video configuration ID
            
        Returns:
            UUID: Validated ID
            
        Raises:
            ValidationError: If configuration doesn't exist
        """
        if value:
            if not VideoConfiguration.objects.filter(id=value).exists():
                raise serializers.ValidationError(
                    'Video configuration not found'
                )
        return value

    def validate_audio_config_id(self, value):
        """
        Validate audio configuration exists.
        
        Args:
            value (UUID): Audio configuration ID
            
        Returns:
            UUID: Validated ID
            
        Raises:
            ValidationError: If configuration doesn't exist
        """
        if value:
            if not AudioConfiguration.objects.filter(id=value).exists():
                raise serializers.ValidationError(
                    'Audio configuration not found'
                )
        return value


class ChannelStatsSerializer(serializers.Serializer):
    """
    Serializer for channel statistics data.
    
    Provides aggregated statistics for channel performance
    and usage metrics.
    """
    
    total_sessions = serializers.IntegerField()
    active_sessions = serializers.IntegerField()
    total_segments = serializers.IntegerField()
    total_duration = serializers.IntegerField()  # in seconds
    success_rate = serializers.FloatField()
    avg_session_duration = serializers.IntegerField()  # in seconds
    last_session_at = serializers.DateTimeField(allow_null=True)
