#!/bin/sh
# Stage prebuilt Colibri FreeBSD service artifacts into an ISO/image root.
#
# This script does not build Colibri. Build or provide artifacts first:
#   (cd /home/clawdie/ai/colibri && cargo build --workspace --release)
#
# Usage:
#   COLIBRI_REPO=/home/clawdie/ai/colibri scripts/stage-colibri-iso.sh /path/to/image-root
#   COLIBRI_ARTIFACT_DIR=/path/to/release scripts/stage-colibri-iso.sh /path/to/image-root

set -eu

if [ "${1:-}" = "" ]; then
    echo "usage: $0 DESTDIR" >&2
    exit 64
fi

DESTDIR=$1
SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
REPO_ROOT=$(CDPATH= cd -- "${SCRIPT_DIR}/.." && pwd)
COLIBRI_REPO=${COLIBRI_REPO:-"/home/clawdie/ai/colibri"}
COLIBRI_ARTIFACT_DIR=${COLIBRI_ARTIFACT_DIR:-"${COLIBRI_REPO}/target/release"}
COLIBRI_STAGE_ENABLE=${COLIBRI_STAGE_ENABLE:-YES}
COLIBRI_STAGE_INCLUDE_TUI=${COLIBRI_STAGE_INCLUDE_TUI:-1}
COLIBRI_STAGE_TEST_AGENT=${COLIBRI_STAGE_TEST_AGENT:-NO}
COLIBRI_COST_MODE=${COLIBRI_COST_MODE:-smart}

BIN_DIR="${DESTDIR}/usr/local/bin"
RC_DIR="${DESTDIR}/usr/local/etc/rc.d"
ETC_DIR="${DESTDIR}/usr/local/etc/colibri"
DB_DIR="${DESTDIR}/var/db/colibri"
RUN_DIR="${DESTDIR}/var/run/colibri"
LOG_DIR="${DESTDIR}/var/log/colibri"
NEWSYSLOG_DIR="${DESTDIR}/usr/local/etc/newsyslog.conf.d"
RC_SOURCE="${COLIBRI_REPO}/packaging/freebsd/colibri_daemon.in"
NEWSYSLOG_SOURCE="${COLIBRI_REPO}/packaging/freebsd/newsyslog-colibri.conf"

require_file() {
    if [ ! -f "$1" ]; then
        echo "missing required Colibri artifact: $1" >&2
        exit 66
    fi
}

require_exec() {
    if [ ! -x "$1" ]; then
        echo "missing executable Colibri artifact: $1" >&2
        echo "hint: (cd ${COLIBRI_REPO} && cargo build --workspace --release)" >&2
        exit 66
    fi
}

copy_bin() {
    require_exec "${COLIBRI_ARTIFACT_DIR}/$1"
    install -m 0555 "${COLIBRI_ARTIFACT_DIR}/$1" "${BIN_DIR}/$1"
}

require_file "${RC_SOURCE}"
require_file "${NEWSYSLOG_SOURCE}"
mkdir -p "${BIN_DIR}" "${RC_DIR}" "${ETC_DIR}" "${NEWSYSLOG_DIR}" "${DB_DIR}" "${RUN_DIR}" "${LOG_DIR}"

copy_bin colibri-daemon
copy_bin colibri
copy_bin colibri-mcp

if [ "${COLIBRI_STAGE_TEST_AGENT}" = "YES" ]; then
    copy_bin colibri-test-agent
fi

if [ "${COLIBRI_STAGE_INCLUDE_TUI}" != "0" ] && [ -x "${COLIBRI_ARTIFACT_DIR}/colibri-tui" ]; then
    copy_bin colibri-tui
fi

install -m 0555 "${RC_SOURCE}" "${RC_DIR}/colibri_daemon"
install -m 0644 "${NEWSYSLOG_SOURCE}" "${NEWSYSLOG_DIR}/colibri.conf"

if ! grep -q '^command="/usr/sbin/daemon"' "${RC_DIR}/colibri_daemon" || \
   ! grep -q -- '-o .*colibri_daemon_binary' "${RC_DIR}/colibri_daemon" || \
   ! grep -q 'colibri_daemon_provider_env' "${RC_DIR}/colibri_daemon" || \
   ! grep -q 'colibri_daemon_cost_mode' "${RC_DIR}/colibri_daemon" || \
   ! grep -q 'rm -f "${pidfile}" "${supervisor_pidfile}"' "${RC_DIR}/colibri_daemon" || \
   ! grep -q 'export PATH="/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"' "${RC_DIR}/colibri_daemon"; then
    echo "ERROR: staged colibri_daemon rc.d script is missing required live USB supervision hooks" >&2
    echo "       Update COLIBRI_REPO (${COLIBRI_REPO}) before building." >&2
    exit 66
fi

if grep -q -- '-u \${colibri_daemon_user}' "${RC_DIR}/colibri_daemon"; then
    echo "ERROR: staged colibri_daemon rc.d script has unsupported live USB command wiring" >&2
    echo "       Update COLIBRI_REPO (${COLIBRI_REPO}) before building." >&2
    exit 66
fi

cat > "${ETC_DIR}/rc.conf.sample" <<EOF
# Colibri control plane service defaults for the Clawdie ISO.
# Merge into /etc/rc.conf or /etc/rc.conf.d/colibri_daemon.
colibri_daemon_enable="${COLIBRI_STAGE_ENABLE}"
colibri_daemon_user="colibri"
colibri_daemon_group="colibri"
colibri_daemon_data_dir="/var/db/colibri"
colibri_daemon_run_dir="/var/run/colibri"
colibri_daemon_socket="/var/run/colibri/colibri.sock"
colibri_daemon_db_path="/var/db/colibri/colibri.sqlite"
colibri_daemon_logfile="/var/log/colibri/daemon.log"
colibri_daemon_provider_env="/usr/local/etc/colibri/provider.env"
colibri_daemon_host="\$(/bin/hostname)"
colibri_daemon_cost_mode="${COLIBRI_COST_MODE}"
colibri_daemon_require_secured="YES"
EOF

cat > "${ETC_DIR}/provider.env" <<'EOF'
# Non-secret Clawdie defaults. Keep this file mode 0600: operators may add
# provider keys and Vaultwarden bootstrap credentials here after boot.
VAULT_SERVER="https://vault.smilepowered.org"
BW_SERVER="https://vault.smilepowered.org"

# Auto-spawn one zot agent on daemon startup once a DeepSeek key is present
# (the Operator Image OOTB flow). The daemon sources this file, so the spawned
# agent inherits the provider keys set here.
COLIBRI_AUTOSPAWN="YES"
# zot is the default harness — pi is available but zot has richer provider
# support (DeepSeek native, OpenRouter, ~25 providers) and a built-in
# Telegram bot mode. Set COLIBRI_AUTOSPAWN_BINARY=pi to switch back.
COLIBRI_AUTOSPAWN_BINARY="zot"
# RPC prompt sent to the autospawned zot agent on first boot.
# zot is in RPC mode and blocks on stdin; this prompt kicks it off.
# The daemon collected hw-probe at boot (CLAWDIE_HW_PROFILE); the seed
# importer installed AGENTS.md with operational context; the provider
# keys are either baked or seeded.  The agent's first job: register
# this node with mother, then report its assigned capabilities.
COLIBRI_AUTOSPAWN_RPC_PROMPT="You just booted. Read CLAWDIE_HW_PROFILE from your environment and call node_register on the mother MCP server with that JSON payload. Then report what capabilities mother assigned and what tasks are available. Your AGENTS.md context explains the verbs and infrastructure."
# Telegram bot token — set this to enable the bot channel (@your_bot).
# Leave blank to use CLI/TUI/Dashboard channels only.
# TELEGRAM_BOT_TOKEN=""

# Enable external MCP server calls so the daemon can connect to mother
# (OSA) for hive-node registration. The SSH key comes from the seed
# partition; without it the connection fails gracefully.
COLIBRI_MCP_EXTERNAL_CALL="1"
EOF
chmod 0600 "${ETC_DIR}/provider.env" 2>/dev/null || true

# External MCP server registry. The mother server entry is pre-configured so
# the daemon (running as user colibri) connects to mother OOTB via the
# "mother" SSH config alias. The SSH key, known_hosts, and Host definition
# for "mother" come from the CLAWDIESEED seed partition and are installed
# to /var/db/colibri/.ssh/ by the importer (see clawdie-live-seed.README.txt).
# Without the seed the connection fails gracefully — the daemon keeps running.
# Path matches colibri-mcp's default COLIBRI_MCP_EXTERNAL_CONFIG.
cat > "${ETC_DIR}/external-mcp.json" <<'EOF'
{
  "servers": {
    "mother": {
      "command": "ssh",
      "args": [
        "-i", "/var/db/colibri/.ssh/mother-mcp",
        "-F", "/var/db/colibri/.ssh/config",
        "-o", "StrictHostKeyChecking=accept-new",
        "mother"
      ],
      "env": {}
    }
  }
}
EOF
chmod 0644 "${ETC_DIR}/external-mcp.json" 2>/dev/null || true

cat > "${ETC_DIR}/provider.env.sample" <<'EOF'
# Optional provider keys and Vaultwarden bootstrap credentials for
# colibri_daemon. The ISO already stages provider.env with the non-secret
# Clawdie Vaultwarden endpoint; copy values from here into provider.env,
# keep it mode 0600, then restart the service.
#
# Baked non-secret defaults:
VAULT_SERVER="https://vault.smilepowered.org"
BW_SERVER="https://vault.smilepowered.org"
#
# Vaultwarden bootstrap credentials (secret; operator-provided):
# BW_CLIENTID="..."
# BW_CLIENTSECRET="..."
# BW_PASSWORD="..."
#
# Direct provider keys (optional when Vaultwarden provisioning is used):
# DEEPSEEK_API_KEY="sk-..."
# OPENROUTER_API_KEY="sk-or-..."
# ANTHROPIC_API_KEY="sk-ant-..."
#
# Optional endpoints/models:
# DEEPSEEK_ENDPOINT="https://api.deepseek.com/chat/completions"
# DEEPSEEK_MODEL="deepseek-v4-pro"
#
# Telegram bot (optional):
# TELEGRAM_BOT_TOKEN="123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11"
#
# Behavior toggles (non-secret):
# COLIBRI_AUTOSPAWN="YES"            # auto-spawn one agent on daemon startup
# COLIBRI_AUTOSPAWN_BINARY="zot"              # agent harness: zot (default) | pi
# COLIBRI_AUTOSPAWN_ARGS="rpc"         # agent argv; default is harness-derived
#                                      # (zot -> "rpc", pi -> "--mode json")
# COLIBRI_MCP_EXTERNAL_CALL="1"        # allow agent (via colibri-mcp) to call
#                                      # external MCP servers; set by
#                                      # clawdie-enable-mother
EOF

cat > "${ETC_DIR}/README.iso" <<'EOF'
Colibri ISO staging notes
=========================

The ISO build creates the colibri user/group and stages the rc.d service.
The colibri-daemon runs under daemon(8) supervision and is enabled at boot.
If the daemon fails, it restarts automatically without blocking SDDM/XFCE.
Provider keys are optional and live in /usr/local/etc/colibri/provider.env.
Keep that file root-owned and mode 0600, then restart colibri_daemon.

Runtime validation:

  service colibri_daemon start
  colibri status
  colibri create-task --title "iso check"
  colibri list-tasks --status queued
  colibri-mcp tools
  COLIBRI_MCP_WRITE=1 colibri-mcp tools   # trusted write-capable MCP profile
  service colibri_daemon stop
EOF

chmod 0755 "${DB_DIR}" "${RUN_DIR}" "${LOG_DIR}"

cat <<EOF
Staged Colibri into ${DESTDIR}
  artifacts: ${COLIBRI_ARTIFACT_DIR}
  rc.d     : ${RC_SOURCE}
  enable   : ${COLIBRI_STAGE_ENABLE}
  cost     : ${COLIBRI_COST_MODE}
  test bin : ${COLIBRI_STAGE_TEST_AGENT}
EOF
