#!/usr/bin/env bash
# deploy/bullpen-up — stand up a bullpen room in a fresh Incus system container and PROVE it answers.
#
# One-shot for a new fleet: launches a bridged Debian system container, installs lmcp + this repo,
# seeds config + a room lmcp, then round-trips a room_say/room_read INSIDE the container so you get
# a working box, not a hopeful one. Run it on an Incus host.
#
#   deploy/bullpen-up                 # create ./bullpen (or $BULLPEN_CT) and verify
#   deploy/bullpen-up --verify        # just re-run the room round-trip on an existing container
#   deploy/bullpen-up --destroy       # tear the container down (throwaway test cleanup)
#
# What it brings up: the ROOM (lmcp serving room_say/room_read) + the repo + config. It deliberately
# does NOT start the LLM workers/lurkers — those need your gateway + models + a trust decision about
# fleet creds. See deploy/DEPLOY.md for trust-tiering the agent/exec layer. This proves the substrate.
#
# Everything is overridable by env; the defaults target the origin fleet's public artifacts.
set -euo pipefail

NAME="${BULLPEN_CT:-bullpen}"
IMAGE="${BULLPEN_IMAGE:-images:debian/13}"
PROFILES="${BULLPEN_PROFILES:-default}"                 # comma list; add your bridge, e.g. default,bridgeprofile
REPO_URL="${BULLPEN_REPO_URL:-https://github.com/marfrit/bullpen.git}"
APT_KEY_URL="${BULLPEN_APT_KEY_URL:-https://packages.reauktion.de/marfrit.gpg}"
APT_LINE="${BULLPEN_APT_LINE:-deb [signed-by=/etc/apt/keyrings/marfrit.gpg] https://packages.reauktion.de/debian trixie main}"
PORT="${BULLPEN_ROOM_PORT:-8080}"

say()  { printf '\033[1;36m::\033[0m %s\n' "$*"; }
die()  { printf '\033[1;31m!!\033[0m %s\n' "$*" >&2; exit 1; }
cx()   { incus exec "$NAME" -- "$@"; }
cxsh() { incus exec "$NAME" -- sh -c "$1"; }

command -v incus >/dev/null || die "incus not found — run bullpen-up on an Incus host."

MODE=create
case "${1:-}" in
  --verify)  MODE=verify ;;
  --destroy) MODE=destroy ;;
  -h|--help) sed -n '2,18p' "$0"; exit 0 ;;
  "")        MODE=create ;;
  *)         die "unknown arg: $1 (try --verify | --destroy | --help)" ;;
esac

exists() { incus info "$NAME" >/dev/null 2>&1; }

if [ "$MODE" = destroy ]; then
  exists || { say "no container '$NAME' — nothing to destroy."; exit 0; }
  say "destroying container '$NAME'"
  incus delete -f "$NAME"
  exit 0
fi

# ---- create the container (skip if verifying an existing one) -------------------------------
if [ "$MODE" = create ]; then
  if exists; then
    say "container '$NAME' already exists — reprovisioning (idempotent), then verifying."
  else
    pargs=(); IFS=, read -ra _p <<<"$PROFILES"; for p in "${_p[@]}"; do pargs+=(-p "$p"); done
    say "launching $IMAGE as '$NAME' (profiles: $PROFILES)"
    incus launch "$IMAGE" "$NAME" "${pargs[@]}"
  fi

  # wait for the guest to boot + get DNS/connectivity (system container = systemd inside)
  say "waiting for container network…"
  for i in $(seq 1 60); do
    if cxsh 'command -v apt-get >/dev/null && getent hosts deb.debian.org >/dev/null' 2>/dev/null; then
      break
    fi
    [ "$i" = 60 ] && die "container did not reach the network in 60s"
    sleep 2
  done

  say "installing base packages + lmcp"
  cxsh 'export DEBIAN_FRONTEND=noninteractive
        apt-get update -qq
        apt-get install -y -qq --no-install-recommends git python3 lua5.4 lua-socket curl ca-certificates >/dev/null'
  cxsh "install -d -m0755 /etc/apt/keyrings
        curl -fsSL '$APT_KEY_URL' -o /etc/apt/keyrings/marfrit.gpg
        printf '%s\n' '$APT_LINE' > /etc/apt/sources.list.d/marfrit.list
        export DEBIAN_FRONTEND=noninteractive
        apt-get update -qq
        apt-get install -y -qq lmcp >/dev/null"
  cxsh 'command -v lmcp-example >/dev/null && test -f /usr/share/lua/5.4/server.lua' \
      || die "lmcp did not install cleanly"

  say "cloning the repo -> /opt/bullpen"
  cxsh "test -d /opt/bullpen/.git || git clone --depth 1 '$REPO_URL' /opt/bullpen"
  # vendored lmcp-tool -> PATH (the coordinators call it by name)
  cxsh 'install -m0755 /opt/bullpen/contrib/lmcp-tool /usr/local/bin/lmcp-tool'
  say "running install.sh (symlinks entrypoints -> the checkout)"
  cxsh '/opt/bullpen/deploy/install.sh >/dev/null'

  say "seeding state + config"
  cxsh 'install -d -m0755 /var/lib/bullpen /etc/bullpen
        [ -f /var/lib/bullpen/counter ]   || printf 0 > /var/lib/bullpen/counter
        [ -f /var/lib/bullpen/room.jsonl ] || : > /var/lib/bullpen/room.jsonl
        if [ ! -f /etc/bullpen/post-secret ]; then
          head -c24 /dev/urandom | base64 > /etc/bullpen/post-secret; chmod 600 /etc/bullpen/post-secret
        fi
        if [ ! -f /etc/bullpen/room.conf ]; then
          printf ".godparticle = %s\n" "$(head -c24 /dev/urandom | base64 | tr -d /+=)" > /etc/bullpen/room.conf
          chmod 600 /etc/bullpen/room.conf
        fi
        [ -f /etc/bullpen/bullpen.conf ] || cp /opt/bullpen/bullpen.conf.example /etc/bullpen/bullpen.conf'

  say "installing + starting the room lmcp (port $PORT, tools from the repo)"
  cxsh "cat > /etc/systemd/system/bullpen-room.service <<UNIT
[Unit]
Description=bullpen room (lmcp: room_say/room_read)
After=network.target

[Service]
Type=simple
ExecStart=/usr/bin/lua5.4 /usr/share/lua/5.4/server.lua
Environment=LMCP_NAME=bullpen-room
Environment=LMCP_HOST=127.0.0.1
Environment=LMCP_PORT=$PORT
Environment=LMCP_CONF=/etc/bullpen/room.conf
Environment=LMCP_TOOLS_DIR=/opt/bullpen/lmcp-tools
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
UNIT
        systemctl daemon-reload
        systemctl enable --now bullpen-room.service >/dev/null 2>&1"
fi

exists || die "container '$NAME' does not exist (create it without --verify first)."

# ---- verify: round-trip a message through the room, inside the container --------------------
say "verifying: posting a probe message and reading it back"
MARKER="bullpen-up-probe-$(date +%s)-$$"
VERIFY_SH=$(cat <<EOF
set -e
TOK=\$(grep -oE '[A-Za-z0-9_-]{20,}' /etc/bullpen/room.conf | head -1)
export LMCP_HOST=127.0.0.1 LMCP_PORT=$PORT LMCP_TOKEN="\$TOK"
# wait for the room to accept connections
for i in \$(seq 1 30); do lmcp-tool list >/dev/null 2>&1 && break; sleep 1; done
# post as a non-privileged nick (no shared secret needed), then read it back
lmcp-tool room_say from=deploy-probe "body=$MARKER" >/dev/null
lmcp-tool room_read since=0 limit=20
EOF
)
OUT=$(cxsh "$VERIFY_SH" 2>&1) || die "verify failed to run inside container:\n$OUT"

if printf '%s' "$OUT" | grep -qF "$MARKER"; then
  IP=$(incus list "$NAME" -c4 --format csv 2>/dev/null | awk '{print $1}' | head -1)
  say "OK — the room answered inside '$NAME'. Probe round-tripped."
  [ -n "$IP" ] && say "container IP: $IP  (room lmcp on 127.0.0.1:$PORT)"
  echo
  echo "Next: bring up the agent/exec tier per deploy/DEPLOY.md (trust-tiered, no fleet creds),"
  echo "and set /etc/bullpen/bullpen.conf for your fleet. Throwaway? deploy/bullpen-up --destroy"
else
  die "verify FAILED — probe '$MARKER' did not come back. Room output was:\n$OUT"
fi
