#!/usr/bin/env bash
# Boots the walled-store stack inside the container, then the app (see WALLED-STORES.md):
#   Xvfb (virtual display) -> headful Chrome (remote debugging) -> x11vnc -> noVNC -> Node app.
# CRITICAL: Chrome runs HEADFUL under Xvfb, never `--headless` (that's the fingerprint
# Cloudflare beats). A human clears challenges through the noVNC stream.
set -euo pipefail

PROFILE_DIR="${CHROME_PROFILE_DIR:-/data/chrome-profile}"
mkdir -p "$PROFILE_DIR"

# SQLite home (cache + measurement DBs). Excluded from the image by .dockerignore;
# better-sqlite3 refuses to create a missing directory. Mount a volume here to persist stats.
mkdir -p /app/data

# A container restart reuses the filesystem: clear a dead X server's lock or Xvfb
# refuses :99, x11vnc can't connect, and the stack crash-loops.
rm -f /tmp/.X99-lock /tmp/.X11-unix/X99

# Same idea for the PERSISTENT profile volume: a previous container's Chrome leaves
# Singleton* locks naming the old hostname, and the new Chrome refuses the profile
# ("in use ... on another computer"). Only one Chrome ever runs here — safe to clear.
rm -f "$PROFILE_DIR"/Singleton{Lock,Socket,Cookie}

# 800x600 deliberately: headful Chrome under Xvfb (no window manager) renders its content
# view at a fixed 800x600 regardless of window/screen size — verified every which way. A
# larger screen just frames that 800x600 in black (an L-shaped border), which is what made
# the noVNC stream look tiny on a phone. Sizing the framebuffer to the content = the whole
# stream IS the browser, and the frontend's noVNC `resize=scale` then fits it to the device.
echo "[entrypoint] starting Xvfb on ${DISPLAY}"
Xvfb "${DISPLAY}" -screen 0 800x600x24 -ac +extension RANDR >/tmp/xvfb.log 2>&1 &

# Give the display a moment.
for _ in $(seq 1 20); do xdpyinfo -display "${DISPLAY}" >/dev/null 2>&1 && break; sleep 0.3; done || true

echo "[entrypoint] starting headful Chrome (remote debugging :9222)"
# --kiosk = fullscreen with NO browser UI (no tab strip, no omnibox): the noVNC stream
# shows only page content, so a solver sees the challenge cleanly, not our pile of
# per-store tabs. BrowserHub.bringToFront() picks which tab's content is on screen.
"${CHROME_BIN}" \
  --display="${DISPLAY}" \
  --remote-debugging-address=127.0.0.1 --remote-debugging-port=9222 \
  --user-data-dir="${PROFILE_DIR}" \
  --no-sandbox --disable-dev-shm-usage --disable-gpu \
  --no-first-run --no-default-browser-check \
  --kiosk --window-position=0,0 --window-size=800,600 \
  about:blank >/tmp/chrome.log 2>&1 &

echo "[entrypoint] starting x11vnc + noVNC (:8080)"
x11vnc -display "${DISPLAY}" -forever -shared -nopw -rfbport 5900 -bg -o /tmp/x11vnc.log
websockify --web=/usr/share/novnc 8080 127.0.0.1:5900 >/tmp/novnc.log 2>&1 &

# NOT `npm start` — that re-runs the Angular build (already baked into the image at
# /app/public) and adds ~35s to every container (re)start.
echo "[entrypoint] starting app on ${HOST}:${PORT}"
exec npx tsx src/server.ts
