#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""PKSTUDIO моушн-промо: три трека по 30 с через ElevenLabs Music API с планом секций.
  ~/bin/kai-env run python3 clients/pk_motion/tools/pm_music.py [A B C]

План держит структуру ролика: вступление 4 с без бочки, дроп ровно на 4,0 с,
брейк 23-26 с, финальный удар на 26 с и хвост до 30 с. Ключ только из окружения.
"""
import json, os, sys, time, urllib.request, urllib.error
from pathlib import Path

OUT = Path(__file__).resolve().parents[1] / "audio"
URL = "https://api.elevenlabs.io/v1/music"

NEG = ["vocals", "singing", "choir", "lo-fi", "acoustic guitar", "slow ballad", "muddy mix"]
STYLES = {
    "A": ["modern tech product launch", "punchy electronic", "120 BPM", "tight sidechained kick", "deep sub bass",
          "glossy synth stabs", "crisp claps", "confident", "instrumental", "clean wide mix"],
    "B": ["cinematic hybrid trap", "120 BPM", "808 sub bass", "hard hitting drums", "dark synth arps",
          "braams", "tension and release", "instrumental", "big trailer energy"],
    "C": ["future garage meets electro house", "120 BPM", "bouncy bass", "chopped vocal-free synth plucks",
          "shimmering hats", "playful and bold", "instrumental", "creator economy vibe"],
}
SECTIONS = [
    ("Intro tension", ["no kick", "ticking hi-hat", "filtered pulse", "rising tension", "short white noise riser into drop"], 4000),
    ("Drop", ["full drums hit on first beat", "huge impact at start", "driving bass", "energetic groove"], 8000),
    ("Groove", ["groove continues", "add melodic synth layer", "more intensity"], 8000),
    ("Build", ["drums keep going", "snare roll building", "rising pitch sweep", "tension"], 3000),
    ("Break", ["stutter edits", "hard chopped hits on every beat", "no melody", "riser into final hit"], 3000),
    ("Final hit and tail", ["one massive final impact on first beat", "then music stops", "long reverb tail fading out", "silence at the end"], 4000),
]


def plan(k):
    return {"positive_global_styles": STYLES[k], "negative_global_styles": NEG,
            "sections": [{"section_name": n, "positive_local_styles": s, "negative_local_styles": [],
                          "duration_ms": d, "lines": []} for n, s, d in SECTIONS]}


def call(k):
    body = json.dumps({"composition_plan": plan(k), "model_id": "music_v1", "respect_sections_durations": True}).encode()
    req = urllib.request.Request(URL + "?output_format=mp3_44100_192", data=body, method="POST", headers={
        "xi-api-key": os.environ["ELEVENLABS_API_KEY"], "Content-Type": "application/json", "Accept": "audio/mpeg"})
    try:
        with urllib.request.urlopen(req, timeout=400) as r:
            return r.read()
    except urllib.error.HTTPError as e:
        raise RuntimeError("HTTP %s: %s" % (e.code, e.read()[:800].decode(errors="ignore")))


def main():
    keys = [k.upper() for k in sys.argv[1:]] or list(STYLES)
    for i, k in enumerate(keys):
        if i:
            time.sleep(3)
        try:
            data = call(k)
            if data[:1] == b"{":
                raise RuntimeError(data[:500].decode(errors="ignore"))
            (OUT / f"music_{k}.mp3").write_bytes(data)
            print(k, "ok", len(data))
        except Exception as e:
            print(k, "fail", e)


if __name__ == "__main__":
    main()
