# backend/app/multimodal/stt.py — 음성→텍스트(STT) 추상화 (LLM Provider 패턴)
from abc import ABC, abstractmethod
from dataclasses import dataclass


@dataclass
class Transcript:
    text: str
    seconds: float = 0.0
    model: str = ""  # "stt:<model>" | "heuristic"
    confidence: float = 0.0


class STTProvider(ABC):
    name: str = "base"

    @abstractmethod
    def health(self) -> dict: ...

    @abstractmethod
    def transcribe(
        self, audio: bytes, *, mime: str = "audio/webm", hint: str = ""
    ) -> Transcript: ...


class OllamaWhisperSTT(STTProvider):
    """STT_MODEL(whisper류) 주입. 로컬 whisper/멀티모달 서버에 오디오 전송.
    미가용 시 factory.auto 가 HeuristicSTT 로 폴백."""

    name = "stt"

    def __init__(self):
        from ..config import get_settings

        self.st = get_settings()

    def health(self) -> dict:
        import httpx

        try:
            r = httpx.get(f"{self.st.ollama_host}/api/tags", timeout=2.0)
            return {"reachable": r.status_code == 200, "model": self.st.stt_model}
        except Exception:
            return {"reachable": False}

    def transcribe(self, audio: bytes, *, mime="audio/webm", hint="") -> Transcript:
        # 실모델 연동은 phase-15. 현재는 health 불가 시 폴백되며, 가능 시에도
        # 안전하게 heuristic 텍스트로 환원(데모 결정성 보장).
        return HeuristicSTT().transcribe(audio, mime=mime, hint=hint)


class HeuristicSTT(STTProvider):
    """오프라인/CI 폴백. 골든 입력(data.js magicInbox / sinbox 음성메모)을 결정적으로 재현."""

    name = "heuristic"
    GOLDEN = {
        "pool": "음성 메모 0:14 — 수영장 차광막 부품 알아보기",
        "gift": "음성 메모 0:09 — 엄마 생신 선물 미리 알아보기",
    }

    def health(self) -> dict:
        return {"reachable": True, "model": "heuristic"}

    def transcribe(self, audio: bytes, *, mime="audio/webm", hint="") -> Transcript:
        text = self.GOLDEN.get(hint) or hint or "음성 메모 — (텍스트로 적어주세요)"
        return Transcript(text=text, seconds=0.0, model="heuristic", confidence=0.4)
