#!/usr/bin/env bash
# AtelierCode supervisor launcher — the package entrypoint (ticket 048).
#
# Installed at /opt/ateliercode/ateliercode and symlinked from /usr/bin/ateliercode.
# It is the production analogue of host/run-host.sh: it starts the headless
# `ateliercode-core` sidecar (which in turn spawns the pty-daemon next to it),
# then launches the native CEF host with the supervisor relaunch loop that
# papers over CEF's ~10% early-startup flake (ticket 018).
#
# Layout it expects (PREFIX defaults to this script's own directory):
#   $PREFIX/ateliercode                 (this launcher)
#   $PREFIX/host/ateliercode_host       (CEF host binary + CEF runtime files)
#   $PREFIX/host/ui/                     (built React UI; host serves it via app://)
#   $PREFIX/bin/ateliercode-core         (headless sidecar)
#   $PREFIX/bin/pty-daemon               (PTY daemon, found next to the core)
set -u

# Resolve install prefix from this script's real location (follows the symlink).
SELF="$(readlink -f "${BASH_SOURCE[0]}")"
PREFIX="${ATELIERCODE_PREFIX:-$(dirname "$SELF")}"

# --- Channel (ticket 054 — parallel CEF rollout) ------------------------------
# Report which release channel this install is. Explicit ATELIER_CHANNEL wins;
# otherwise infer from the install prefix (`/opt/ateliercode-next` -> next). This
# is the opt-in flag the app/host can read (exported below) and what shows up in
# logs/feedback so rollout telemetry can attribute reports to the right channel.
if [[ -z "${ATELIER_CHANNEL:-}" ]]; then
  case "$PREFIX" in
    */ateliercode-next) ATELIER_CHANNEL="next" ;;
    *)                  ATELIER_CHANNEL="stable" ;;
  esac
fi
export ATELIER_CHANNEL
# ATELIER_SHELL is the runtime-shell hint the docs/launcher use; the CEF build
# is always the `cef` shell regardless of channel.
export ATELIER_SHELL="${ATELIER_SHELL:-cef}"

HOST_BIN="${ATELIERCODE_HOST_BIN:-$PREFIX/host/ateliercode_host}"
CORE_BIN="${ATELIERCODE_CORE_BIN:-$PREFIX/bin/ateliercode-core}"

# The host serves the bundled UI from <exe>/ui by default; we ship it there, so
# no ATELIER_UI_DIR override is needed. Set it anyway for robustness.
export ATELIER_UI_DIR="${ATELIER_UI_DIR:-$PREFIX/host/ui}"

# Supervisor relaunch knobs (mirror host/run-host.sh).
MAX_RETRIES="${ATELIERCODE_HOST_MAX_RETRIES:-5}"
EARLY_SECONDS="${ATELIERCODE_HOST_EARLY_SECONDS:-8}"

log() { echo "[ateliercode] $*" >&2; }

log "channel=$ATELIER_CHANNEL shell=$ATELIER_SHELL prefix=$PREFIX"

if [[ ! -x "$HOST_BIN" ]]; then
  log "host binary not found/executable: $HOST_BIN"
  exit 127
fi

# --- Core sidecar ------------------------------------------------------------
# The HOST owns the core lifecycle: it spawns and supervises an ateliercode-core
# child (which in turn spawns the pty-daemon next to itself) and discovers it via
# core-endpoint.json in the XDG data dir. We only point the host at the installed
# core binary — we must NOT start the core here, or the host treats it as a stale
# core, kills it, and respawns (churn + a transient window with no backend).
# NB: the host reads $ATELIER_CORE_BIN (note: not $ATELIERCODE_CORE_BIN).
export ATELIER_CORE_BIN="$CORE_BIN"
if [[ ! -x "$CORE_BIN" ]]; then
  log "WARNING: ateliercode-core not found at $CORE_BIN — terminals/agent backend will be unavailable"
fi

# --- Supervised host launch ---------------------------------------------------
rc=0
for attempt in $(seq 1 "$MAX_RETRIES"); do
  start=$SECONDS
  "$HOST_BIN" "$@"
  rc=$?
  elapsed=$(( SECONDS - start ))
  if [[ $rc -eq 0 || $elapsed -ge $EARLY_SECONDS ]]; then
    exit $rc
  fi
  log "host exited rc=$rc after ${elapsed}s (early startup crash) — relaunch ${attempt}/${MAX_RETRIES}"
done

log "gave up after ${MAX_RETRIES} early crashes (see ticket 018)"
exit "$rc"
