#!/usr/bin/env bash
# python_gate — pre-execution schema enforcement shim
# This script intercepts 'python' calls and validates code before running it.
#
# Controlled by $GATEHOUSE_MODE:
#   hard  — block execution on violations (LLM enforcement)
#   soft  — print violations but always run (developer visibility)
#   off   — pass-through, no checking (default when unset)

# Discover own location — works whether symlinked, aliased, or installed to PATH
SCRIPT_DIR="$(cd "$(dirname "$(readlink -f "$0" 2>/dev/null || realpath "$0" 2>/dev/null || echo "$0")")" && pwd)"

# Real Python interpreter — found dynamically, never hardcoded
REAL_PYTHON="$(command -v python3)"

# Enforcement mode: off (default), hard, soft
MODE="${GATEHOUSE_MODE:-off}"

# Normalise to lowercase
MODE=$(echo "$MODE" | tr '[:upper:]' '[:lower:]')

# Off or unset — pass through immediately, zero overhead
if [[ "$MODE" != "hard" && "$MODE" != "soft" ]]; then
    exec $REAL_PYTHON "$@"
fi

# Gate home: self-discovered from script location, with optional override
GATE_HOME="${GATE_HOME:-$SCRIPT_DIR}"
GATE_ENGINE="${GATE_HOME}/gate_engine.py"

# Find the .py file in the command arguments
PY_FILE=""
for arg in "$@"; do
    if [[ "$arg" == *.py ]]; then
        PY_FILE="$arg"
        break
    fi
done

# If no .py file or no gate engine, just run Python normally
if [[ -z "$PY_FILE" ]] || [[ ! -f "$GATE_ENGINE" ]]; then
    exec $REAL_PYTHON "$@"
fi

# Walk up from the .py file's directory looking for .gate_schema.yaml
# This is how the shim knows which project (and schema) to use
DIR=$(dirname "$(realpath "$PY_FILE")")
SCHEMA=""
while [[ "$DIR" != "/" ]]; do
    if [[ -f "$DIR/.gate_schema.yaml" ]]; then
        SCHEMA="$DIR/.gate_schema.yaml"
        break
    fi
    DIR=$(dirname "$DIR")
done

# No .gate_schema.yaml found? This project isn't gated. Run normally.
if [[ -z "$SCHEMA" ]]; then
    exec $REAL_PYTHON "$@"
fi

# Read schema name for the banner (best-effort grep from the config)
SCHEMA_NAME=$(grep -m1 '^schema:' "$SCHEMA" 2>/dev/null | sed 's/schema:[[:space:]]*//' | tr -d '"' | tr -d "'")
SCHEMA_NAME="${SCHEMA_NAME:-unknown}"

# Print activation banner to stderr (always visible, never corrupts stdout)
if [[ "$MODE" == "hard" ]]; then
    MODE_LABEL="\033[91mHARD\033[0m"
else
    MODE_LABEL="\033[93mSOFT\033[0m"
fi

{
    echo -e "\033[2m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\033[0m"
    echo -e "  \033[1mGATEHOUSE ACTIVE\033[0m  |  Mode: ${MODE_LABEL}  |  Schema: \033[96m${SCHEMA_NAME}\033[0m"
    echo -e "  \033[2mDeactivate: export GATEHOUSE_MODE=off\033[0m"
    echo -e "\033[2m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\033[0m"
} >&2

# Run the gate engine to check the code
GATE_OUTPUT=$($REAL_PYTHON "$GATE_ENGINE" --file "$PY_FILE" --schema "$SCHEMA" 2>&1)
GATE_EXIT=$?

# If violations were found, print the gate output to stderr
if [[ -n "$GATE_OUTPUT" ]]; then
    echo "$GATE_OUTPUT" >&2
fi

# Mode-specific behavior
if [[ $GATE_EXIT -ne 0 ]]; then
    if [[ "$MODE" == "hard" ]]; then
        # Hard mode: block execution — the LLM must fix the code
        exit $GATE_EXIT
    else
        # Soft mode: print a reminder that hard mode would have blocked, then run anyway
        {
            echo ""
            echo -e "  \033[93m▸ Soft mode: execution continues. Hard mode would have BLOCKED.\033[0m"
            echo -e "  \033[2m  Switch: export GATEHOUSE_MODE=hard\033[0m"
            echo ""
        } >&2
    fi
fi

# Gate passed (or soft mode) — run the code with real Python
exec $REAL_PYTHON "$@"
