"""② Higgsfield step — photos + prompt → completed 8s base video.

Thin wrapper around the verified CLI flow:
  higgsfield generate cost/create marketing_studio_video --mode tv_spot ...
dry_run=True returns a bundled demo clip and spends no credits.
"""
from __future__ import annotations

import json
import re
import subprocess
import urllib.request
import uuid
from pathlib import Path

ENGINE = Path(__file__).resolve().parents[3]          # engine/higgsfield_shorts
DEMO_VIDEO = ENGINE / "webapp" / "demo" / "mumum.mp4"
TMP = ENGINE / "server" / ".tmp"

MODEL = "marketing_studio_video"
_URL_RE = re.compile(r'"result_url"\s*:\s*"([^"]+)"')
_CREDITS_RE = re.compile(r'"credits(?:_exact)?"\s*:\s*([0-9.]+)')


def _base_args(prompt: str, image_paths: list[Path], duration: int) -> list[str]:
    args = ["--prompt", prompt]
    for p in image_paths:
        args += ["--image", str(p)]
    args += ["--mode", "tv_spot", "--duration", str(duration),
             "--generate_audio", "true", "--aspect_ratio", "9:16"]
    return args


def cost(prompt: str, image_paths: list[Path], duration: int = 8) -> float:
    out = subprocess.run(
        ["higgsfield", "generate", "cost", MODEL, *_base_args(prompt, image_paths, duration), "--json"],
        capture_output=True, text=True, check=True,
    )
    m = _CREDITS_RE.search(out.stdout)
    return float(m.group(1)) if m else 0.0


def generate(
    prompt: str,
    image_paths: list[Path],
    duration: int = 8,
    dry_run: bool = False,
    wait_timeout: str = "15m",
) -> tuple[Path, float]:
    """Return (local mp4 path, credits spent)."""
    if dry_run:
        return DEMO_VIDEO, 0.0

    out = subprocess.run(
        ["higgsfield", "generate", "create", MODEL,
         *_base_args(prompt, image_paths, duration),
         "--wait", "--wait-timeout", wait_timeout, "--json"],
        capture_output=True, text=True, check=True,
    )
    m = _URL_RE.search(out.stdout)
    if not m:
        raise RuntimeError(f"Higgsfield returned no result_url:\n{out.stdout[-2000:]}")
    url = m.group(1)
    credits_m = _CREDITS_RE.search(out.stdout)
    credits = float(credits_m.group(1)) if credits_m else 0.0

    TMP.mkdir(parents=True, exist_ok=True)
    dest = TMP / f"base_{uuid.uuid4().hex[:8]}.mp4"
    urllib.request.urlretrieve(url, dest)
    return dest, credits
