#!/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>
  local want="$1" label="$2" subs="$3" ifs="$4"
  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"
}
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
[ "$rc_all" -eq 0 ] && echo "ALL PASS" || echo "SOME FAILED"
rm -f "$OUT"; exit "$rc_all"
