#!/usr/bin/env bash
# Behavior regression for carve-host-interfaces.sh -- Pattern A (D-060).
# Fake `maas` (read-only fixtures) + real jq. Drives the carve in DRY-RUN for
# openstack0 (octet .40) and asserts the emitted WOULD-actions and absences.
# Rewritten 2026-07-03 from the retired D-057 provider-vip expectations
# (harness must travel with its script's scheme).
set -uo pipefail
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CARVE="$(cd "$HERE/../../scripts" && pwd)/carve-host-interfaces.sh"
BIN="$HERE/fakebin"; FIX="$HERE/fix"
chmod +x "$BIN"/* 2>/dev/null || true   # GitHub Desktop lands files mode 100644
command -v jq >/dev/null || { echo "FAIL: jq required"; exit 1; }
python3 "$HERE/make_fixtures.py" >/dev/null
rc_all=0; OUT="$(mktemp)"

run() {  # <want_exit> <label> <subnets> <ifaces> [dc_value]
  local want="$1" label="$2" subs="$3" ifs="$4" dcval="${5:-}"
  DC="$dcval" PATH="$BIN:$PATH" FIX_MACHINES="$FIX/machines.json" FIX_MACHINE="$FIX/machine.json" \
    FIX_SUBNETS="$subs" FIX_IFACES="$ifs" \
    bash "$CARVE" openstack0 >"$OUT" 2>&1
  local rc=$?
  if [ "$rc" -ne "$want" ]; then
    printf '  [XX] %-40s exit %s (want %s)\n' "$label" "$rc" "$want"; sed 's/^/        /' "$OUT"; rc_all=1; return
  fi
  printf '  [ok] %-40s exit %s\n' "$label" "$rc"
}

# run_dc: like run(), but no fixtures needed -- used for $DC values expected to
# fail loud at the selector layer, BEFORE the script ever touches need_jq/MAAS.
run_dc() {  # <want_exit> <label> <dc_value>
  local want="$1" label="$2" dcval="$3"
  DC="$dcval" bash "$CARVE" openstack0 >"$OUT" 2>&1
  local rc=$?
  if [ "$rc" -ne "$want" ]; then
    printf '  [XX] %-40s exit %s (want %s)\n' "$label" "$rc" "$want"; sed 's/^/        /' "$OUT"; rc_all=1; return
  fi
  printf '  [ok] %-40s exit %s\n' "$label" "$rc"
}
has()  { grep -qE "$1" "$OUT" || { printf '       MISS expected /%s/\n' "$1"; rc_all=1; }; }
absent(){ grep -qE "$1" "$OUT" && { printf '       LEAK forbidden /%s/\n' "$1"; rc_all=1; } || true; }
count() { local n; n=$(grep -cE "$1" "$OUT"); [ "$n" -eq "$2" ] || { printf '       COUNT /%s/ = %s (want %s)\n' "$1" "$n" "$2"; rc_all=1; }; }

echo "=== carve-host-interfaces.sh -- Pattern A carve (fake maas + real jq) ==="

run 0 "fresh host: full Pattern-A plan" "$FIX/sub_ok.json" "$FIX/if_fresh.json"
has   'WOULD: unlink enp1s0\(id=100\) commissioning link id=900'    # L3 leaves the uplink (D-057 root cause)
has   'WOULD: create br-ex \(OVS\) parent=enp1s0\(id=100\)'
has   'STATIC 10\.12\.4\.40 on subnet 1'                            # br-ex carries the provider static
has   'WOULD: create br-metal \(standard\) parent=enp7s0\(id=101\)'
has   'STATIC 10\.12\.8\.40 on subnet 2'
has   'create br-metal\.103 \(VID 103, vlan obj 5003\)'
has   'WOULD: create br-internal \(standard\)'
has   'STATIC 10\.12\.12\.40 on subnet 3'
has   'enp8s0\(id=102\) -> VLAN 5004 \(10\.12\.16\.0/22\)'          # vlan resolved by CIDR, not hardcoded
has   'STATIC 10\.12\.16\.40 on subnet 4'
has   'STATIC 10\.12\.32\.40 on subnet 5'
has   'STATIC 10\.12\.36\.40 on subnet 6'
has   'no action on enp11s0'
has   'Summary: 0 fatal'
absent 'br-prov-api'                                                # the D-057 world must never reappear
absent 'enp1s0\.104'
absent 'provider-vip'

run 1 "missing data-tenant subnet -> hard gate" "$FIX/sub_missing.json" "$FIX/if_fresh.json"
has   'no MAAS subnet for 10\.12\.16\.0/22'

run 1 "metal-internal on wrong VID -> hard gate" "$FIX/sub_wrongvid.json" "$FIX/if_fresh.json"
has   "metal-internal 10\.12\.12\.0/22 is VID '99', expected 103"

run 0 "idempotent: Pattern A complete -> all SKIP" "$FIX/sub_ok.json" "$FIX/if_done.json"
count 'WOULD:' 0
has   'br-ex exists -- SKIP create'
has   'br-ex already on 10\.12\.4\.0/22 -- SKIP'
has   'br-metal exists -- SKIP create'
has   'br-internal already on 10\.12\.12\.0/22 -- SKIP'
has   'enp8s0 already STATIC on 10\.12\.16\.0/22 -- SKIP'
has   'Summary: 0 fatal'

echo
echo "=== \$DC selector wiring (DOCFIX-166; tooling gap register #15 sub-item 2) ==="

run 0 "DC=vr0-dc0 explicit: identical no-op full carve plan" "$FIX/sub_ok.json" "$FIX/if_fresh.json" vr0-dc0
has 'WOULD: create br-ex \(OVS\) parent=enp1s0\(id=100\)'
has 'Summary: 0 fatal'

run_dc 1 "DC=vr1-dc0: REFUSED (D-133 guard -- VR0 flow, VR1 arms populated 2026-07-23)" vr1-dc0
has 'superseded for VR1 by D-133'
absent 'DO:|WOULD:'                                                 # must exit before any MAAS interaction

run_dc 1 "DC=vr1-dc1: REFUSED (D-133 guard -- VR0 flow, VR1 arms populated 2026-07-23)" vr1-dc1
has 'superseded for VR1 by D-133'
absent 'DO:|WOULD:'                                                 # must exit before any MAAS interaction

run_dc 1 "DC=bogus: unknown token fails loud" bogus
has "unknown DC 'bogus'"

echo
[ "$rc_all" -eq 0 ] && echo "ALL PASS" || echo "SOME FAILED"
rm -f "$OUT"; exit "$rc_all"
