from __future__ import annotations

from pathlib import Path
from typing import Any, BinaryIO

import httpx

from .._types import TranscriptionResponse


class Transcriptions:
    """Sync audio transcriptions: client.audio.transcriptions.create(...)"""

    def __init__(self, client: object) -> None:
        self._client = client

    def create(
        self,
        *,
        file: str | Path | bytes | BinaryIO,
        model: str = "whisper-v3-arabic",
        language: str = "ar",
        **kwargs: Any,
    ) -> TranscriptionResponse:
        if isinstance(file, (str, Path)):
            file_obj = open(file, "rb")
            close_after = True
        elif isinstance(file, bytes):
            import io

            file_obj = io.BytesIO(file)
            close_after = True
        else:
            file_obj = file
            close_after = False

        try:
            files = {"file": ("audio.wav", file_obj, "application/octet-stream")}
            params = {"model": model, "language": language, **kwargs}

            # Use multipart upload — override Content-Type
            headers = {
                k: v for k, v in self._client._headers.items()  # type: ignore[attr-defined]
                if k.lower() != "content-type"
            }
            resp = self._client._http.post(  # type: ignore[attr-defined]
                self._client._build_url("/v1/audio/transcriptions"),  # type: ignore[attr-defined]
                files=files,
                params=params,
                headers=headers,
                timeout=120.0,
            )
        finally:
            if close_after:
                file_obj.close()

        self._client._raise_for_status(resp)  # type: ignore[attr-defined]
        return TranscriptionResponse(**resp.json())


class Speech:
    """Sync text-to-speech: client.audio.speech.create(...)"""

    def __init__(self, client: object) -> None:
        self._client = client

    def create(
        self,
        *,
        input: str,
        voice: str = "default",
        model: str = "chatterbox-arabic",
        response_format: str = "mp3",
        speed: float = 1.0,
        **kwargs: Any,
    ) -> httpx.Response:
        payload: dict[str, Any] = {
            "input": input,
            "voice": voice,
            "model": model,
            "response_format": response_format,
            "speed": speed,
            **kwargs,
        }
        resp = self._client._http.post(  # type: ignore[attr-defined]
            self._client._build_url("/v1/audio/speech"),  # type: ignore[attr-defined]
            json=payload,
            headers=self._client._headers,  # type: ignore[attr-defined]
            timeout=120.0,
        )
        self._client._raise_for_status(resp)  # type: ignore[attr-defined]
        return resp


class AsyncTranscriptions:
    """Async audio transcriptions: client.audio.transcriptions.create(...)"""

    def __init__(self, client: object) -> None:
        self._client = client

    async def create(
        self,
        *,
        file: str | Path | bytes | BinaryIO,
        model: str = "whisper-v3-arabic",
        language: str = "ar",
        **kwargs: Any,
    ) -> TranscriptionResponse:
        if isinstance(file, (str, Path)):
            file_obj = open(file, "rb")
            close_after = True
        elif isinstance(file, bytes):
            import io

            file_obj = io.BytesIO(file)
            close_after = True
        else:
            file_obj = file
            close_after = False

        try:
            files = {"file": ("audio.wav", file_obj, "application/octet-stream")}
            params = {"model": model, "language": language, **kwargs}

            headers = {
                k: v for k, v in self._client._headers.items()  # type: ignore[attr-defined]
                if k.lower() != "content-type"
            }
            resp = await self._client._http.post(  # type: ignore[attr-defined]
                self._client._build_url("/v1/audio/transcriptions"),  # type: ignore[attr-defined]
                files=files,
                params=params,
                headers=headers,
                timeout=120.0,
            )
        finally:
            if close_after:
                file_obj.close()

        self._client._raise_for_status(resp)  # type: ignore[attr-defined]
        return TranscriptionResponse(**resp.json())


class AsyncSpeech:
    """Async text-to-speech: client.audio.speech.create(...)"""

    def __init__(self, client: object) -> None:
        self._client = client

    async def create(
        self,
        *,
        input: str,
        voice: str = "default",
        model: str = "chatterbox-arabic",
        response_format: str = "mp3",
        speed: float = 1.0,
        **kwargs: Any,
    ) -> httpx.Response:
        payload: dict[str, Any] = {
            "input": input,
            "voice": voice,
            "model": model,
            "response_format": response_format,
            "speed": speed,
            **kwargs,
        }
        resp = await self._client._http.post(  # type: ignore[attr-defined]
            self._client._build_url("/v1/audio/speech"),  # type: ignore[attr-defined]
            json=payload,
            headers=self._client._headers,  # type: ignore[attr-defined]
            timeout=120.0,
        )
        self._client._raise_for_status(resp)  # type: ignore[attr-defined]
        return resp


class Audio:
    """Sync audio resource: client.audio.transcriptions / client.audio.speech"""

    def __init__(self, client: object) -> None:
        self.transcriptions = Transcriptions(client)
        self.speech = Speech(client)


class AsyncAudio:
    """Async audio resource: client.audio.transcriptions / client.audio.speech"""

    def __init__(self, client: object) -> None:
        self.transcriptions = AsyncTranscriptions(client)
        self.speech = AsyncSpeech(client)
