#!/usr/bin/env bash
# tests/site-baseleg/run-tests.sh
#
# Harness for scripts/site-baseleg.sh (D-126 amendment). OFFLINE -- touches no
# libvirt, no systemd, no network, no root. Renders the unit and greps it, and
# drives the error paths. It PINS the discipline-relevant shape: NO baked bridge
# (virbrN is discovered, PATTERN-1), idempotent mutation, root-guarded apply,
# no baked secret, no inferred DC IP. A careless edit reddens HERE, not at boot.
# ASCII + LF.
set -uo pipefail
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
S="$(cd "$HERE/../../scripts" && pwd)/site-baseleg.sh"
pass=0; fail=0
ok()  { pass=$((pass+1)); }
bad() { fail=$((fail+1)); echo "  FAIL: $1"; }

command -v bash >/dev/null 2>&1 || { echo "FAIL: bash required"; exit 1; }

# --- parse / help / list ---
bash -n "$S" 2>/dev/null && ok || bad "does not parse (bash -n)"
bash "$S" --help >/dev/null 2>&1 && ok || bad "--help -> nonzero"
bash "$S" >/dev/null 2>&1; [ $? -ne 0 ] && ok || bad "no-arg must be nonzero (prints usage)"
bash "$S" list 2>&1 | grep -q 'office1' && ok || bad "list lost office1"

R="$(bash "$S" render office1 2>&1)"

# --- unit shape ---
printf '%s' "$R" | grep -q 'Description=D-126' && ok || bad "unit not tagged D-126"
printf '%s' "$R" | grep -q '^After=libvirtd.service' && ok || bad "lost After=libvirtd (the race fix)"
printf '%s' "$R" | grep -q '^Type=oneshot' && ok || bad "not a oneshot"
printf '%s' "$R" | grep -q '^RemainAfterExit=yes' && ok || bad "lost RemainAfterExit"
printf '%s' "$R" | grep -qE '^ExecStart=/[^ ]*/site-baseleg.sh apply office1$' && ok || bad "ExecStart is not an absolute self-call to 'apply office1'"
printf '%s' "$R" | grep -q '^WantedBy=multi-user.target' && ok || bad "lost system-target install"

# --- PATTERN-1: NO baked drifting bridge id in the rendered unit ---
printf '%s' "$R" | grep -q 'virbr' && bad "unit bakes a virbrN (must discover from net name)" || ok
# discovery is via the stable network name, at run time
grep -q 'virsh net-info' "$S" && ok || bad "bridge not discovered via virsh net-info"
printf '%s' "$R" | grep -q 'office1-local' && ok || bad "unit lost the stable net name office1-local"

# --- measured / as-built values present (hard rule 2) ---
bash "$S" list 2>&1 | grep -q 'office1-local|10.10.0.10/24|10.10.1.0/24|10.10.0.20' && ok \
  || bad "office1 leg row drifted from as-built (net|host|route|gw)"

# --- idempotency: guarded add + route replace ---
grep -q 'ip route replace' "$S" && ok || bad "route is not idempotent (use ip route replace)"
grep -qE 'grep -qw "\$HOST_CIDR"' "$S" && ok || bad "address add is not guarded (idempotency)"

# --- apply MUTATES and is root-guarded; check/render/list are read-only ---
grep -qE 'apply needs root' "$S" && ok || bad "apply not root-guarded"
# non-root apply must refuse (we run tests as non-root) and must NOT touch libvirt first
if [ "$(id -u)" -ne 0 ]; then
  out="$(bash "$S" apply office1 2>&1)"; rc=$?
  [ $rc -ne 0 ] && printf '%s' "$out" | grep -q 'needs root' && ok || bad "non-root apply did not refuse cleanly"
else
  ok  # running as root in CI: skip the refuse-path assertion
fi

# --- error paths (capture-then-grep: die exits nonzero, which pipefail would
#     otherwise propagate through the pipe even when grep matches) ---
e1="$(bash "$S" render 2>&1)";       printf '%s' "$e1" | grep -q 'render needs a <site>' && ok || bad "render w/o site not rejected"
e2="$(bash "$S" render bogus 2>&1)"; printf '%s' "$e2" | grep -q "unknown site 'bogus'" && ok || bad "unknown site not rejected"
e3="$(bash "$S" boguscmd 2>&1)";     printf '%s' "$e3" | grep -q "unknown command" && ok || bad "unknown command not rejected"

# --- SECRETS: nothing key/credential-shaped is baked ---
grep -qE '\-creds/|BEGIN [A-Z ]*PRIVATE KEY|api\.token|authkey' "$S" && bad "script bakes a secret path/material" || ok
grep -q 'NO SECRETS' "$S" && ok || bad "lost the no-secrets contract comment"

# --- NO INFERRED VALUE: no unmeasured DC IP in an ACTIVE leg row ---
# active rows are the declare -A body lines that are NOT commented; DC supernets
# (10.12., 172.31.) must not appear un-commented until measured.
active="$(sed -n '/declare -A LEGS=(/,/^)/p' "$S" | grep -vE '^[[:space:]]*#')"
printf '%s' "$active" | grep -qE '10\.12\.|172\.31\.' && bad "an ACTIVE leg row carries an unmeasured DC supernet" || ok

echo "site-baseleg: ${pass} passed, ${fail} failed"
[ "$fail" -eq 0 ]
