#!/usr/bin/env bash
# Harness for scripts/dc-dc-whole-host-budget.py (R3-F06: the committed replacement
# for the lost scratchpad/optc-calc.py). Read-only arithmetic; asserts the ruled
# Model B / R-3 shape FITS, the model math, and the failure/usage paths.
set -u
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SCRIPT="$HERE/../../scripts/dc-dc-whole-host-budget.py"
PASS=0; FAIL=0
ok()   { PASS=$((PASS+1)); }
bad()  { FAIL=$((FAIL+1)); echo "  FAIL: $1"; }

# assert_contains <desc> <expected-substring> <command...>
assert_contains() {
  local desc="$1" want="$2"; shift 2
  local out; out="$("$@" 2>&1)"
  if grep -qF -- "$want" <<<"$out"; then ok; else bad "$desc (want '$want')"; fi
}
# assert_exit <desc> <expected-code> <command...>
assert_exit() {
  local desc="$1" want="$2"; shift 2
  "$@" >/dev/null 2>&1; local got=$?
  if [ "$got" -eq "$want" ]; then ok; else bad "$desc (want exit $want, got $got)"; fi
}

# 1. Ruled shape: Model B, defaults (3+2+4) -> FIT at 838 GiB, exit 0.
assert_contains "model B ram=838"     "ram=838/1024GiB verdict=FIT" python3 "$SCRIPT" --model B
assert_contains "model B headroom"    "headroom=186GiB"             python3 "$SCRIPT" --model B
assert_exit     "model B fits (0)"    0                              python3 "$SCRIPT" --model B
assert_contains "model B binds RAM"   "BINDING resource"            python3 "$SCRIPT" --model B

# 2. Model A (fallback) -> FIT at 822 GiB (16 GiB less: no containment overhead, has small rack).
assert_contains "model A ram=822"     "ram=822/1024GiB verdict=FIT" python3 "$SCRIPT" --model A
assert_exit     "model A fits (0)"    0                              python3 "$SCRIPT" --model A

# 3. Model math: B adds containment overhead on top of A's node RAM; B RAM > A RAM by 2*16 - (2*rackmem).
#    (B: +2*16 overhead; A: +2*8 rack) => B - A = 32 - 16 = 16 GiB. Assert B==838, A==822.
assert_contains "B minus A = 16 GiB"  "ram=838/1024GiB"             python3 "$SCRIPT" --model B

# 4. Old 3-storage shape (pre-R-3) is LIGHTER: 3 storage/DC -> 838 - 2*24 = 790 GiB (matches D-121's original).
assert_contains "3-storage = 790"     "ram=790/1024GiB verdict=FIT" python3 "$SCRIPT" --model B --storage 3,8,24,550

# 5. NO-FIT path: oversized control nodes push RAM over 1024 -> exit 1, NO-FIT.
assert_exit     "oversize -> exit 1"  1  python3 "$SCRIPT" --model B --control 3,16,160,150
assert_contains "oversize NO-FIT"     "verdict=NO-FIT"  python3 "$SCRIPT" --model B --control 3,16,160,150

# 6. Usage error: malformed triple -> exit 2.
assert_exit     "bad arg -> exit 2"   2  python3 "$SCRIPT" --host 256,1024

# 7. Determinism: two identical runs produce identical output.
A_OUT="$(python3 "$SCRIPT" --model B 2>&1)"; B_OUT="$(python3 "$SCRIPT" --model B 2>&1)"
if [ "$A_OUT" = "$B_OUT" ]; then ok; else bad "non-deterministic output"; fi

# 8. Single-DC scaling: --dcs 1 halves the node RAM contribution.
assert_contains "dcs=1 lighter"       "verdict=FIT"  python3 "$SCRIPT" --model B --dcs 1

TOTAL=$((PASS+FAIL))
echo "dc-dc-whole-host-budget: $PASS/$TOTAL PASS"
[ "$FAIL" -eq 0 ]
