from __future__ import annotations

from typing import TYPE_CHECKING, Literal

from attrs import define, field

from griptape.artifacts.audio_artifact import AudioArtifact
from griptape.drivers.text_to_speech import BaseTextToSpeechDriver
from griptape.utils import import_optional_dependency
from griptape.utils.decorators import lazy_property

if TYPE_CHECKING:
    import openai


@define
class OpenAiTextToSpeechDriver(BaseTextToSpeechDriver):
    model: str = field(default="tts-1", kw_only=True, metadata={"serializable": True})
    voice: Literal["alloy", "echo", "fable", "onyx", "nova", "shimmer"] = field(
        default="alloy",
        kw_only=True,
        metadata={"serializable": True},
    )
    format: Literal["mp3", "opus", "aac", "flac"] = field(default="mp3", kw_only=True, metadata={"serializable": True})
    # These defaults were changed from openai.api_type, openai.api_version, and openai.organization
    # to None because those module-level attributes don't exist in OpenAI SDK v1.0+
    api_type: str | None = field(default=None, kw_only=True)
    api_version: str | None = field(default=None, kw_only=True, metadata={"serializable": True})
    base_url: str | None = field(default=None, kw_only=True, metadata={"serializable": True})
    api_key: str | None = field(default=None, kw_only=True)
    organization: str | None = field(default=None, kw_only=True, metadata={"serializable": True})
    _client: openai.OpenAI | None = field(default=None, kw_only=True, alias="client", metadata={"serializable": False})

    @lazy_property()
    def client(self) -> openai.OpenAI:
        openai = import_optional_dependency("openai")
        return openai.OpenAI(
            api_key=self.api_key,
            base_url=self.base_url,
            organization=self.organization,
        )

    def try_text_to_audio(self, prompts: list[str]) -> AudioArtifact:
        response = self.client.audio.speech.create(
            input=". ".join(prompts),
            voice=self.voice,
            model=self.model,
            response_format=self.format,
        )

        return AudioArtifact(value=response.content, format=self.format)
