import uuid
from typing import Optional
from config import Config


class McubeService:
    """
    Provides all Mcube call service integration logic for the application.
    
    - Handles Mcube WebSocket protocol for incoming calls
    - Creates Mcube-compatible messages (playAudio, checkpoint, clearAudio, transfer, terminate)
    - Extracts and interprets Mcube event payloads
    
    This class is the main entry point for all Mcube-related operations.
    """
    
    @staticmethod
    def create_play_audio_message(audio_payload: str, name: str = None) -> dict:
        """
        Create a Mcube playAudio message with audio payload.
        
        Args:
            audio_payload: Base64 encoded audio data
            name: Unique name for the audio segment (generated if not provided)
            
        Returns:
            Dictionary containing Mcube playAudio message
        """
        if name is None:
            name = f"audio_{uuid.uuid4().hex[:8]}"
            
        return {
            "event": "playAudio",
            "media": {
                "contentType": Config.MCUBE_AUDIO_FORMAT,
                "sampleRate": Config.MCUBE_SAMPLE_RATE,
                "payload": audio_payload,
                "name": name
            }
        }
    
    @staticmethod
    def create_checkpoint_message(stream_id: str, name: str) -> dict:
        """
        Create a Mcube checkpoint message for audio synchronization.
        
        Args:
            stream_id: Mcube stream identifier
            name: Name of the audio segment to checkpoint
            
        Returns:
            Dictionary containing Mcube checkpoint message
        """
        return {
            "event": "checkpoint",
            "streamId": stream_id,
            "name": name
        }
    
    @staticmethod
    def create_clear_audio_message(stream_id: str) -> dict:
        """
        Create a Mcube clearAudio message to clear audio buffer.
        
        Args:
            stream_id: Mcube stream identifier
            
        Returns:
            Dictionary containing Mcube clearAudio message
        """
        return {
            "event": "clearAudio",
            "streamId": stream_id
        }
    
    @staticmethod
    def create_transfer_message(stream_id: str, transfer_to: str, show_original_caller_id: bool = True) -> dict:
        """
        Create a Mcube transfer message to transfer the call.
        
        Args:
            stream_id: Mcube stream identifier
            transfer_to: Phone number to transfer call to in E.164 format
            show_original_caller_id: Whether to show caller's phone number as callerId
            
        Returns:
            Dictionary containing Mcube transfer message
        """
        return {
            "event": "transfer",
            "streamId": stream_id,
            "transferTo": transfer_to,
            "showOriginalCallerId": show_original_caller_id
        }
    
    @staticmethod
    def create_terminate_message(stream_id: str) -> dict:
        """
        Create a Mcube terminate message to end the call.
        
        Args:
            stream_id: Mcube stream identifier
            
        Returns:
            Dictionary containing Mcube terminate message
        """
        return {
            "event": "terminate",
            "streamId": stream_id
        }
    
    
    @staticmethod
    def extract_call_id(start_event_data: dict) -> Optional[str]:
        """
        Extract call ID from Mcube start event data.
        
        Args:
            start_event_data: Mcube start event data
            
        Returns:
            Call ID if found, None otherwise
        """
        try:
            return start_event_data['start']['callId']
        except (KeyError, TypeError):
            return None
    
    @staticmethod
    def extract_stream_id(start_event_data: dict) -> Optional[str]:
        """
        Extract stream ID from Mcube start event data.
        
        Args:
            start_event_data: Mcube start event data
            
        Returns:
            Stream ID if found, None otherwise
        """
        try:
            return start_event_data['start']['streamId']
        except (KeyError, TypeError):
            return None
    
    @staticmethod
    def extract_media_payload(media_event_data: dict) -> Optional[str]:
        """
        Extract audio payload from Mcube media event data.
        
        Args:
            media_event_data: Mcube media event data
            
        Returns:
            Audio payload if found, None otherwise
        """
        try:
            return media_event_data['media']['payload']
        except (KeyError, TypeError):
            return None
    
    @staticmethod
    def extract_media_timestamp(media_event_data: dict) -> Optional[str]:
        """
        Extract timestamp from Mcube media event data.
        
        Args:
            media_event_data: Mcube media event data
            
        Returns:
            Timestamp if found, None otherwise
        """
        try:
            return media_event_data['media']['timestamp']
        except (KeyError, TypeError):
            return None
    
    @staticmethod
    def extract_media_track(media_event_data: dict) -> Optional[str]:
        """
        Extract track from Mcube media event data.
        
        Args:
            media_event_data: Mcube media event data
            
        Returns:
            Track if found, None otherwise
        """
        try:
            return media_event_data['media']['track']
        except (KeyError, TypeError):
            return None
    
    @staticmethod
    def is_media_event(event_data: dict) -> bool:
        """Check if event data represents a Mcube media event."""
        return event_data.get('event') == 'media'
    
    @staticmethod
    def is_start_event(event_data: dict) -> bool:
        """Check if event data represents a Mcube start event."""
        return event_data.get('event') == 'start'
    
    @staticmethod
    def is_played_stream_event(event_data: dict) -> bool:
        """Check if event data represents a Mcube playedStream event."""
        return event_data.get('event') == 'playedStream'
    
    @staticmethod
    def extract_played_stream_name(played_stream_event_data: dict) -> Optional[str]:
        """
        Extract name from Mcube playedStream event data.
        
        Args:
            played_stream_event_data: Mcube playedStream event data
            
        Returns:
            Name if found, None otherwise
        """
        try:
            return played_stream_event_data['name']
        except (KeyError, TypeError):
            return None
