"""Audio tools for SDKRouter - STT and TTS.

Modular audio capabilities:
- STT (Speech-to-Text): OpenAI Whisper, Deepgram streaming
- TTS (Text-to-Speech): OpenAI TTS with streaming

Example:
    ```python
    from sdkrouter import SDKRouter

    client = SDKRouter(api_key="...")

    # Transcribe audio (OpenAI Whisper)
    result = client.audio.transcribe("audio.mp3")
    print(result.text)

    # Generate speech (OpenAI TTS)
    response = client.audio.speech("Hello!", voice="nova")
    Path("output.mp3").write_bytes(response.audio_bytes)

    # Deepgram streaming
    from sdkrouter.tools.audio.stt import DeepgramClient
    dg = DeepgramClient(api_key="...")
    async with dg.stream() as session:
        await session.send(audio_chunk)
        async for segment in session.transcripts():
            print(segment.text)
    ```
"""

from __future__ import annotations

import logging
from collections.abc import AsyncIterator, Iterator
from pathlib import Path
from typing import TYPE_CHECKING

from ..._api.client import BaseResource, AsyncBaseResource
from ..._types.audio import (
    SpeechResponse,
    SpeechStreamChunk,
    SpeechStreamDone,
    TranscriptionResponse,
    TranscriptionResponseFormat,
    TTSResponseFormat,
    VerboseTranscriptionResponse,
)
from ...exceptions import handle_api_errors, async_api_error_handler

# STT providers
from .stt import (
    OpenAISTT,
    AsyncOpenAISTT,
    DeepgramClient,
    DeepgramSession,
    DeepgramConfig,
    TranscriptSegment,
    TranscriptWord,
    DeepgramConnectionError,
    DeepgramStreamError,
    create_deepgram_client,
)

# TTS providers
from .tts import (
    OpenAITTS,
    AsyncOpenAITTS,
)

# Utilities
from ._utils import AUDIO_MIME_TYPES, guess_mime_type, resolve_file

if TYPE_CHECKING:
    from ..._config import SDKConfig

logger = logging.getLogger(__name__)


class AudioResource(BaseResource):
    """Audio tool (sync) - STT transcription and TTS speech.

    Uses the audio backend (audio_url) for OpenAI-compatible audio endpoints.
    For Deepgram streaming, use DeepgramClient directly.

    Example:
        ```python
        from sdkrouter import SDKRouter, AudioModel

        client = SDKRouter(api_key="your-api-key")

        # Transcribe audio file
        result = client.audio.transcribe("audio.mp3")
        print(result.text)

        # Generate speech with analysis
        response = client.audio.speech(input="Hello!", voice="nova")
        Path("output.mp3").write_bytes(response.audio_bytes)
        ```
    """

    def __init__(self, config: "SDKConfig"):
        super().__init__(config, use_audio_url=True)
        self._stt = OpenAISTT(config)
        self._tts = OpenAITTS(config)

    @property
    def stt(self) -> OpenAISTT:
        """Access STT (Speech-to-Text) client."""
        return self._stt

    @property
    def tts(self) -> OpenAITTS:
        """Access TTS (Text-to-Speech) client."""
        return self._tts

    def transcribe(
        self,
        file: bytes | str | Path,
        *,
        model: str = "whisper-1",
        language: str | None = None,
        response_format: TranscriptionResponseFormat = "json",
        temperature: float = 0,
        filename: str | None = None,
    ) -> TranscriptionResponse | VerboseTranscriptionResponse | str:
        """Transcribe audio to text (STT).

        Args:
            file: Audio data as bytes, file path string, or Path object.
            model: STT model or tier alias ("@cheap", "@quality").
            language: ISO 639-1 language code (e.g. "en", "ja"). Optional.
            response_format: Output format (json, verbose_json, text, srt, vtt).
            temperature: Sampling temperature (0 to 1). Default: 0
            filename: Filename hint for the uploaded audio.

        Returns:
            TranscriptionResponse, VerboseTranscriptionResponse, or str.
        """
        return self._stt.transcribe(
            file,
            model=model,
            language=language,
            response_format=response_format,
            temperature=temperature,
            filename=filename,
        )

    def speech(
        self,
        input: str,
        *,
        model: str = "tts-1",
        voice: str = "nova",
        response_format: TTSResponseFormat = "mp3",
        speed: float = 1.0,
        instructions: str | None = None,
    ) -> SpeechResponse:
        """Generate speech from text (TTS).

        Returns a SpeechResponse containing base64 audio and per-frame
        analysis metadata for visualization.

        Args:
            input: Text to synthesize (max 4096 characters).
            model: TTS model or tier alias ("@cheap", "@quality").
            voice: Voice: alloy, ash, coral, echo, fable, nova, onyx, sage, shimmer.
            response_format: Audio format: mp3, opus, aac, flac, wav, pcm.
            speed: Playback speed (0.25 to 4.0). Default: 1.0
            instructions: Custom voice instructions (for gpt-4o-mini-tts).

        Returns:
            SpeechResponse with .audio_bytes property and .analysis data.
        """
        return self._tts.speech(
            input,
            model=model,
            voice=voice,
            response_format=response_format,
            speed=speed,
            instructions=instructions,
        )

    def speech_stream(
        self,
        input: str,
        *,
        model: str = "tts-1",
        voice: str = "nova",
        response_format: TTSResponseFormat = "mp3",
        speed: float = 1.0,
        instructions: str | None = None,
    ) -> Iterator[SpeechStreamChunk | SpeechStreamDone]:
        """Generate speech with SSE streaming (sync).

        Streams audio chunks with real-time analysis frames.

        Args:
            input: Text to synthesize (max 4096 characters).
            model: TTS model or tier alias.
            voice: Voice identifier. Default: "nova"
            response_format: Audio format: "mp3" (default) or "pcm".
            speed: Playback speed (0.25 to 4.0). Default: 1.0
            instructions: Custom voice instructions.

        Yields:
            SpeechStreamChunk for each audio chunk, then SpeechStreamDone.
        """
        return self._tts.speech_stream(
            input,
            model=model,
            voice=voice,
            response_format=response_format,
            speed=speed,
            instructions=instructions,
        )


class AsyncAudioResource(AsyncBaseResource):
    """Audio tool (async) - STT transcription and TTS speech.

    Async version of AudioResource.

    Example:
        ```python
        from sdkrouter import AsyncSDKRouter

        client = AsyncSDKRouter(api_key="your-api-key")
        result = await client.audio.transcribe("audio.mp3")
        print(result.text)
        ```
    """

    def __init__(self, config: "SDKConfig"):
        super().__init__(config, use_audio_url=True)
        self._stt = AsyncOpenAISTT(config)
        self._tts = AsyncOpenAITTS(config)

    @property
    def stt(self) -> AsyncOpenAISTT:
        """Access STT (Speech-to-Text) client."""
        return self._stt

    @property
    def tts(self) -> AsyncOpenAITTS:
        """Access TTS (Text-to-Speech) client."""
        return self._tts

    async def transcribe(
        self,
        file: bytes | str | Path,
        *,
        model: str = "whisper-1",
        language: str | None = None,
        response_format: TranscriptionResponseFormat = "json",
        temperature: float = 0,
        filename: str | None = None,
    ) -> TranscriptionResponse | VerboseTranscriptionResponse | str:
        """Transcribe audio to text (async).

        Args:
            file: Audio data as bytes, file path string, or Path object.
            model: STT model or tier alias.
            language: ISO 639-1 language code. Optional.
            response_format: Output format (json, verbose_json, text, srt, vtt).
            temperature: Sampling temperature (0 to 1).
            filename: Filename hint for uploaded audio.

        Returns:
            TranscriptionResponse, VerboseTranscriptionResponse, or str.
        """
        return await self._stt.transcribe(
            file,
            model=model,
            language=language,
            response_format=response_format,
            temperature=temperature,
            filename=filename,
        )

    async def speech(
        self,
        input: str,
        *,
        model: str = "tts-1",
        voice: str = "nova",
        response_format: TTSResponseFormat = "mp3",
        speed: float = 1.0,
        instructions: str | None = None,
    ) -> SpeechResponse:
        """Generate speech from text (async).

        Returns a SpeechResponse containing base64 audio and per-frame
        analysis metadata for visualization.

        Args:
            input: Text to synthesize (max 4096 characters).
            model: TTS model or tier alias.
            voice: Voice identifier. Default: "nova"
            response_format: Audio format. Default: "mp3"
            speed: Playback speed (0.25 to 4.0).
            instructions: Custom voice instructions.

        Returns:
            SpeechResponse with .audio_bytes property and .analysis data.
        """
        return await self._tts.speech(
            input,
            model=model,
            voice=voice,
            response_format=response_format,
            speed=speed,
            instructions=instructions,
        )

    async def speech_stream(
        self,
        input: str,
        *,
        model: str = "tts-1",
        voice: str = "nova",
        response_format: TTSResponseFormat = "mp3",
        speed: float = 1.0,
        instructions: str | None = None,
    ) -> AsyncIterator[SpeechStreamChunk | SpeechStreamDone]:
        """Generate speech with SSE streaming (async).

        Streams audio chunks with real-time analysis frames.

        Args:
            input: Text to synthesize (max 4096 characters).
            model: TTS model or tier alias.
            voice: Voice identifier. Default: "nova"
            response_format: Audio format: "mp3" (default) or "pcm".
            speed: Playback speed (0.25 to 4.0). Default: 1.0
            instructions: Custom voice instructions.

        Yields:
            SpeechStreamChunk for each audio chunk, then SpeechStreamDone.
        """
        async for item in self._tts.speech_stream(
            input,
            model=model,
            voice=voice,
            response_format=response_format,
            speed=speed,
            instructions=instructions,
        ):
            yield item


__all__ = [
    # Main resources (backwards compatible)
    "AudioResource",
    "AsyncAudioResource",
    # STT providers
    "OpenAISTT",
    "AsyncOpenAISTT",
    "DeepgramClient",
    "DeepgramSession",
    "DeepgramConnectionError",
    "DeepgramStreamError",
    "create_deepgram_client",
    # TTS providers
    "OpenAITTS",
    "AsyncOpenAITTS",
    # Utilities
    "AUDIO_MIME_TYPES",
    "guess_mime_type",
    "resolve_file",
]
