#!/bin/bash
# Vexor naemon boot self-heal guard.
#
# Installed as the naemon ExecStartPre (with the systemd '+' prefix so it runs
# as root regardless of the unit's User=naemon). If the on-disk Naemon config
# fails verification at start/boot, this restores the last-known-good config
# snapshot that vexor-api maintains under /var/lib/vexor/naemon-lkg so a single
# bad saved check can never turn a reboot into a permanently-down monitor.
#
# Outcomes:
#   * config already valid                  -> exit 0 (naemon starts normally)
#   * invalid, restored & now valid         -> drop a marker for vexor-api to
#                                              surface as a user event, exit 0
#   * invalid and unrecoverable / no LKG    -> exit 1 (fail start, as stock)
set -u

NAEMON=/usr/bin/naemon
CFG=/etc/naemon/naemon.cfg
LKG=/var/lib/vexor/naemon-lkg
TREE="$LKG/tree"
OUT=/run/vexor-naemon-startguard.out

# naemon refuses to run -v as root; verify as the naemon user.
verify() { runuser -u naemon -- "$NAEMON" -v "$CFG" >"$OUT" 2>&1; }

if verify; then
    exit 0
fi

# Preserve the ORIGINAL failure output so the user-facing notice names the real
# problem, not the post-restore (clean) verify result.
cp -f "$OUT" "$OUT.orig" 2>/dev/null || true

# Config is invalid. Roll back to the last-known-good snapshot if we have one.
if [ ! -f "$LKG/meta.json" ] || [ ! -d "$TREE" ]; then
    echo "vexor-startguard: config invalid and no LKG snapshot to restore" >&2
    cat "$OUT" >&2 2>/dev/null || true
    exit 1
fi

restore_dir() {
    local live="$1"; local mirror="$TREE$live"
    [ -d "$mirror" ] || return 0
    shopt -s nullglob
    local f b
    for f in "$mirror"/*.cfg; do cp -f "$f" "$live/" 2>/dev/null || true; done
    for f in "$live"/*.cfg; do
        b=$(basename "$f")
        [ -e "$mirror/$b" ] || rm -f "$f" 2>/dev/null || true
    done
    shopt -u nullglob
}
restore_file() {
    local live="$1"; local mirror="$TREE$live"
    if [ -f "$mirror" ]; then
        cp -f "$mirror" "$live" 2>/dev/null || true
    elif [ -f "$live" ]; then
        rm -f "$live" 2>/dev/null || true
    fi
}

restore_dir  /etc/naemon/vexor/hosts
restore_dir  /etc/naemon/vexor/services
restore_dir  /etc/naemon/vexor/commands
restore_dir  /etc/naemon/vexor/templates
restore_file /etc/naemon/vexor/_servicedeps.cfg
restore_file /etc/naemon/vexor/op5-commands.cfg
restore_file /etc/naemon/conf.d/vexor-custom-commands.cfg
restore_file /etc/naemon/conf.d/vexor_timeperiods.cfg

if verify; then
    echo "vexor-startguard: restored last-known-good config; naemon will start" >&2
    ERR=$(grep -iE 'error|warning' "$OUT.orig" 2>/dev/null | head -n 12)
    /usr/bin/python3 - "$LKG/boot-restored.json" "$ERR" <<'PY' 2>/dev/null || true
import json, os, sys, time
p = sys.argv[1]
err = sys.argv[2] if len(sys.argv) > 2 else ""
tmp = p + ".tmp"
with open(tmp, "w") as fh:
    fh.write(json.dumps({"ts": int(time.time()), "errors": err[:4000]}))
os.replace(tmp, p)
os.chmod(p, 0o644)
PY
    exit 0
fi

echo "vexor-startguard: config still invalid after restore; failing start" >&2
cat "$OUT" >&2 2>/dev/null || true
exit 1
