"""OpenAI Whisper STT (Speech-to-Text) client.

REST API-based transcription using OpenAI-compatible endpoints.

Example:
    ```python
    from sdkrouter.tools.audio.stt import OpenAISTT

    stt = OpenAISTT(config)
    result = stt.transcribe("audio.mp3", model="whisper-1")
    print(result.text)
    ```
"""

from __future__ import annotations

import logging
from collections.abc import AsyncIterator
from contextlib import asynccontextmanager
from pathlib import Path
from typing import TYPE_CHECKING

from ...._api.client import BaseResource, AsyncBaseResource
from ...._types.audio import (
    TranscriptionResponse,
    TranscriptionResponseFormat,
    VerboseTranscriptionResponse,
)
from ....exceptions import handle_api_errors, async_api_error_handler
from .._utils import guess_mime_type, resolve_file
from .deepgram import DeepgramClient, DeepgramConfig, DeepgramSession

if TYPE_CHECKING:
    from ...._config import SDKConfig

logger = logging.getLogger(__name__)


class OpenAISTT(BaseResource):
    """OpenAI Whisper STT client (sync).

    Uses OpenAI-compatible transcription endpoint.

    Example:
        ```python
        stt = OpenAISTT(config)

        # Transcribe from file path
        result = stt.transcribe("audio.mp3")
        print(result.text)

        # Transcribe from bytes
        result = stt.transcribe(audio_bytes, filename="recording.wav")
        print(result.text)

        # Get verbose response with segments
        result = stt.transcribe(
            "audio.mp3",
            response_format="verbose_json",
        )
        for segment in result.segments:
            print(f"[{segment.start:.1f}s] {segment.text}")
        ```
    """

    def __init__(self, config: "SDKConfig"):
        super().__init__(config, use_audio_url=True)

    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.

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

        Returns:
            TranscriptionResponse, VerboseTranscriptionResponse, or str.
        """
        file_bytes, resolved_filename = resolve_file(file, filename)

        files = {
            "file": (resolved_filename, file_bytes, guess_mime_type(resolved_filename)),
        }
        data: dict = {
            "model": model,
            "response_format": response_format,
            "temperature": str(temperature),
        }
        if language:
            data["language"] = language

        logger.debug(
            "STT transcribe: model=%s, format=%s, file=%s (%d bytes)",
            model, response_format, resolved_filename, len(file_bytes),
        )

        with handle_api_errors():
            response = self._http_client.post(
                "/v1/audio/transcriptions",
                data=data,
                files=files,
            )
            response.raise_for_status()

        if response_format in ("text", "srt", "vtt"):
            return response.text
        elif response_format == "verbose_json":
            return VerboseTranscriptionResponse.model_validate(response.json())
        else:
            return TranscriptionResponse.model_validate(response.json())


class AsyncOpenAISTT(AsyncBaseResource):
    """OpenAI Whisper STT client (async).

    Async version of OpenAISTT with Deepgram streaming support.

    Example:
        ```python
        stt = AsyncOpenAISTT(config)

        # OpenAI Whisper transcription
        result = await stt.transcribe("audio.mp3")
        print(result.text)

        # Deepgram streaming
        async with stt.stream_deepgram() as session:
            await session.send(audio_chunk)
            async for segment in session.transcripts():
                print(segment.text)
        ```
    """

    def __init__(self, config: "SDKConfig"):
        super().__init__(config, use_audio_url=True)
        self._deepgram: DeepgramClient | None = None

    @property
    def deepgram(self) -> DeepgramClient:
        """Get Deepgram streaming client."""
        if self._deepgram is None:
            self._deepgram = DeepgramClient(self._config)
        return self._deepgram

    @asynccontextmanager
    async def stream_deepgram(
        self,
        config: DeepgramConfig | None = None,
    ) -> AsyncIterator[DeepgramSession]:
        """Open Deepgram streaming session via SDKRouter server.

        Streams audio in real-time for transcription using Deepgram.
        Authentication is handled by the server - you only need SDKROUTER_API_KEY.

        Args:
            config: Deepgram configuration (model, language, sample_rate, etc.)

        Yields:
            DeepgramSession for sending audio and receiving transcripts.

        Example:
            ```python
            async with stt.stream_deepgram() as session:
                # Send audio chunks
                await session.send(audio_bytes)

                # Receive transcripts
                async for segment in session.transcripts():
                    if segment.is_final:
                        print(f">>> {segment.text}")
                    else:
                        print(f"... {segment.text}")
            ```
        """
        async with self.deepgram.stream(config) as session:
            yield session

    @async_api_error_handler
    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.
        """
        file_bytes, resolved_filename = resolve_file(file, filename)

        files = {
            "file": (resolved_filename, file_bytes, guess_mime_type(resolved_filename)),
        }
        data: dict = {
            "model": model,
            "response_format": response_format,
            "temperature": str(temperature),
        }
        if language:
            data["language"] = language

        logger.debug(
            "STT transcribe async: model=%s, format=%s, file=%s (%d bytes)",
            model, response_format, resolved_filename, len(file_bytes),
        )

        response = await self._http_client.post(
            "/v1/audio/transcriptions",
            data=data,
            files=files,
        )
        response.raise_for_status()

        if response_format in ("text", "srt", "vtt"):
            return response.text
        elif response_format == "verbose_json":
            return VerboseTranscriptionResponse.model_validate(response.json())
        else:
            return TranscriptionResponse.model_validate(response.json())


__all__ = [
    "OpenAISTT",
    "AsyncOpenAISTT",
]
