#!/bin/sh
# Put the host back on the last version that worked.
#
# novox/hq ADR 0059. This runs when nox-mesh-host will not start, so it shares no code with it
# and calls none of it: a binary that cannot start cannot be its own recovery. POSIX sh, no
# bashisms, nothing that has to be installed.
#
# It is deliberately dull. Everything it does is one of: read a file, run the package manager,
# ask the service manager to try again.
set -eu

STATE_DIR="${MESH_HOST_STATE_DIR:-/var/lib/mesh-host}"
PKG_CACHE="${MESH_HOST_PKG_CACHE:-/var/cache/pacman/pkg}"
PACKAGE="${MESH_HOST_PACKAGE:-nox-mesh-host}"

KNOWN_GOOD="$STATE_DIR/known-good"
ATTEMPTED="$STATE_DIR/rollback-attempted"

say() { echo "nox-mesh-host-rollback: $*" >&2; }

# Roll back once. A second failure is a different diagnosis: the previously working binary also
# does not run, so the binary is not the problem — the machine is. Rolling back again would flap
# between two versions forever and bury the actual cause under a loop.
if [ -e "$ATTEMPTED" ]; then
	say "already rolled back once, to $(cat "$ATTEMPTED" 2>/dev/null || echo unknown)."
	say "the previous version also failed to start, so this is the machine and not the binary."
	say "not rolling back again. this node needs a person."
	exit 0
fi

# A machine whose host never completed a reconcile has no version to go back to. That is a real
# state rather than a fault: the node was never working, so the failure belongs to the
# installation. Guessing a version here is how a recovery becomes a second fault.
if [ ! -s "$KNOWN_GOOD" ]; then
	say "no known-good version recorded — this host has never completed a reconcile."
	say "there is nothing to roll back to. this is an installation failure, not an upgrade one."
	exit 0
fi

VERSION="$(tr -d '[:space:]' < "$KNOWN_GOOD")"
if [ -z "$VERSION" ]; then
	say "known-good is empty. refusing to guess."
	exit 0
fi

PKG="$(ls "$PKG_CACHE"/"$PACKAGE"-"$VERSION"-*.pkg.tar.* 2>/dev/null | head -n 1 || true)"
if [ -z "$PKG" ]; then
	say "known-good is $VERSION and no package for it is in $PKG_CACHE."
	say "the cache was cleaned, or that version was never installed from here."
	say "cannot roll back. this node needs a person."
	exit 1
fi

say "rolling back to $VERSION ($PKG)"
printf '%s\n' "$VERSION" > "$ATTEMPTED"

if ! pacman -U --noconfirm "$PKG"; then
	say "the package manager refused to install $PKG."
	exit 1
fi

# Deliberately does NOT start anything. The launcher called this and will exec the host next,
# so starting it here would run two. novox/hq ADR 0061 moved that responsibility; this script
# installs a version and says so, and nothing else.
say "rolled back to $VERSION. the launcher will start it."
