#!/usr/bin/env bash
# Installs the agent sandbox onto a buildbox: host tooling, the forced-command
# e2e channel, and the pinned images. Touches only the target user's home —
# never /etc, never a systemd unit, never network or sshd configuration.
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" && pwd)"
MODULE_DIR="$(cd "$SCRIPT_DIR/../../../sandbox" && pwd)"
REGISTRY="$SCRIPT_DIR/../lib/buildbox-registry.mjs"
SHARED_PAIR_LIB="$SCRIPT_DIR/../lib/e2e-pair.sh"
AUTHORIZED_KEYS_MARKER="overdeck-sandbox-e2e"
HOST=""
FORCE_BUILD=()

usage() {
  cat >&2 <<'USAGE'
usage: sandbox-provision [--host <name>] [--rebuild]

Resolves the target from the buildbox registry (order "build", role "agent-seat")
unless --host names one explicitly. Idempotent.
USAGE
  exit "${1:-2}"
}

while [ $# -gt 0 ]; do
  case "$1" in
    --host)    HOST="${2-}"; shift 2 ;;
    --rebuild) FORCE_BUILD=(--force); shift ;;
    -h|--help) usage 0 ;;
    *) echo "sandbox-provision: unknown arg: $1" >&2; usage ;;
  esac
done

[ -r "$REGISTRY" ] || { echo "sandbox-provision: buildbox registry resolver missing at $REGISTRY" >&2; exit 2; }
[ -r "$SHARED_PAIR_LIB" ] || { echo "sandbox-provision: e2e pair orchestrator missing at $SHARED_PAIR_LIB" >&2; exit 2; }

if [ -z "$HOST" ]; then
  HOST="$(node -e '
    import("'"$REGISTRY"'").then(({ loadRegistry, resolveHosts }) => {
      const registry = loadRegistry();
      const byName = new Map(registry.hosts.map((h) => [h.name, h]));
      const candidates = resolveHosts(registry, { order: "build" })
        .filter((name) => byName.get(name).roles.includes("agent-seat"));
      if (candidates.length === 0) throw new Error("no enabled registry host carries the agent-seat role");
      process.stdout.write(byName.get(candidates[0]).ssh_alias);
    }).catch((err) => { process.stderr.write(`sandbox-provision: ${err.message}\n`); process.exit(3); });
  ')"
fi
[ -n "$HOST" ] || exit 3

SSH=(ssh -F "$HOME/.ssh/config" -o BatchMode=yes "$HOST")
# The sandbox reaches the receiver through podman's host mapping, so it needs the
# port sshd actually answers on. This client config is the value already proven to work.
SSH_PORT="$(ssh -F "$HOME/.ssh/config" -G "$HOST" | awk '/^port /{print $2; exit}')"
[[ "$SSH_PORT" =~ ^[0-9]+$ ]] || { echo "sandbox-provision: could not resolve the ssh port for $HOST" >&2; exit 2; }
echo "sandbox-provision: target $HOST (sshd port $SSH_PORT)"

STAGE="$(mktemp -d -t sandbox-provision.XXXXXX)"
trap 'rm -rf "$STAGE"' EXIT
mkdir -p "$STAGE/bin" "$STAGE/lib" "$STAGE/image-context"
cp "$MODULE_DIR"/host/bin/* "$STAGE/bin/"
cp "$MODULE_DIR"/host/lib/*.mjs "$STAGE/lib/"
cp "$MODULE_DIR"/lib/sandbox-payload.mjs "$STAGE/lib/"
cp -r "$MODULE_DIR"/image/. "$STAGE/image-context/"
mkdir -p "$STAGE/image-context/lib"
cp "$MODULE_DIR"/lib/sandbox-payload.mjs "$STAGE/image-context/lib/"
cp "$SHARED_PAIR_LIB" "$STAGE/image-context/lib/e2e-pair.sh"
chmod 0755 "$STAGE"/bin/* "$STAGE"/image-context/bin/*

ROOT='$HOME/.local/share/overdeck-sandbox'
"${SSH[@]}" "mkdir -p $ROOT/bin $ROOT/lib $ROOT/image-context $ROOT/secrets \
  \$HOME/sandbox/workspaces \$HOME/sandbox/home \$HOME/sandbox/store/pnpm \$HOME/sandbox/toolgap \
  && chmod 0700 $ROOT/secrets"

rsync -a --delete -e "ssh -F $HOME/.ssh/config -o BatchMode=yes" \
  "$STAGE/bin/" "$HOST:.local/share/overdeck-sandbox/bin/"
rsync -a --delete -e "ssh -F $HOME/.ssh/config -o BatchMode=yes" \
  "$STAGE/lib/" "$HOST:.local/share/overdeck-sandbox/lib/"
rsync -a --delete -e "ssh -F $HOME/.ssh/config -o BatchMode=yes" \
  "$STAGE/image-context/" "$HOST:.local/share/overdeck-sandbox/image-context/"

"${SSH[@]}" "SANDBOX_BUILD_FORCE='${FORCE_BUILD[*]-}' SANDBOX_SSH_PORT='$SSH_PORT' bash -s" <<'REMOTE'
set -euo pipefail
ROOT="$HOME/.local/share/overdeck-sandbox"
KEY="$ROOT/secrets/e2e_key"
MARKER="overdeck-sandbox-e2e"
AK="$HOME/.ssh/authorized_keys"

[ -f "$KEY" ] || ssh-keygen -q -t ed25519 -N '' -C "$MARKER" -f "$KEY"
chmod 0600 "$KEY"

printf '[host.containers.internal]:%s %s\n' "$SANDBOX_SSH_PORT" \
  "$(cut -d' ' -f1,2 /etc/ssh/ssh_host_ed25519_key.pub)" >"$ROOT/secrets/e2e_known_hosts"
chmod 0644 "$ROOT/secrets/e2e_known_hosts"
printf '%s\n' "$SANDBOX_SSH_PORT" >"$ROOT/e2e-port"

tr -d '\n' </etc/machine-id >"$ROOT/host-machine-id"

mkdir -p "$HOME/.ssh"
touch "$AK"
chmod 0600 "$AK"
LINE="restrict,command=\"$ROOT/bin/sandbox-e2e-receiver\" $(cat "$KEY.pub")"
TMP="$(mktemp)"
grep -v -F "$MARKER" "$AK" >"$TMP" || true
printf '%s\n' "$LINE" >>"$TMP"
chmod 0600 "$TMP"
mv "$TMP" "$AK"

"$ROOT/bin/sandbox-image-build" ${SANDBOX_BUILD_FORCE:-}
REMOTE

echo "sandbox-provision: $HOST provisioned"
