"""Plain recording: fixed duration / stop-when / scroll-through."""
from __future__ import annotations

import sys
import time
from pathlib import Path

from . import js_loader
from .bootstrap import ensure_runtime
from .browser import (
    apply_pre_action_waits,
    build_context_options,
    launch_with_browser_install,
    wait_until_settled,
)


def _scroll_through(page, cfg: dict) -> None:
    step = cfg.get("scrollStep", 60)
    interval = cfg.get("scrollInterval", 50)
    pause_top = cfg.get("scrollPauseTop", 800)
    pause_bottom = cfg.get("scrollPauseBottom", 1200)
    page.evaluate("() => window.scrollTo(0, 0)")
    page.wait_for_timeout(pause_top)
    page.evaluate(js_loader.load("scroll_through"), {"step": step, "interval": interval})
    page.wait_for_timeout(pause_bottom)


def _wait_for_stop_condition(page, cfg: dict) -> str:
    cap = cfg.get("maxDuration", 60000)
    duration = cfg.get("duration")
    stop_when_selector = cfg.get("stopWhenSelector")
    stop_when_hidden = cfg.get("stopWhenHidden")
    if not (duration or stop_when_selector or stop_when_hidden):
        page.wait_for_timeout(5000)
        return "default-5s"

    deadline = time.time() + cap / 1000.0
    if duration:
        deadline = min(deadline, time.time() + duration / 1000.0)

    poll = 100
    while time.time() < deadline:
        if stop_when_selector:
            try:
                page.wait_for_selector(stop_when_selector, state="visible", timeout=poll)
                return "stopWhenSelector"
            except Exception:
                pass
        if stop_when_hidden:
            try:
                page.wait_for_selector(stop_when_hidden, state="hidden", timeout=poll)
                return "stopWhenHidden"
            except Exception:
                pass
        if not (stop_when_selector or stop_when_hidden):
            page.wait_for_timeout(min(poll, max(0, int((deadline - time.time()) * 1000))))
    return "duration" if duration else "cap"


def do_record(cfg: dict) -> tuple[Path, int, int]:
    """Plain recording — returns (output_path, start_ms, end_ms).

    start_ms/end_ms 是相对视频起点（context 创建）的内容窗口：start_ms=页面加载就绪时刻，
    end_ms=内容动作结束时刻。调用方据此端锚裁掉开头加载段（skill 侧或委托 ab-render）。
    """
    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 ≈ 视频开始录制的时刻（context 创建即开录）；用于测量加载头/内容窗口，
            # 供 trim_video 端锚裁剪。
            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)
                # 无条件等页面真正加载完成（networkidle + settled 检测 + settleMs）再开录内容——
                # 对所有 URL 生效。加载/白屏段仍会被录进原始视频，随后由 trim_video 端锚裁掉。
                wait_until_settled(page, cfg)
                start_ms = int((time.time() - t0) * 1000)
                if cfg.get("scrollThrough"):
                    _scroll_through(page, cfg)
                    reason = "scrollThrough"
                else:
                    reason = _wait_for_stop_condition(page, cfg)
                end_ms = int((time.time() - t0) * 1000)
                print(f"[runner] stop reason: {reason}", file=sys.stderr)
                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("record finished but no video file was produced")
    src = Path(video_path)
    if src.resolve() != output:
        src.replace(output)
    # 不在此处裁剪：加载头由调用方在收尾/转码那一步端锚裁掉（见 record.py），
    # 避免 skill 侧依赖 ffmpeg 并省去一次重编码。
    return output, start_ms, end_ms
