"""Generate the 5 mood reference clips Pocket TTS clones for [emotion] tags.

Jarvis can prefix a sentence with [calm]/[warm]/[excited]/[sad]/[dry]/… and have
it spoken in that tone. On the Mac (Pocket TTS) that works by *swapping the
voice-clone reference clip* per mood — but those clips have to exist. This script
renders them once with Chatterbox (which has a real emotion dial), cloning the
base Jarvis voice (voices/jarvis_ref.wav) at each mood's exaggeration level, and
writes voices/jarvis_<stem>.wav. Pocket picks them up automatically at startup.

WHERE TO RUN: the RTX/Windows box (CUDA) or this M4 (MPS) — anywhere Chatterbox
loads. It is NOT needed for tone *sensing* (that's pure-numpy, always on); it only
gives Jarvis's own spoken replies real mood on the Mac Pocket engine.

    VOICE_ENGINE=chatterbox python tools/make_mood_clips.py         # make missing
    VOICE_ENGINE=chatterbox FORCE=1 python tools/make_mood_clips.py # redo all

Stems mirror voice/tts_pocket.py:_TAG_TO_STEM. Chatterbox outputs float32 @ 24kHz.
"""

from __future__ import annotations

import os
import sys
from pathlib import Path

import numpy as np
from scipy.io import wavfile

sys.path.insert(0, str(Path(__file__).resolve().parent.parent))

_VOICES = Path(__file__).resolve().parent.parent / "voices"
_SR = 24_000

# stem -> ([emotion] tag driving Chatterbox's exaggeration, a line whose delivery
# characterises that mood so the cloned timbre carries it). Stems match Pocket's
# _TAG_TO_STEM: calm, warm, excited, sad, dry.
_MOODS = {
    "calm":    ("[calm] Everything is under control, sir. There's no need to worry at all."),
    "warm":    ("[warm] Of course, sir. It's always a genuine pleasure to help you."),
    "excited": ("[excited] Brilliant news, sir — this is exactly what we'd hoped for!"),
    "sad":     ("[sad] I'm terribly sorry, sir. I do wish I had better news for you."),
    "dry":     ("[dry] Oh, marvelous. Another meeting. How thrilling, sir."),
    # richer palette (2026-07-10)
    "shocked": ("[shocked] Good God, sir — you actually did it. I did not see that coming."),
    "curious": ("[curious] Now that is genuinely interesting. Tell me more, sir — how does it work?"),
    "amused":  ("[amused] Ha. Oh, that's brilliant, sir. You really are something else."),
    "annoyed": ("[annoyed] Sir. For the third time. It is not going to change."),
    "tender":  ("[tender] It's alright, sir. Take your time. I'm right here."),
}


def main() -> int:
    os.environ.setdefault("VOICE_ENGINE", "chatterbox")
    from voice.tts_chatterbox import ChatterboxTTS, loadable

    if not loadable():
        print("Chatterbox can't load here (no CUDA/MPS headroom). Run this on "
              "the RTX box or an idle Mac with VOICE_ENGINE=chatterbox.")
        return 1

    ref = _VOICES / "jarvis_ref.wav"
    if not ref.is_file():
        print(f"Missing base voice {ref} — clone Jarvis first.")
        return 1

    _VOICES.mkdir(exist_ok=True)
    force = os.environ.get("FORCE") == "1"
    tts = ChatterboxTTS()
    made = 0
    for stem, line in _MOODS.items():
        out = _VOICES / f"jarvis_{stem}.wav"
        if out.is_file() and not force:
            print(f"  keep  {out.name} (exists; FORCE=1 to redo)")
            continue
        pcm = tts.synth(line)  # [tag] sets the exaggeration; ref clones the voice
        if pcm is None or len(pcm) == 0:
            print(f"  FAIL  {out.name} (empty synth)")
            continue
        pcm = np.clip(np.asarray(pcm, dtype=np.float32), -1.0, 1.0)
        wavfile.write(str(out), _SR, (pcm * 32767).astype(np.int16))
        made += 1
        print(f"  wrote {out.name}  ({len(pcm)/_SR:.1f}s)")
    print(f"\nDone — {made} clip(s) written to {_VOICES}. "
          "Restart Jarvis; Pocket TTS loads them at startup.")
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
