#!/usr/bin/env bash
#
# adr-077 dispatch invariants — behavioural test for the two-path domain
# activation gate in install/ontoref-global (_dispatch_domain).
#
# Asserts, against the SOURCE wrapper (not the installed copy):
#   T1  bond path      — a bond-only consumer (carrier, NO manifest) activates.
#   T2  refusal        — a bare project (no manifest, no carrier) is refused.
#   T3  additive Hard  — a repo_kind-matching project activates IDENTICALLY with
#                        and without a carrier present (constraint
#                        `bond-path-is-purely-additive`: the carrier never alters
#                        an outcome the repo_kind path already granted).
#   T4  bond rescues   — a manifest whose repo_kind does NOT match is refused
#                        without a carrier, and activates WITH one.
#
# "Activated" = the dispatch passed the gate and proceeded to run the domain's
# commands.nu; the gate's refusal line is absent. The command itself may then
# fail on its own logic (the fixtures are not real rustelo sites) — that failure
# is BEYOND the gate and is exactly what proves the gate let it through.

set -euo pipefail

cd "$(dirname "$0")/.."

WRAPPER="install/ontoref-global"
DOMAIN="rustelo"          # a real installed domain with repo_kinds.txt = RusteloApp
REFUSAL="not available for this project"

# ── locate a data dir (ONTOREF_ROOT) so domains/ + dispatcher resolve ─────────
DD=""
for candidate in "$HOME/Library/Application Support/ontoref" "$HOME/.local/share/ontoref"; do
  if [[ -d "$candidate/domains/$DOMAIN" ]]; then DD="$candidate"; break; fi
done
if [[ -z "$DD" ]]; then
  echo "bond-dispatch-test: no installed data dir with domains/$DOMAIN — run 'just install-daemon' first" >&2
  exit 3
fi

echo "== adr-077 dispatch invariants =="
echo "  wrapper=$WRAPPER  data_dir=$DD  domain=$DOMAIN"
echo

TMP="$(mktemp -d)"
trap 'rm -rf "$TMP"' EXIT

PASS=0
FAIL=0

# Run the source wrapper against a project root; echo combined output.
run_dispatch() {
  local root="$1"
  ONTOREF_ROOT="$DD" ONTOREF_PROJECT_ROOT="$root" bash "$WRAPPER" "$DOMAIN" routes 2>&1 || true
}

# assert_activated <label> <project_root>
assert_activated() {
  local label="$1" root="$2" out
  out="$(run_dispatch "$root")"
  if echo "$out" | grep -qF "$REFUSAL"; then
    echo "  FAIL  $label — gate REFUSED (expected activation)"; FAIL=$((FAIL + 1))
  else
    echo "  pass  $label — gate passed"; PASS=$((PASS + 1))
  fi
}

# assert_refused <label> <project_root>
assert_refused() {
  local label="$1" root="$2" out
  out="$(run_dispatch "$root")"
  if echo "$out" | grep -qF "$REFUSAL"; then
    echo "  pass  $label — gate refused"; PASS=$((PASS + 1))
  else
    echo "  FAIL  $label — gate ACTIVATED (expected refusal)"; FAIL=$((FAIL + 1))
  fi
}

# ── fixtures ──────────────────────────────────────────────────────────────────
make_carrier() {
  local root="$1"
  mkdir -p "$root/.domains-ontoref/$DOMAIN"
  cat > "$root/.domains-ontoref/$DOMAIN/bonds.ncl" <<EOF
let s = import "bond.ncl" in
{
  domain = "$DOMAIN",
  bonds = [
    { id = "test-to-$DOMAIN", from = "test", to = "$DOMAIN", axis = 'Dependency, state = 'Linked, dep_kind = 'Conformist, mutual = false, plane = "$DOMAIN" },
  ],
} | s.BondSet
EOF
}

make_manifest() {
  local root="$1" kind="$2"
  mkdir -p "$root/.ontoref/ontology"
  printf 'let m = import "manifest" in\n{ project = "t", repo_kind = %s }\n' "'$kind" \
    > "$root/.ontoref/ontology/manifest.ncl"
}

# T1 — bond-only consumer (carrier, no manifest)
BOND_ONLY="$TMP/bond-only"; mkdir -p "$BOND_ONLY"; make_carrier "$BOND_ONLY"
assert_activated "T1 bond-only (carrier, no manifest)" "$BOND_ONLY"

# T2 — bare project (no manifest, no carrier)
BARE="$TMP/bare"; mkdir -p "$BARE"
assert_refused "T2 bare (no manifest, no carrier)" "$BARE"

# T3 — additive Hard: repo_kind match, with vs without carrier → both activate
MANAGED="$TMP/managed"; make_manifest "$MANAGED" "RusteloApp"
assert_activated "T3a managed repo_kind, no carrier" "$MANAGED"
make_carrier "$MANAGED"
assert_activated "T3b managed repo_kind, WITH carrier (additive)" "$MANAGED"

# T4 — bond rescues a non-matching repo_kind
WRONG="$TMP/wrong-kind"; make_manifest "$WRONG" "SomeOtherKind"
assert_refused  "T4a wrong repo_kind, no carrier" "$WRONG"
make_carrier "$WRONG"
assert_activated "T4b wrong repo_kind, WITH carrier (bond rescues)" "$WRONG"

echo
echo "== summary: $PASS passed, $FAIL failed =="
[[ "$FAIL" -eq 0 ]] || exit 1
