#!/bin/zsh
set -euo pipefail

# browser-window-capture — live screenshot of a Chrome/Edge tab via CDP.
#
# WHY THIS EXISTS
#   `background-window-capture` uses ScreenCaptureKit, which reads the window's
#   backing IOSurface. A Chromium browser window that is occluded (covered by
#   another window, on another Space, or minimized) is throttled by macOS window
#   occlusion: its renderer stops pushing new frames to the IOSurface, so any
#   screen-capture path (ScreenCaptureKit / screencapture / CGWindowList) returns
#   a STALE frame even though the DOM already changed.
#
#   CDP `Page.captureScreenshot` asks the renderer to composite the CURRENT page,
#   independent of window visibility, so it returns a live image of a background
#   tab without bringing the browser to the foreground.
#
# This wrapper is the preferred path to verify browser automation results.
# Use `background-window-capture` for non-browser app windows.

BIN_DIR=${0:A:h}
BWC="$BIN_DIR/background-web-control"

SELECTOR="body"
CLIP="viewport"
TRANSPORT="auto"
FALLBACK="auto"
OUT=""
PSEUDO=""
FRESH_TARGET=0
FRESH_ACTIVE=0
FRESH_WAIT_MS=""
KEEP_FRESH_TARGET=0
typeset -a MATCH
MATCH=()

usage() {
  cat <<'EOF'
Usage:
  browser-window-capture (--url-contains TEXT | --title-contains TEXT |
                          --url-equals URL | --title-equals TITLE | --tab-id ID)
                         --out FILE
                         [--selector CSS] [--clip viewport|element|manual]
                         [--pseudo hover|focus|target|...]
                         [--debugger-transport auto|native|apple-events-js]
                         [--fallback auto|only|off]
                         [--fresh-target] [--fresh-active]

Captures a LIVE screenshot of a matching Chrome/Edge tab through CDP, even when
the browser window is in the background or occluded. Prints the output path.

Examples:
  browser-window-capture --url-contains app.open.qq.com --out /tmp/page.png
  browser-window-capture --title-contains 编辑页 --selector 'textarea.ant-input' \
    --clip element --out /tmp/field.png

For ordinary (non-browser) app windows use background-window-capture instead.
EOF
}

while [[ $# -gt 0 ]]; do
  case "$1" in
    --url-contains|--title-contains|--url-equals|--title-equals|--tab-id|--window-index|--tab-index)
      [[ $# -ge 2 ]] || { echo "browser-window-capture: $1 needs a value" >&2; exit 2; }
      MATCH+=("$1" "$2"); shift 2;;
    --out) OUT="${2:-}"; shift 2;;
    --selector) SELECTOR="${2:-}"; shift 2;;
    --clip) CLIP="${2:-}"; shift 2;;
    --pseudo) PSEUDO="${2:-}"; shift 2;;
    --debugger-transport) TRANSPORT="${2:-}"; shift 2;;
    --fallback) FALLBACK="${2:-}"; shift 2;;
    --fresh-target) FRESH_TARGET=1; shift;;
    --fresh-active) FRESH_ACTIVE=1; shift;;
    --fresh-wait-ms) FRESH_WAIT_MS="${2:-}"; shift 2;;
    --keep-fresh-target) KEEP_FRESH_TARGET=1; shift;;
    -h|--help) usage; exit 0;;
    *) echo "browser-window-capture: unknown argument: $1" >&2; usage >&2; exit 2;;
  esac
done

if [[ -z "$OUT" ]]; then
  echo "browser-window-capture: --out is required" >&2; exit 2
fi
if [[ ${#MATCH} -eq 0 ]]; then
  echo "browser-window-capture: a tab matcher is required (--url-contains/--title-contains/--url-equals/--title-equals/--tab-id)" >&2
  exit 2
fi

typeset -a ARGS
ARGS=(pseudo-snapshot "${MATCH[@]}" --selector "$SELECTOR" --clip "$CLIP" \
      --debugger-transport "$TRANSPORT" --fallback "$FALLBACK" --out "$OUT")
[[ -n "$PSEUDO" ]] && ARGS+=(--pseudo "$PSEUDO")
[[ "$FRESH_TARGET" -eq 1 ]] && ARGS+=(--fresh-target)
[[ "$FRESH_ACTIVE" -eq 1 ]] && ARGS+=(--fresh-active)
[[ -n "$FRESH_WAIT_MS" ]] && ARGS+=(--fresh-wait-ms "$FRESH_WAIT_MS")
[[ "$KEEP_FRESH_TARGET" -eq 1 ]] && ARGS+=(--keep-fresh-target)

resp="$("$BWC" "${ARGS[@]}" 2>&1)" || { echo "$resp" >&2; exit 1; }

# Surface a friendly result; fall back to raw response if JSON parsing fails.
python3 - "$OUT" <<'PY' "$resp" 2>/dev/null || { echo "$resp"; }
import json, sys
out = sys.argv[1]
raw = sys.argv[2]
data = json.loads(raw)
res = (data.get("result") or {}).get("result") or {}
tab = res.get("targetTab") or {}
ok = (data.get("result") or {}).get("ok")
if not ok:
    print(raw); sys.exit(1)
print(res.get("outPath") or out)
print("tab: %s | %s" % (tab.get("title", "?"), tab.get("url", "?")), file=sys.stderr)
PY
