#!/usr/bin/env bash
# Regression test for pin-identity-gate.sh (Task 619).
#
# Covers:
#   1. Non-admin role                                  → ALLOW (no-op)
#   2. admin, unauthenticated, ordinary tool           → BLOCK (op=pin-prompted)
#   3. admin, already authenticated (state file)       → ALLOW
#   4. admin, auth tool, endpoint match                → ALLOW + state written (op=pin-bound)
#   5. admin, auth tool, endpoint miss                 → BLOCK (op=session-terminated)
#   6. admin, auth tool, endpoint unavailable          → BLOCK (op=pin-unavailable)
#   7. admin, auth tool, endpoint unreachable          → BLOCK (op=pin-error)
#
# The validate endpoint is stubbed via a `curl` shim on PATH whose response is
# driven by $FAKE_VALIDATE_KIND.

set -u
HOOK="$(cd "$(dirname "$0")/.." && pwd)/pin-identity-gate.sh"
[ -x "$HOOK" ] || { echo "FAIL: $HOOK not executable" >&2; exit 1; }

TMP_DIR=$(mktemp -d)
trap 'rm -rf "$TMP_DIR"' EXIT
mkdir -p "$TMP_DIR/bin" "$TMP_DIR/state"

# curl shim: emit a canned validate response based on $FAKE_VALIDATE_KIND.
cat > "$TMP_DIR/bin/curl" <<'SHIM'
#!/usr/bin/env bash
case "${FAKE_VALIDATE_KIND:-}" in
  match)       echo '{"kind":"match","userId":"user-0001"}' ;;
  miss)        echo '{"kind":"miss"}' ;;
  unavailable) echo '{"kind":"unavailable"}' ;;
  corrupt)     echo '{"kind":"corrupt"}' ;;
  unreachable) echo '' ;;
  *)           echo '' ;;
esac
SHIM
chmod +x "$TMP_DIR/bin/curl"

AUTH_TOOL='mcp__plugin_admin_admin__admin-identity-authenticate'
PASS=0; FAIL=0

# run <role> <kind> <stdin-json> [specialist] ; sets EXIT and ERR
run() {
  ERR=$(printf '%s' "$3" | \
    PATH="$TMP_DIR/bin:$PATH" \
    MAXY_SESSION_ROLE="$1" \
    MAXY_SPECIALIST="${4:-}" \
    FAKE_VALIDATE_KIND="$2" \
    MAXY_IDENTITY_GATE_STATE_DIR="$TMP_DIR/state" \
    MAXY_IDENTITY_VALIDATE_URL="http://stub/validate" \
    bash "$HOOK" 2>&1 >/dev/null)
  EXIT=$?
}

check() { # <label> <want-exit> <grep-or-->
  if [ "$EXIT" != "$2" ]; then echo "FAIL[$1]: exit=$EXIT want=$2 err=$ERR"; FAIL=$((FAIL+1)); return; fi
  if [ "$3" != "-" ] && ! printf '%s' "$ERR" | grep -q "$3"; then echo "FAIL[$1]: missing '$3' in: $ERR"; FAIL=$((FAIL+1)); return; fi
  echo "PASS[$1]"; PASS=$((PASS+1))
}

# 1. non-admin → allow
run public '' '{"session_id":"s1","tool_name":"Bash","tool_input":{}}'
check non-admin 0 -

# 1b. admin but specialist subagent (MAXY_SPECIALIST set) → allow (no-op)
run admin '' '{"session_id":"s1b","tool_name":"Bash","tool_input":{}}' database-operator
check specialist-exempt 0 -

# 2. admin unauth, ordinary tool → block
run admin '' '{"session_id":"s2","tool_name":"Bash","tool_input":{}}'
check unauth-block 2 "op=pin-prompted"

# 3. admin, authenticated (state file present) → allow
echo '{"userId":"user-0001"}' > "$TMP_DIR/state/s3.json"
run admin '' '{"session_id":"s3","tool_name":"Bash","tool_input":{}}'
check authed-allow 0 -

# 4. admin, auth tool, match → allow + state written + pin-bound
run admin match "{\"session_id\":\"s4\",\"tool_name\":\"$AUTH_TOOL\",\"tool_input\":{\"pin\":\"1234\"}}"
check match-allow 0 "op=pin-bound"
[ -f "$TMP_DIR/state/s4.json" ] && { echo "PASS[match-state-written]"; PASS=$((PASS+1)); } || { echo "FAIL[match-state-written]"; FAIL=$((FAIL+1)); }

# 5. admin, auth tool, miss → block + terminate
run admin miss "{\"session_id\":\"s5\",\"tool_name\":\"$AUTH_TOOL\",\"tool_input\":{\"pin\":\"9999\"}}"
check miss-block 2 "op=session-terminated"

# 6. admin, auth tool, unavailable → block
run admin unavailable "{\"session_id\":\"s6\",\"tool_name\":\"$AUTH_TOOL\",\"tool_input\":{\"pin\":\"1\"}}"
check unavailable-block 2 "op=pin-unavailable"

# 7. admin, auth tool, unreachable endpoint → block (fail-closed)
run admin unreachable "{\"session_id\":\"s7\",\"tool_name\":\"$AUTH_TOOL\",\"tool_input\":{\"pin\":\"1\"}}"
check unreachable-block 2 "op=pin-error"

echo "---"
echo "PASS=$PASS FAIL=$FAIL"
[ "$FAIL" = 0 ] || exit 1
