#!/usr/bin/env bash
# Regression test for quote-engine-gate.sh.
#
# The gate is a PreToolUse hook on Bash. It refuses a Bash command that runs the
# persisted quoting engine or render script directly (quoting/engine.mjs or
# quoting/render.mjs), because those scripts must run only through the
# deterministic quote-engine-run / quote-render MCP tools (which apply the gates
# and write receipts). A mode=verify engine run and every unrelated command pass.
#
# Covers:
#   A. Bash running quoting/engine.mjs            → BLOCKED (exit 2)
#   B. Bash running quoting/render.mjs            → BLOCKED
#   C. engine.mjs run with mode=verify by hand    → BLOCKED (verify runs through the tool too)
#   D. engine.mjs run with a `# mode=verify` tail → BLOCKED (no token-anywhere escape)
#   E. unrelated Bash (ls quoting)                → ALLOWED
#   F. a quote-engine-run MCP tool call           → ALLOWED (not Bash)
#   G. empty stdin                                → ALLOWED (fail-open)
#   H. a non-Bash tool                            → ALLOWED (matcher defence-in-depth)
#   I. a block emits the op=bypass fault line
#   J. reading the script (cat) is not execution  → ALLOWED
#   K. grepping the script is not execution       → ALLOWED
#   L. the script run at command position         → BLOCKED

set -u

HOOK="$(cd "$(dirname "$0")/.." && pwd)/quote-engine-gate.sh"
if [[ ! -x "$HOOK" ]]; then
  echo "FAIL: $HOOK not executable" >&2
  exit 1
fi

PASS=0
FAIL=0

run_case() {
  local name="$1" stdin="$2" expected_exit="$3"
  local actual_exit
  ( printf '%s' "$stdin" | bash "$HOOK" >/dev/null 2>/dev/null )
  actual_exit=$?
  if [[ "$actual_exit" -eq "$expected_exit" ]]; then
    echo "PASS: $name (exit=$actual_exit)"
    PASS=$((PASS + 1))
  else
    echo "FAIL: $name (expected exit=$expected_exit, got=$actual_exit)" >&2
    FAIL=$((FAIL + 1))
  fi
}

bash_env() { # command string (JSON-escaped by caller)
  printf '{"hook_event_name":"PreToolUse","tool_name":"Bash","tool_input":{"command":"%s"}}' "$1"
}

run_case "A: Bash runs quoting/engine.mjs → BLOCKED" \
  "$(bash_env "node quoting/engine.mjs < quoting/job-1854.json")" 2

run_case "B: Bash runs quoting/render.mjs → BLOCKED" \
  "$(bash_env "node quoting/render.mjs")" 2

run_case "C: engine.mjs mode=verify by hand → BLOCKED" \
  "$(bash_env "node quoting/engine.mjs mode=verify")" 2

run_case "D: engine.mjs with # mode=verify tail → BLOCKED" \
  "$(bash_env "node quoting/engine.mjs < job.json # mode=verify")" 2

run_case "E: unrelated Bash → ALLOWED" \
  "$(bash_env "ls quoting")" 0

run_case "J: reading the script (cat) → ALLOWED" \
  "$(bash_env "cat quoting/engine.mjs")" 0

run_case "K: grepping the script → ALLOWED" \
  "$(bash_env "grep foo quoting/render.mjs")" 0

run_case "L: script at command position → BLOCKED" \
  "$(bash_env "./quoting/engine.mjs < job.json")" 2

run_case "F: quote-engine-run MCP call → ALLOWED" \
  '{"hook_event_name":"PreToolUse","tool_name":"mcp__plugin_sitedesk-job_sitedesk-job__quote-engine-run","tool_input":{"job":"1854","mode":"quote"}}' 0

run_case "G: empty stdin → ALLOWED (fail-open)" \
  "" 0

run_case "H: non-Bash tool → ALLOWED" \
  '{"hook_event_name":"PreToolUse","tool_name":"Write","tool_input":{"file_path":"/x/quoting/engine.mjs"}}' 0

# I: a block emits the op=bypass fault line on stderr.
STDERR=$( printf '%s' "$(bash_env "node quoting/engine.mjs")" | bash "$HOOK" 2>&1 >/dev/null )
if printf '%s' "$STDERR" | grep -q '\[quote-engine\] op=bypass reason=direct-script-exec'; then
  echo "PASS: I: block emits op=bypass reason=direct-script-exec"
  PASS=$((PASS + 1))
else
  echo "FAIL: I: op=bypass line absent (got: $STDERR)" >&2
  FAIL=$((FAIL + 1))
fi

echo "──────── quote-engine-gate test summary ────────"
echo "PASS=$PASS FAIL=$FAIL"
[[ "$FAIL" -eq 0 ]]
