"""
Base connector interface for voice agent connections.

All connectors must implement this interface to provide
a consistent API across different platforms (Twilio, WebSocket, VAPI, etc.)
"""

from abc import ABC, abstractmethod
from dataclasses import dataclass
from typing import Optional


@dataclass
class AudioChunk:
    """A chunk of audio data with metadata."""

    data: bytes
    sample_rate: int = 24000
    sample_width: int = 2  # 16-bit
    channels: int = 1


@dataclass
class ReceivedAudio:
    """Audio received from the agent with optional transcript."""

    audio: bytes
    transcript: str = ""
    tool_calls: list = None

    def __post_init__(self):
        if self.tool_calls is None:
            self.tool_calls = []


class BaseConnector(ABC):
    """
    Abstract base class for voice agent connectors.

    A connector handles:
    - Establishing connection to the agent
    - Sending audio (from TTS)
    - Receiving audio (for STT)
    - Managing call lifecycle
    """

    @abstractmethod
    async def connect(self) -> None:
        """
        Establish connection to the voice agent.

        Raises:
            ConnectionError: If connection fails
            TimeoutError: If connection times out
        """
        pass

    @abstractmethod
    async def send_audio(self, audio: bytes) -> None:
        """
        Send audio to the agent.

        Args:
            audio: PCM16 audio bytes at 24kHz

        Raises:
            ConnectionError: If not connected
        """
        pass

    @abstractmethod
    async def receive_audio(
        self,
        timeout: float = 15.0,
        silence_threshold: float = 1.5,
        max_duration: float = 8.0,
    ) -> ReceivedAudio:
        """
        Receive audio from the agent until silence is detected.

        Args:
            timeout: Maximum time to wait for first audio
            silence_threshold: Seconds of silence before stopping
            max_duration: Maximum recording duration

        Returns:
            ReceivedAudio with audio bytes and optional transcript

        Raises:
            TimeoutError: If no audio received within timeout
        """
        pass

    @abstractmethod
    async def send_dtmf(self, digits: str) -> None:
        """
        Send DTMF tones (for IVR navigation).

        Args:
            digits: String of digits (0-9, *, #, w for pause)
        """
        pass

    @abstractmethod
    async def close(self) -> None:
        """Close the connection and clean up resources."""
        pass

    @property
    @abstractmethod
    def is_connected(self) -> bool:
        """Check if currently connected."""
        pass

    @property
    def tool_calls(self) -> list:
        """Tool calls detected during the session (if available)."""
        return []

    @property
    def transcripts(self) -> list:
        """All transcripts from this session."""
        return []
