#!/usr/bin/env python3
"""foundry_stems — thin bridge to the Foundry demucs engine for stem-aware emotion.

The Foundry (tools/foundry) is the shared stem-separation engine; we consume its
in-process Python API to turn a track into vocals/bass/drums/other, idempotently
(catch.json caches the result, so re-runs are free). Why stems: the full mix is
muddy for CLAP — the VOCALS carry valence, DRUMS+BASS carry arousal, and vocal
presence is itself a section/structure cue. See ../../tools/foundry/README.md
("Use as an API") and [[project_foundry]] / [[project_hexa_emotion_convergence]].

    python3 foundry_stems.py <audio-file> [slug]      # separate one file, print stem paths
"""
import sys
from pathlib import Path

HERE = Path(__file__).resolve().parent
FOUNDRY = HERE.parent.parent / "tools" / "foundry"
WS = HERE / "_corpus_cache" / "foundry"
STEM_NAMES = ("vocals", "bass", "drums", "other")


def ensure_stems(audio_path, slug, *, shifts=1, log=print):
    """Local audio file → {mix, vocals, bass, drums, other} → absolute Paths.
    Reuses existing stems if the catch is already separated (idempotent)."""
    import shutil
    if str(FOUNDRY) not in sys.path:
        sys.path.insert(0, str(FOUNDRY))
    from engine import separate
    from engine.model import Catch
    WS.mkdir(parents=True, exist_ok=True)
    d = WS / slug
    if (d / "catch.json").exists():
        c = Catch.load(d)
    else:
        d.mkdir(parents=True, exist_ok=True)
        src = d / ("source" + Path(audio_path).suffix.lower())
        if not src.exists():
            shutil.copy(audio_path, src)
        c = Catch(slug=slug, title=slug, source_path=src.name)
        c.save(WS)
    if not c.separated:
        c = separate.separate(c, WS, backend="demucs", shifts=shifts, log=log)
        c.save(WS)
    cd = c.dir(WS)
    out = {"mix": cd / c.source_path}
    for s in c.stems:
        out[s.name] = cd / s.path
    return out


def main():
    if len(sys.argv) < 2:
        sys.exit("usage: foundry_stems.py <audio-file> [slug]")
    p = Path(sys.argv[1])
    slug = sys.argv[2] if len(sys.argv) > 2 else p.stem
    stems = ensure_stems(p, slug)
    for name, path in stems.items():
        print(f"  {name:<7} {path}")


if __name__ == "__main__":
    main()
