#!/usr/bin/env bash
#
# packaging/bootstrap-install.sh
#
# Idempotent bootstrap installer for rvc-ssh-agent, delivered to a device
# already running the legacy grpc-tty agent as the *source* of this script,
# not as a separately-hosted download: it travels inline as the exec
# payload of grpc-tty's `cli cmd <device_id> "$(cat packaging/bootstrap-install.sh)"`
# (see grpc-tty/cli/main.go: `cmd = strings.Join(os.Args[3:], "\n")`, sent
# as the Frame.Payload on the legacy DeviceControl/DeviceManager channel,
# right after the handshake). Only the release bundle below
# (.deb/.sha256/hub-ca.pem) needs separate HTTPS hosting, pulled from
# https://usetup.rvc.digital/rvc-ssh/.
#
# The legacy grpc-tty agent is left completely untouched -- this script only
# installs and starts rvc-ssh-agent alongside it (fallback posture).
#
# Required environment, set by whoever invokes `cli cmd` -- never sniffed
# on-device:
#   DEVICE_ID  - this device's rvc-ssh device id (becomes RVC_SSH_DEVICE_ID)
#   HUB_ADDR   - hub gRPC address (becomes RVC_SSH_HUB_ADDR)
#
# See README.md's "Fleet bootstrap from grpc-tty" section and DEVLOG.md's
# bootstrap design note for the full rationale (why an HTTPS bundle pull is
# acceptable here despite the self-update design's rejection of exactly
# that pattern for steady state, why the CA cert travels with VERSION, why
# DEVICE_ID/HUB_ADDR are caller-supplied).

set -euo pipefail

# Bare upstream version, bumped by hand per rollout wave -- never resolved
# as "latest" (see DEVLOG.md's bootstrap design note). The Debian package
# revision suffix ("-1") is appended below wherever the on-disk dpkg
# version string is compared or a bundle filename is built; confirmed to
# match `dpkg-query -W -f='${Version}'`'s actual output format for this
# package (e.g. "0.1.2-1", not "0.1.2"). Matches agent/Cargo.toml's current
# `version` as of this rollout wave -- bump both together.
VERSION="0.1.2"
PKG_REVISION="${VERSION}-1"

BASE_URL="https://usetup.rvc.digital/rvc-ssh/${VERSION}"
DEB_NAME="rvc-ssh-agent_${PKG_REVISION}_amd64.deb"
SHA_NAME="${DEB_NAME}.sha256"
CA_NAME="hub-ca.pem"

LOG_FILE="/var/log/rvc-ssh-bootstrap.log"
WORK_DIR="$(mktemp -d /tmp/rvc-ssh-bootstrap.XXXXXX)"

log() {
    printf '%s %s\n' "$(date -u +%Y-%m-%dT%H:%M:%SZ)" "$*" | tee -a "$LOG_FILE"
}

cleanup() {
    rm -rf "$WORK_DIR"
}
trap cleanup EXIT

if [ "$(id -u)" -ne 0 ]; then
    echo "bootstrap-install.sh must run as root (dpkg -i / systemctl / writes under /etc, /var/log)" >&2
    exit 1
fi

: "${DEVICE_ID:?DEVICE_ID must be set by the caller (maps to RVC_SSH_DEVICE_ID)}"
: "${HUB_ADDR:?HUB_ADDR must be set by the caller (maps to RVC_SSH_HUB_ADDR)}"

log "bootstrap-install starting: version=${PKG_REVISION} device_id=${DEVICE_ID} hub_addr=${HUB_ADDR}"

# --- idempotency check ------------------------------------------------------
# `dpkg-query -W` on a package that isn't installed yet exits non-zero and
# prints nothing to stdout; `|| true` keeps that from tripping `set -e`,
# and the resulting empty string just fails the comparison below, falling
# through to a fresh install (the correct behavior on a first run).
installed_version="$(dpkg-query -W -f='${Version}' rvc-ssh-agent 2>/dev/null || true)"

if [ "$installed_version" = "$PKG_REVISION" ]; then
    log "rvc-ssh-agent ${PKG_REVISION} already installed, skipping download/install"
else
    log "installing rvc-ssh-agent ${PKG_REVISION} (currently installed: ${installed_version:-none})"

    log "downloading bundle from ${BASE_URL}"
    curl -fsSL -o "${WORK_DIR}/${DEB_NAME}" "${BASE_URL}/${DEB_NAME}"
    curl -fsSL -o "${WORK_DIR}/${SHA_NAME}" "${BASE_URL}/${SHA_NAME}"
    curl -fsSL -o "${WORK_DIR}/${CA_NAME}" "${BASE_URL}/${CA_NAME}"

    log "verifying checksum"
    if ! (cd "$WORK_DIR" && sha256sum -c "$SHA_NAME"); then
        log "checksum verification failed, aborting"
        exit 1
    fi

    log "installing package via dpkg -i (Depends: empty -- static musl binary, no apt needed)"
    dpkg -i "${WORK_DIR}/${DEB_NAME}"

    # postinst (run by the dpkg -i above) already created /etc/rvc-ssh and
    # the rvc-ssh user/group, so both writes below land in an existing,
    # correctly-owned directory.
    log "installing hub CA cert to /etc/rvc-ssh/ca.pem"
    install -m 644 "${WORK_DIR}/${CA_NAME}" /etc/rvc-ssh/ca.pem

    log "writing /etc/rvc-ssh/agent.env"
    cat > /etc/rvc-ssh/agent.env <<EOF
RVC_SSH_HUB_ADDR=${HUB_ADDR}
RVC_SSH_CA_CERT=/etc/rvc-ssh/ca.pem
RVC_SSH_DEVICE_ID=${DEVICE_ID}
EOF
    chmod 640 /etc/rvc-ssh/agent.env
    chown root:rvc-ssh /etc/rvc-ssh/agent.env

    # The package's systemd-units metadata enables the unit (comes up on
    # boot) but deliberately does not start it (see agent/Cargo.toml) --
    # agent.env didn't exist with real values until the write above, so
    # this is the first point at which starting it is meaningful.
    log "starting rvc-ssh-agent"
    systemctl start rvc-ssh-agent
fi

# Whether freshly installed above or already present, make sure the service
# is actually up: an already-installed-but-stopped unit (crashed, manually
# stopped) must not be silently left down just because there was nothing to
# reinstall.
if ! systemctl is-active --quiet rvc-ssh-agent; then
    log "rvc-ssh-agent not active, starting"
    systemctl start rvc-ssh-agent
fi

log "bootstrap-install complete: rvc-ssh-agent $(systemctl is-active rvc-ssh-agent)"
