#!/usr/bin/env bash
# VNC + browser lifecycle — single source of truth.
# Called by systemd ExecStartPre (boot) and lib/vnc.ts ensureVnc() (recovery).
#
# Usage: vnc.sh start | stop | start-chrome | status
#
# Components:
#   Xtigervnc :99        — virtual X11 display + VNC server on port 5900
#   websockify :6080     — WebSocket bridge serving noVNC static files
#   Chromium :9222       — headed browser on display :99 with CDP enabled
#                          (Playwright MCP connects via --cdp-endpoint)

set -uo pipefail

# Derive config dir from brand.json so logs go to the correct brand-specific
# directory (e.g. ~/.realagent/ instead of ~/.maxy/). Primary source is the
# script's own filesystem location; $MAXY_PLATFORM_ROOT is a fallback.
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PLATFORM_ROOT="${MAXY_PLATFORM_ROOT:-$(dirname "$SCRIPT_DIR")}"
BRAND_JSON="${PLATFORM_ROOT}/config/brand.json"
CONFIG_DIR=".maxy"
if [ -f "$BRAND_JSON" ] && command -v jq >/dev/null 2>&1; then
  _dir=$(jq -r '.configDir // empty' "$BRAND_JSON" 2>/dev/null) || true
  [ -n "$_dir" ] && CONFIG_DIR="$_dir"
fi

MAXY_DIR="${HOME}/${CONFIG_DIR}"
LOG_DIR="${MAXY_DIR}/logs"
LOG_FILE="${LOG_DIR}/vnc-boot.log"

mkdir -p "$LOG_DIR"

log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >> "$LOG_FILE"; }

kill_stale() {
  pkill -f 'chromium.*remote-debugging-port=9222' 2>/dev/null || true
  pkill -f 'Xtigervnc :99' 2>/dev/null || true
  pkill -f 'websockify.*6080' 2>/dev/null || true
  rm -f /tmp/.X99-lock /tmp/.X11-unix/X99
  # Clear Chromium profile locks left by unclean shutdown — without this,
  # Chromium refuses to start after a service restart or power loss.
  rm -f "${HOME}/.config/chromium/SingletonLock" \
        "${HOME}/.config/chromium/SingletonCookie" \
        "${HOME}/.config/chromium/SingletonSocket" 2>/dev/null || true
  sleep 2

  # If any VNC-stack processes survived SIGTERM, force-kill them.
  local survivors=0
  pgrep -f 'chromium.*remote-debugging-port=9222' >/dev/null 2>&1 && survivors=1
  pgrep -f 'Xtigervnc :99' >/dev/null 2>&1 && survivors=1
  pgrep -f 'websockify.*6080' >/dev/null 2>&1 && survivors=1
  if [ "$survivors" -eq 1 ]; then
    log "SIGTERM survivors detected — sending SIGKILL"
    pkill -9 -f 'chromium.*remote-debugging-port=9222' 2>/dev/null || true
    pkill -9 -f 'Xtigervnc :99' 2>/dev/null || true
    pkill -9 -f 'websockify.*6080' 2>/dev/null || true
    sleep 1
  fi
}

wait_for_port() {
  local port="$1" max="${2:-40}"
  for _ in $(seq 1 "$max"); do
    ss -tln "sport = :$port" | grep -q LISTEN && return 0
    sleep 0.3
  done
  return 1
}

start_chrome() {
  pkill -f 'chromium.*remote-debugging-port=9222' 2>/dev/null || true
  sleep 0.3

  log "Starting Chromium on :99 with CDP on :9222"

  DISPLAY=:99 /usr/bin/chromium \
    --ozone-platform=x11 \
    --no-sandbox \
    --disable-dev-shm-usage \
    --disable-gpu \
    --password-store=basic \
    --use-mock-keychain \
    --no-first-run \
    --no-default-browser-check \
    --disable-background-networking \
    --disable-sync \
    --disable-default-apps \
    --disable-component-update \
    --disable-features=TranslateUI \
    --disable-session-crashed-bubble \
    --hide-crash-restore-bubble \
    --noerrdialogs \
    --metrics-recording-only \
    --window-size=1280,800 \
    --window-position=0,0 \
    --remote-debugging-port=9222 \
    about:blank \
    >> "$LOG_FILE" 2>&1 &

  if wait_for_port 9222; then
    log "Chromium ready with CDP on :9222"
  else
    log "ERROR: Chromium failed to start — CDP port 9222 not listening (browser-specialist degraded)"
  fi
}

case "${1:-}" in
  start)
    kill_stale
    log "Starting Xtigervnc on :99"

    Xtigervnc :99 \
      -geometry 1280x800 \
      -depth 24 \
      -rfbport 5900 \
      -localhost \
      -SecurityTypes None \
      -AlwaysShared \
      -BlacklistThreshold 1000000 \
      >> "$LOG_FILE" 2>&1 &

    if wait_for_port 5900; then
      log "Xtigervnc ready on :5900"
    else
      log "ERROR: Xtigervnc failed to start — port 5900 not listening"
      exit 1
    fi

    # Guard against duplicate websockify — kill any stale instance before starting
    pkill -f 'websockify.*6080' 2>/dev/null || true
    sleep 0.2

    websockify --web /usr/share/novnc [::]:6080 localhost:5900 >> "$LOG_FILE" 2>&1 &

    if wait_for_port 6080; then
      log "websockify ready on :6080"
    else
      log "ERROR: websockify failed to start — port 6080 not listening"
      exit 1
    fi

    start_chrome

    log "VNC + browser stack running"
    ;;

  start-chrome)
    start_chrome
    ;;

  stop)
    log "Stopping VNC stack"
    kill_stale
    log "VNC stack stopped"
    ;;

  status)
    ss -tln "sport = :5900" | grep -q LISTEN && echo "running" || echo "stopped"
    ;;

  *)
    echo "Usage: vnc.sh start | stop | start-chrome | status" >&2
    exit 1
    ;;
esac
