#!/usr/bin/env bash
# tests/opnsense-plugins/run-tests.sh
#
# Harness for scripts/opnsense-plugins.sh (D-129 edge plugin profile installer).
# OFFLINE -- no network, no creds, no edge. Drives --dry-run (which prints the
# intended opnsense-api.sh calls without touching the wire) + greps the source,
# PINNING the two lessons the script exists to encode: (1) install ONE plugin at
# a time and POLL between (the firmware-lock trap), (2) os-qemu-guest-agent is a
# package, NOT a working agent (the channel/enable/restart caveat). A careless
# edit reddens HERE, not on a live edge. ASCII + LF.
set -uo pipefail
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
S="$(cd "$HERE/../../scripts" && pwd)/opnsense-plugins.sh"
pass=0; fail=0
ok()  { pass=$((pass+1)); }
bad() { fail=$((fail+1)); echo "  FAIL: $1"; }

# dry-run still needs a host set (opnsense-api.sh checks it before the dry-run
# branch) -- use an invalid one; nothing must reach it.
export OPNSENSE_API_HOST="test.invalid"
export OPNSENSE_API_CREDS="/nonexistent/should-never-be-read"

# --- parse / usage ---
bash -n "$S" 2>/dev/null && ok || bad "does not parse (bash -n)"
bash "$S" >/dev/null 2>&1; [ $? -ne 0 ] && ok || bad "no-arg must be nonzero (usage)"
bash "$S" bogus-cmd >/dev/null 2>&1; [ $? -ne 0 ] && ok || bad "bad subcommand must be nonzero"

# --- list ---
L="$(bash "$S" list 2>&1)"
printf '%s' "$L" | grep -q 'vr1-edge' && ok || bad "list lost vr1-edge"
printf '%s' "$L" | grep -q 'os-qemu-guest-agent' && ok || bad "vr1-edge lost os-qemu-guest-agent"
printf '%s' "$L" | grep -q 'os-iperf' && ok || bad "vr1-edge lost os-iperf"
printf '%s' "$L" | grep -q 'metal-edge' && ok || bad "list lost metal-edge"
printf '%s' "$L" | grep -qE 'microcode|os-nut|os-apcupsd' && ok || bad "metal-edge lost its site-specific note"

# --- dry-run apply vr1-edge (stdout=calls, stderr=warnings) ---
OUT="$(bash "$S" --dry-run apply vr1-edge 2>/tmp/opl_err.$$)"; rc=$?
ERR="$(cat /tmp/opl_err.$$ 2>/dev/null)"; rm -f /tmp/opl_err.$$
[ "$rc" -eq 0 ] && ok || bad "--dry-run apply vr1-edge -> nonzero ($rc)"
printf '%s' "$OUT" | grep -q 'core/firmware/install/os-qemu-guest-agent' && ok || bad "dry-run missing qga install call"
printf '%s' "$OUT" | grep -q 'core/firmware/install/os-iperf' && ok || bad "dry-run missing iperf install call"

# --- DISCIPLINE 1: one-at-a-time + poll. qga install BEFORE iperf, poll BETWEEN. ---
nq="$(printf '%s\n' "$OUT" | grep -n 'install/os-qemu-guest-agent' | head -1 | cut -d: -f1)"
np="$(printf '%s\n' "$OUT" | grep -n 'poll'                        | head -1 | cut -d: -f1)"
ni="$(printf '%s\n' "$OUT" | grep -n 'install/os-iperf'            | head -1 | cut -d: -f1)"
if [ -n "$nq" ] && [ -n "$np" ] && [ -n "$ni" ] && [ "$nq" -lt "$np" ] && [ "$np" -lt "$ni" ]; then ok
else bad "not one-at-a-time: expected qga($nq) < poll($np) < iperf($ni)"; fi
grep -q 'upgradestatus' "$S" && ok || bad "source lost the upgradestatus poll (the firmware-lock fix)"

# --- DISCIPLINE 2: qemu-guest-agent honesty (channel/enable/restart caveat) ---
printf '%s' "$ERR" | grep -qiE 'channel|guest_agent' && ok || bad "no qga channel/enable warning emitted"

# --- unknown profile fails loud ---
bash "$S" --dry-run apply no-such-profile >/dev/null 2>&1; [ $? -ne 0 ] && ok || bad "unknown profile must be nonzero"

# --- no baked secret; delegates auth to opnsense-api.sh ---
grep -qiE '^[^#]*secret[[:space:]]*=' "$S" && bad "script bakes a secret (must delegate to opnsense-api.sh)" || ok
grep -q 'opnsense-api.sh' "$S" && ok || bad "does not delegate HTTP to opnsense-api.sh"

echo "opnsense-plugins: $pass passed, $fail failed"
[ "$fail" -eq 0 ]
