#!/usr/bin/env bash
# deploy/install.sh — point this host's live bullpen AT this working copy, so the repo is the
# source of truth and `git pull` is the whole deploy.
#
# The drift problem: the fleet used to run hand-edited loose copies (scripts in ~/.local/bin,
# unit files copied into /etc/systemd/system), which silently diverged from the repo. This
# replaces those copies with SYMLINKS into the checked-out repo, so:
#   * the running fleet == the repo, always; editing the live file IS editing the tracked file;
#   * to update a host: `git pull` here (+ a daemon-reload / service restart to pick it up).
#
# Two layouts:
#   install.sh            user layout  — bin/ -> ~/.local/bin, units -> ~/.config/systemd/user
#   install.sh --system   system layout — bin/ -> /usr/local/bin, lib/ -> /usr/local/lib/bullpen,
#                         contrib/lmcp-tool on PATH, units -> /etc/systemd/system (run as root)
#
# It deploys: bin/bullpen-* + the lurker, lib/*.py (--system), contrib/lmcp-tool (--system),
# and every systemd/ + lurker/ unit file. It does NOT touch per-nick lurker config dirs or the
# lmcp room tool (fleet state / load-bearing — deploy those deliberately).
#
# The units carry NO usernames and need no per-host editing. Because the SAME tracked file is
# symlinked into either layout, a literal ExecStart path is necessarily wrong in one of them —
# which is why it flip-flopped twice (6905f4e -> 933dd86) and crash-looped bullpen-triage. The
# units instead say `Environment=PATH=%h/.local/bin:/usr/local/bin:…` + `ExecStart=/usr/bin/env
# <prog>`: in user scope %h is the user's home and ~/.local/bin wins; in system scope %h is
# /root, that entry misses, and /usr/local/bin wins. tests/test_units_portable.py holds the line.
#
# Idempotent and reversible: a pre-existing NON-symlink file is moved to <name>.predeploy-bak
# before the symlink is created. Re-running is safe.
set -euo pipefail

REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"

SYSTEM=0
case "${1:-}" in
  --system) SYSTEM=1 ;;
  ""|--user) SYSTEM=0 ;;
  -h|--help) sed -n '2,20p' "$0"; exit 0 ;;
  *) echo "usage: install.sh [--system]" >&2; exit 2 ;;
esac

if [ "$SYSTEM" = 1 ]; then
  BINDEST="/usr/local/bin"; LIBDEST="/usr/local/lib/bullpen"; UNITDEST="/etc/systemd/system"
  [ -w /usr/local/bin ] || { echo "install.sh --system needs write to /usr/local — run as root/sudo." >&2; exit 1; }
else
  BINDEST="${HOME}/.local/bin"; LIBDEST=""; UNITDEST="${HOME}/.config/systemd/user"
fi
mkdir -p "$BINDEST" "$UNITDEST"; [ -n "$LIBDEST" ] && mkdir -p "$LIBDEST"

link() {  # link <path-relative-to-repo> <dest-dir> <name>
  local src="$REPO/$1" dest="$2" name="$3" tgt="$2/$3"
  [ -f "$src" ] || { echo "  skip $name (no $1 in repo)"; return; }
  if [ -L "$tgt" ] && [ "$(readlink -f "$tgt")" = "$(readlink -f "$src")" ]; then
    echo "  ok   $name (already linked)"; return
  fi
  if [ -e "$tgt" ] && [ ! -L "$tgt" ]; then
    mv -- "$tgt" "$tgt.predeploy-bak"
    echo "  bak  $name -> $name.predeploy-bak"
  fi
  ln -sfn "$src" "$tgt"
  echo "  link $name -> $src"
}

echo "bullpen deploy ($([ "$SYSTEM" = 1 ] && echo system || echo user)): symlinking -> $REPO"
# EVERY executable in bin/, not just bullpen-*. The old glob was `bin/bullpen-*`, which
# silently excluded `bp`, `room-ask`, `room_tail`, `news-de` and `deus-seize` — i.e. the
# commands a human actually types, plus the emergency stop. They were hand-copied once and
# then drifted: on 2026-08-02 hertz still ran a `bp` from 2026-07-21, and deus-seize had
# never been deployed at all. A deploy whose promise is "the running fleet == the repo"
# cannot have a name-shaped hole in it.
for f in "$REPO"/bin/*; do
  [ -f "$f" ] || continue          # skips __pycache__/ and any other directory
  [ -x "$f" ] || continue          # data files in bin/ are not entrypoints
  link "bin/$(basename "$f")" "$BINDEST" "$(basename "$f")"
done
# … plus the lurker (lives under lurker/, not bin/)
link "lurker/bullpen-lurker" "$BINDEST" "bullpen-lurker"

if [ "$SYSTEM" = 1 ]; then
  # the config/worker/participant libs the entrypoints import from /usr/local/lib/bullpen
  for f in "$REPO"/lib/*.py; do
    [ -e "$f" ] || continue
    link "lib/$(basename "$f")" "$LIBDEST" "$(basename "$f")"
  done
  # the lmcp-tool client the coordinators call by name (room host)
  link "contrib/lmcp-tool" "$BINDEST" "lmcp-tool"
fi

# systemd units — symlink service/timer files so `git pull` + daemon-reload deploys unit edits
units=0
for f in "$REPO"/systemd/*.service "$REPO"/systemd/*.timer "$REPO"/lurker/*.service; do
  [ -e "$f" ] || continue
  case "$f" in "$REPO"/systemd/*) rel="systemd/$(basename "$f")";; *) rel="lurker/$(basename "$f")";; esac
  link "$rel" "$UNITDEST" "$(basename "$f")"; units=1
done
if [ "$units" = 1 ]; then
  if [ "$SYSTEM" = 1 ]; then systemctl daemon-reload; else systemctl --user daemon-reload 2>/dev/null || true; fi
  echo "  systemd daemon-reload ($UNITDEST)"
fi

echo "done. scripts are byte-identical to what already ran (no restart needed);"
echo "changed unit files take effect after the daemon-reload above + a service restart."
