"""One-off: synthesize a short Korean sample for every canonical emotion.

Each clip announces the emotion name at neutral (base) speed, then speaks a
sample sentence steered by that emotion's ``[태그]`` — exactly the path the live
voice server uses. Writes one wav per emotion into an output directory (plus a
stitched all-in-one) so each emotion can be auditioned separately. Run with the
orchestrator venv:

    .venv/bin/python -m tests.gen_emotion_samples /abs/out_dir
"""

from __future__ import annotations

import asyncio
import sys
import wave
from pathlib import Path

from wsai.backends.melo import MeloTTS

# (canonical english for filename, announced Korean name, emotion tag, sample)
SAMPLES: list[tuple[str, str, str, str]] = [
    ("base",         "기본",        "기본",        "이건 기본 목소리예요, 감정 없이 이렇게 말해요."),
    ("happy",        "기쁨",        "기쁨",        "오늘은 정말 기분 좋은 하루예요!"),
    ("excited",      "신남",        "신남",        "우와, 이거 진짜 신난다! 빨리 하자!"),
    ("hopeful",      "희망",        "희망",        "우리 분명히 잘 해낼 수 있어요!"),
    ("sad",          "슬픔",        "슬픔",        "조금 속상한 일이 있었어요."),
    ("angry",        "화남",        "화남",        "정말 너무하잖아요, 화가 나요."),
    ("fearful",      "두려움",      "두려움",      "어떡하지, 너무 무서워요."),
    ("surprised",    "놀람",        "놀람",        "어머, 이게 정말이에요?"),
    ("disgust",      "혐오",        "혐오",        "으, 이건 좀 별로예요."),
    ("calm",         "차분",        "차분",        "천천히 하나씩 정리해 볼게요."),
    ("friendly",     "다정",        "다정",        "언제든지 편하게 말해 주세요."),
    ("serious",      "진지",        "진지",        "이건 정말 중요한 이야기예요."),
    ("disappointed", "실망",        "실망",        "조금 아쉬운 결과네요."),
    ("tired",        "피곤",        "피곤",        "아, 오늘 너무 피곤하네요."),
    ("affectionate", "사랑스럽게",  "사랑스럽게",  "당신은 정말 소중한 사람이에요."),
    ("playful",      "장난스럽게",  "장난스럽게",  "히히, 한번 맞혀 보세요!"),
    ("curious",      "궁금",        "궁금",        "그건 대체 왜 그런 걸까요?"),
    ("whisper",      "속삭임",      "속삭임",      "조용히, 우리끼리만 아는 비밀이에요."),
    ("shout",        "외침",        "외침",        "다 같이 힘내자, 파이팅!"),
    ("determined",   "단호",        "단호",        "이번엔 반드시 해내겠어요."),
    ("relieved",     "안도",        "안도",        "휴, 이제야 마음이 놓이네요."),
]


def stitch(paths: list[str], out: str, gap_s: float = 0.45) -> None:
    with wave.open(paths[0], "rb") as w0:
        nch, sw, fr = w0.getnchannels(), w0.getsampwidth(), w0.getframerate()
    silence = b"\x00" * (int(fr * gap_s) * sw * nch)
    with wave.open(out, "wb") as wo:
        wo.setnchannels(nch)
        wo.setsampwidth(sw)
        wo.setframerate(fr)
        for i, p in enumerate(paths):
            with wave.open(p, "rb") as w:
                wo.writeframes(w.readframes(w.getnframes()))
            if i < len(paths) - 1:
                wo.writeframes(silence)


async def main(out_dir: str) -> None:
    d = Path(out_dir)
    d.mkdir(parents=True, exist_ok=True)
    tts = MeloTTS()  # base speed comes from WSAI_TTS_SPEED default
    await tts.warmup()
    print(f"melo ready ({tts.load_ms} ms), base speed {tts.speed}")
    paths: list[str] = []
    for i, (canon, name, tag, sample) in enumerate(SAMPLES, 1):
        text = f"{name}. [{tag}] {sample}"
        src = await tts.synth(text)
        dst = d / f"emo_{i:02d}_{canon}.wav"
        Path(src).replace(dst)
        paths.append(str(dst))
        print(f"  {name:8s} -> {dst}")
    await tts.aclose()
    stitch(paths, str(d / "emotion_samples_all.wav"))
    print(f"wrote {len(paths)} per-emotion wavs + stitched all -> {d}")


if __name__ == "__main__":
    out_dir = sys.argv[1] if len(sys.argv) > 1 else "/tmp/emotion_samples"
    asyncio.run(main(out_dir))
