#!/usr/bin/env bash
# tests/site-tailscale/run-tests.sh -- offline harness for scripts/site-tailscale.sh.
# Fakes `tailscale` (status --json / up / version) and `ip`; real python3 for jget. NO network,
# mutates nothing outside mktemp. Proves each exit path can FIRE (a new assertion is decoration
# until it has a failing-direction fixture):
#   check-happy    -> 0   (Running + route approved + tagged + .7 leg)
#   check-notrun   -> 1   (BackendState != Running)
#   check-noroute  -> 1   (metal-admin CIDR not in approved PrimaryRoutes)
#   check-notag    -> 1   (node not tagged)
#   check-noleg    -> 1   (no .7 metal-admin leg on the host)
#   install-nokey  -> 4   (no tagged pre-auth key)
#   install-noTS   -> 4   (tailscale binary absent)
#   install-upfail -> 4   (tailscale up rejected)
#   install-happy  -> 0   (up ok + check green)
#   badmode/badsite/noargs -> 2
#   site-table rows carry MEASURED tags (hard rule 2)
#   dc1 site resolves its own CIDR (10.12.68.0/22), not dc0's
# Exit: 0 all pass | 1 any case failed.  ASCII + LF.
set -uo pipefail
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO="$(cd "$HERE/../.." && pwd)"
SUT="$REPO/scripts/site-tailscale.sh"
TMP="$(mktemp -d)"; trap 'rm -rf "$TMP"' EXIT
PASS=0; FAIL=0
BIN="$TMP/bin"; mkdir -p "$BIN"

# ---- fake tailscale --------------------------------------------------------
cat > "$BIN/tailscale" <<'FB'
#!/usr/bin/env bash
mode="${TS_FAKE_MODE:-happy}"; cidr="${TS_FAKE_CIDR:-10.12.8.0/22}"
case "$1" in
  version) echo "1.98.9"; exit 0;;
  up) [ "$mode" = upfail ] && exit 1; exit 0;;
  status)
     # $2 == --json
     st='"Running"'; routes="[\"$cidr\"]"; tags='["tag:subnet-router"]'
     case "$mode" in
       notrun)  st='"Stopped"';;
       noroute) routes='[]';;
       notag)   tags='[]';;
     esac
     printf '{"BackendState":%s,"Self":{"PrimaryRoutes":%s,"Tags":%s}}\n' "$st" "$routes" "$tags"
     exit 0;;
  *) exit 0;;
esac
FB
chmod +x "$BIN/tailscale"

# ---- fake ip (own_leg_matches) --------------------------------------------
cat > "$BIN/ip" <<'FB'
#!/usr/bin/env bash
# emit a .7 metal-admin leg unless TS_FAKE_MODE=noleg
[ "${TS_FAKE_MODE:-}" = noleg ] && { echo "1: lo inet 127.0.0.1/8 scope host lo"; exit 0; }
echo "2: enp1s0 inet ${TS_FAKE_LEG:-10.12.8.7}/22 scope global enp1s0"
exit 0
FB
chmod +x "$BIN/ip"

run(){ # <name> <expected-exit> <mode> <args...>
  local name="$1" exp="$2" mode="$3"; shift 3
  local out code
  out="$(PATH="$BIN:$PATH" TAILSCALE="$BIN/tailscale" TS_FAKE_MODE="$mode" \
         TS_AUTHKEY="${CASE_AUTHKEY:-}" TAILSCALE="${CASE_TS:-$BIN/tailscale}" \
         bash "$SUT" "$@" 2>&1)"; code=$?
  if [ "$code" -eq "$exp" ]; then PASS=$((PASS+1)); echo "PASS: $name (exit $code)"
  else FAIL=$((FAIL+1)); echo "FAIL: $name (got $code want $exp)"; echo "$out" | sed 's/^/    /'; fi
}

echo "=== site-tailscale harness ==="
# check cases (dc0)
run check-happy   0 happy   check vr1-dc0
run check-notrun  1 notrun  check vr1-dc0
run check-noroute 1 noroute check vr1-dc0
run check-notag   1 notag   check vr1-dc0
run check-noleg   1 noleg   check vr1-dc0
# install cases
CASE_AUTHKEY="tskey-fake" run install-happy  0 happy   install vr1-dc0
                          run install-nokey  4 happy   install vr1-dc0
CASE_AUTHKEY="tskey-fake" run install-upfail 4 upfail  install vr1-dc0
CASE_TS="$BIN/nope" CASE_AUTHKEY="tskey-fake" run install-noTS 4 happy install vr1-dc0
# arg/site validation
run badmode  2 happy frobnicate vr1-dc0
run badsite  2 happy check      vr1-dc9
run noargs   2 happy

# dc1 resolves its OWN cidr (not dc0's) -- run check-happy with dc1 fixture
PASS_BEFORE=$PASS
out="$(PATH="$BIN:$PATH" TAILSCALE="$BIN/tailscale" TS_FAKE_MODE=happy TS_FAKE_CIDR='10.12.68.0/22' TS_FAKE_LEG='10.12.68.7' \
       bash "$SUT" check vr1-dc1 2>&1)"; code=$?
if [ "$code" -eq 0 ] && printf '%s' "$out" | grep -q '10.12.68.0/22'; then PASS=$((PASS+1)); echo "PASS: dc1 resolves 10.12.68.0/22 (exit 0)"
else FAIL=$((FAIL+1)); echo "FAIL: dc1 site (got $code)"; echo "$out" | sed 's/^/    /'; fi

# site-table rows must carry MEASURED tags (hard rule 2)
for s in 'vr1-dc0.*MEASURED' 'vr1-dc1.*MEASURED'; do
  if grep -qE "$s" "$SUT"; then PASS=$((PASS+1)); echo "PASS: site row tagged MEASURED ($s)"
  else FAIL=$((FAIL+1)); echo "FAIL: site row missing MEASURED ($s)"; fi
done

echo "=== $PASS pass / $FAIL fail ==="
[ "$FAIL" -eq 0 ]
