#!/bin/sh
# Enable the opt-in MCP link to "mother".
#
# Direction: this agent's Pi calls mother's tools. colibri-mcp dials OUT to
# mother over SSH-stdio and proxies mother's MCP tools to the Pi via its
# external-call path. Off by default; this script turns it on.
#
# Key exchange is vault-mediated: this node publishes its colibri pubkey to
# Vaultwarden (item `hive-pubkey-<hostname>`), and the mother node's
# `mother-sync-hive-keys` rebuilds its authorized_keys from those items. The
# pubkey is also printed as a manual fallback.
#
# The colibri daemon (and the Pi it spawns) run as the `colibri` user, so the
# outbound SSH uses an identity in the colibri home (/var/db/colibri/.ssh).

set -eu

PROVIDER_ENV="/usr/local/etc/colibri/provider.env"
EXTERNAL_MCP="/usr/local/etc/colibri/external-mcp.json"
COLIBRI_HOME="/var/db/colibri"
SSH_KEY="${COLIBRI_HOME}/.ssh/id_ed25519"

finish() {
    echo ""
    echo "Press Enter to close."
    read -r _
    exit "${1:-0}"
}

have() {
    command -v "$1" >/dev/null 2>&1
}

# Publish the colibri pubkey to Vaultwarden as hive-pubkey-<hostname> so a
# mother node can authorize it automatically (mother-sync-hive-keys). bw runs as
# root so it can read the BW_* bootstrap creds from provider.env; the pubkey is
# public, so passing it through the environment is fine. Returns non-zero on any
# failure so the caller can fall back to the printed key.
publish_pubkey() {
    mdo -u root env \
        HIVE_ITEM="hive-pubkey-$(hostname)" \
        HIVE_PUB="$1" \
        PROVIDER_ENV="$PROVIDER_ENV" \
        sh -s <<'PUBLISH'
set -eu
command -v bw >/dev/null 2>&1 || { echo "bw not found" >&2; exit 4; }
. "$PROVIDER_ENV"
[ -n "${BW_CLIENTID:-}" ] && [ -n "${BW_CLIENTSECRET:-}" ] && [ -n "${BW_PASSWORD:-}" ] ||
    { echo "provider.env lacks BW_* creds" >&2; exit 1; }
bw logout >/dev/null 2>&1 || true
bw login --apikey >/dev/null 2>&1 || true
SESS="$(bw unlock --passwordenv BW_PASSWORD --raw 2>/dev/null)" ||
    { echo "bw unlock failed" >&2; exit 1; }
[ -n "$SESS" ] || { echo "empty bw session" >&2; exit 1; }
bw sync --session "$SESS" >/dev/null 2>&1 || true
ITEM_ID="$(bw list items --search "$HIVE_ITEM" --session "$SESS" 2>/dev/null |
    python3 -c "import sys,json,os
n=os.environ['HIVE_ITEM']
try: d=json.load(sys.stdin)
except Exception: d=[]
print(next((i['id'] for i in d if i.get('name')==n), ''))")"
if [ -n "$ITEM_ID" ]; then
    bw get item "$ITEM_ID" --session "$SESS" | python3 -c "import sys,json,os,base64
d=json.load(sys.stdin); d['notes']=os.environ['HIVE_PUB']
sys.stdout.write(base64.b64encode(json.dumps(d).encode()).decode())" |
        bw edit item "$ITEM_ID" --session "$SESS" >/dev/null
else
    python3 -c "import json,os,base64
print(base64.b64encode(json.dumps({'type':2,'name':os.environ['HIVE_ITEM'],'notes':os.environ['HIVE_PUB']}).encode()).decode())" |
        bw create item --session "$SESS" >/dev/null
fi
bw lock >/dev/null 2>&1 || true
PUBLISH
}

if ! have mdo; then
    echo "ERROR: mdo is required to update the colibri service configuration."
    finish 1
fi

echo "========================================"
echo "  Clawdie — Enable Mother Link"
echo "========================================"
echo ""

# 0. Mother's reachable address + remote MCP command.
printf "  Mother SSH target (user@tailscale-ip-or-name): "
read -r MOTHER_HOST
if [ -z "${MOTHER_HOST:-}" ]; then
    echo "  Cancelled: no mother target entered."
    finish 0
fi
printf "  Mother MCP command [colibri-mcp]: "
read -r MOTHER_CMD
[ -n "${MOTHER_CMD:-}" ] || MOTHER_CMD="colibri-mcp"

# 1. Ensure the colibri service account has an SSH key for the outbound link.
echo ""
echo "[1/5] Ensuring colibri SSH identity..."
mdo -u root sh -c '
    set -eu
    home="$1"; key="$2"
    install -d -o colibri -g colibri -m 0700 "${home}/.ssh"
    if [ ! -f "$key" ]; then
        ssh-keygen -t ed25519 -N "" -f "$key" -C "colibri@$(hostname)" >/dev/null
        chown colibri:colibri "$key" "${key}.pub"
        chmod 0600 "$key"; chmod 0644 "${key}.pub"
    fi
' sh "$COLIBRI_HOME" "$SSH_KEY"

# 2. Publish the pubkey to Vaultwarden so mother can authorize it.
echo "[2/5] Publishing pubkey to Vaultwarden..."
PUBKEY="$(mdo -u root cat "${SSH_KEY}.pub" 2>/dev/null || true)"
if [ -z "$PUBKEY" ]; then
    echo "       WARNING: could not read ${SSH_KEY}.pub; skipping publish."
elif have bw && publish_pubkey "$PUBKEY"; then
    echo "       Published as hive-pubkey-$(hostname); mother will pick it up on sync."
else
    echo "       NOTE: vault publish unavailable; authorize the printed key manually."
fi

# 3. Merge the mother entry into the external MCP registry. Use jq so existing
# server entries are preserved (not overwritten), and write atomically.
echo "[3/5] Registering mother in ${EXTERNAL_MCP}..."
if ! have jq; then
    echo "       ERROR: jq is required to merge the mother entry into ${EXTERNAL_MCP}."
    finish 1
fi
existing="$(mdo -u root cat "$EXTERNAL_MCP" 2>/dev/null || echo '{}')"
[ -n "$existing" ] || existing='{}'
printf '%s\n' "$existing" |
    jq --arg host "$MOTHER_HOST" --arg cmd "$MOTHER_CMD" --arg key "$SSH_KEY" \
        '.servers = ((.servers // {}) + {mother: {command: "ssh", args: ["-i", $key, "-o", "BatchMode=yes", "-o", "StrictHostKeyChecking=accept-new", $host, $cmd], env: {}}})' |
    mdo -u root sh -c '
        set -eu
        f="$1"
        tmp="$(mktemp "$(dirname "$f")/external-mcp.XXXXXX")"
        cat >"$tmp"
        chmod 0644 "$tmp"
        mv "$tmp" "$f"
    ' sh "$EXTERNAL_MCP"

# 4. Allow external MCP calls: upsert COLIBRI_MCP_EXTERNAL_CALL=1 into provider.env.
echo "[4/5] Enabling external MCP calls..."
mdo -u root sh -c '
    set -eu
    f="$1"
    tmp="$(mktemp "$(dirname "$f")/.provider.env.XXXXXX")"
    grep -v "^COLIBRI_MCP_EXTERNAL_CALL=" "$f" >"$tmp" 2>/dev/null || :
    printf "COLIBRI_MCP_EXTERNAL_CALL=\"1\"\n" >>"$tmp"
    chmod 0600 "$tmp"
    mv "$tmp" "$f"
' sh "$PROVIDER_ENV"

# 5. Restart the daemon so the Pi inherits the new env + registry.
echo "[5/5] Restarting colibri daemon..."
mdo -u root service colibri_daemon restart >/dev/null 2>&1 ||
    echo "       WARNING: restart failed; run: mdo -u root service colibri_daemon restart"

echo ""
echo "Mother link configured. If the vault publish succeeded, mother authorizes"
echo "this key automatically on its next sync. Manual fallback — add to mother's"
echo "authorized_keys, restricted to the MCP command:"
echo ""
echo "  command=\"${MOTHER_CMD}\",restrict,no-pty $(mdo -u root cat "${SSH_KEY}.pub" 2>/dev/null || echo '<pubkey unavailable>')"
echo ""
echo "Once authorized on mother, the Pi can call mother's tools via colibri-mcp."
finish 0
