#!/usr/bin/env bash
set -euo pipefail

ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)"

TMP_FILE="$(mktemp)"
VIOLATION_FILE="$(mktemp)"
trap 'rm -f "$TMP_FILE" "$VIOLATION_FILE"' EXIT

find \
  "$ROOT_DIR/runtime" \
  "$ROOT_DIR/tests" \
  "$ROOT_DIR/tools" \
  -type f \
  \( -name '*.c' -o -name '*.cc' -o -name '*.cpp' -o -name '*.h' -o -name '*.hh' -o -name '*.hpp' -o -name '*.js' -o -name '*.ts' \) \
  ! -path "$ROOT_DIR/vendor/*" \
  ! -path "$ROOT_DIR/runtime/ui/ini-panel/linuxcnc_ini.js" \
  -print0 |
  xargs -0 grep -nE '^[[:space:]]*([A-Za-z_][A-Za-z0-9_:<>~*&[:space:]]+[[:space:]]+)?Interp::[A-Za-z_~][A-Za-z0-9_]*[[:space:]]*\(' > "$TMP_FILE" || true

ALLOWED_STUB_FILE="$ROOT_DIR/runtime/core/linuxcnc_wrap/linuxcnc_interp_edge_stubs.cpp"
ALLOWED_PYTHON_STUB_FILE="$ROOT_DIR/runtime/core/linuxcnc_wrap/linuxcnc_interp_python_edge_stubs.cpp"

is_allowed_interp_stub() {
  local line="$1"

  case "$line" in
    "$ALLOWED_STUB_FILE":*Interp::is_pycallable\(* | \
    "$ALLOWED_STUB_FILE":*Interp::is_user_defined_g_code\(* | \
    "$ALLOWED_STUB_FILE":*Interp::is_any_m_code_remapped\(* | \
    "$ALLOWED_STUB_FILE":*Interp::is_user_defined_m_code\(* | \
    "$ALLOWED_STUB_FILE":*Interp::is_m_code_remappable\(* | \
    "$ALLOWED_STUB_FILE":*Interp::is_g_code_remappable\(* | \
    "$ALLOWED_STUB_FILE":*Interp::remap_in_progress\(* | \
    "$ALLOWED_STUB_FILE":*Interp::remapping\(* | \
    "$ALLOWED_STUB_FILE":*Interp::parse_remap\(* | \
    "$ALLOWED_STUB_FILE":*Interp::convert_remapped_code\(* | \
    "$ALLOWED_STUB_FILE":*Interp::add_parameters\(* | \
    "$ALLOWED_STUB_FILE":*Interp::pycall\(* | \
    "$ALLOWED_STUB_FILE":*Interp::py_execute\(* | \
    "$ALLOWED_STUB_FILE":*Interp::py_reload\(* | \
    "$ALLOWED_PYTHON_STUB_FILE":*Interp::is_pycallable\(* | \
    "$ALLOWED_PYTHON_STUB_FILE":*Interp::pycall\(* | \
    "$ALLOWED_PYTHON_STUB_FILE":*Interp::py_execute\(* | \
    "$ALLOWED_PYTHON_STUB_FILE":*Interp::py_reload\(*)
      return 0
      ;;
  esac

  return 1
}

while IFS= read -r line; do
  if ! is_allowed_interp_stub "$line"; then
    printf '%s\n' "$line" >> "$VIOLATION_FILE"
  fi
done < "$TMP_FILE"

if [[ -s "$VIOLATION_FILE" ]]; then
  echo "standalone Interp member definitions are not allowed outside documented runtime-edge stubs:" >&2
  cat "$VIOLATION_FILE" >&2
  exit 1
fi

echo "standalone CNC semantics guard complete"
