"""Storyboard runner: orchestrate a sequence of scenes with smooth transitions."""
from __future__ import annotations

import sys
import time
from pathlib import Path

from .bootstrap import ensure_runtime
from .browser import (
    apply_pre_action_waits,
    build_context_options,
    launch_with_browser_install,
    wait_until_settled,
)
from .overlay import clear_overlay, ensure_overlay, fade_out_overlays
from . import scenes


def _run_storyboard(page, cfg: dict) -> None:
    ensure_overlay(page)
    scene_list = cfg.get("scenes") or []
    transition = cfg.get("transition") or {}
    fade_out_ms = transition.get("fadeOutMs", transition.get("duration", 350))
    gap_ms = transition.get("gapMs", 150)
    for i, scene in enumerate(scene_list):
        handler = scenes.get_handler(scene.get("type", ""))
        if not handler:
            print(
                f"[runner] skip unknown scene type: {scene.get('type')!r} "
                f"(known: {', '.join(scenes.known_types())})",
                file=sys.stderr,
            )
            continue
        print(
            f"[runner] scene {i + 1}/{len(scene_list)}: {scene['type']}",
            file=sys.stderr,
        )
        handler(page, scene)
        if i < len(scene_list) - 1:
            fade_out_overlays(page, fade_out_ms)
            clear_overlay(page)
            ensure_overlay(page)
            if gap_ms > 0:
                page.wait_for_timeout(gap_ms)


def do_storyboard(cfg: dict) -> tuple[Path, int, int]:
    """Run a storyboard recording. Returns (output_path, start_ms, end_ms)."""
    ensure_runtime()
    from playwright.sync_api import sync_playwright

    output = Path(cfg["output"]).resolve()
    output.parent.mkdir(parents=True, exist_ok=True)
    out_dir = str(output.parent)

    with sync_playwright() as p:
        browser = launch_with_browser_install(p, cfg.get("browser"))
        try:
            t0 = time.time()
            context = browser.new_context(**build_context_options(p, cfg, out_dir))
            if cfg.get("timeout"):
                context.set_default_timeout(cfg["timeout"])
            page = context.new_page()
            video_path: str | None = None
            start_ms = 0
            end_ms = 0
            try:
                page.goto(cfg["url"], wait_until="domcontentloaded")
                apply_pre_action_waits(page, cfg)
                wait_until_settled(page, cfg)
                start_ms = int((time.time() - t0) * 1000)
                _run_storyboard(page, cfg)
                end_ms = int((time.time() - t0) * 1000)
                video = page.video
                context.close()
                if video:
                    video_path = video.path()
            finally:
                pass
        finally:
            browser.close()

    if not video_path or not Path(video_path).exists():
        raise SystemExit("storyboard finished but no video file was produced")
    src = Path(video_path)
    if src.resolve() != output:
        src.replace(output)
    return output, start_ms, end_ms
