#!/bin/bash
#
# STEWARD PROTOCOL - Pre-Commit Guard (Phase 3.1)
# ================================================
# "The Electric Fence" - Fast, dumb, effective
#
# Purpose: Block 95% of architectural violations BEFORE they get committed
# Performance: <50ms (if slower, devs will bypass with --no-verify)
# Philosophy: Fail fast, fail loud, fail early
#
# CONFIG SOURCE: config/quality.yaml (guards section)
#
# Part of Defense in Depth:
# - Layer 1 (this): Fast pattern matching (pre-commit)
# - Layer 2: Watchman AST analysis (CI/CD)
# - Layer 3: Auditor verdict (CI/CD)

set -e  # Exit on first error

REPO_ROOT=$(git rev-parse --show-toplevel)
cd "$REPO_ROOT"

# Colors for output
RED='\033[0;31m'
YELLOW='\033[1;33m'
GREEN='\033[0;32m'
NC='\033[0m' # No Color

# =============================================================================
# LOAD CONFIG FROM quality.yaml
# =============================================================================
CONFIG_FILE="config/quality.yaml"

# Read agent_paths from config (fallback to defaults if yq not available)
if command -v yq &> /dev/null && [ -f "$CONFIG_FILE" ]; then
    AGENT_PATHS=$(yq -r '.guards.agent_paths[]' "$CONFIG_FILE" 2>/dev/null | tr '\n' '|' | sed 's/|$//')
else
    # Fallback: hardcoded defaults (matches config/quality.yaml)
    AGENT_PATHS="vibe_core/cartridges/system|vibe_core/cartridges/agent_city"
fi

# Convert pipe-separated to regex pattern
AGENT_PATH_REGEX="^(${AGENT_PATHS})"

echo -e "${YELLOW}⚡ Running Steward Protocol Pre-Commit Guards...${NC}"

# ============================================================================
# GUARD 1: Block requirements.txt in agent directories
# ============================================================================
echo -n "  🔍 Checking for requirements.txt in agent dirs... "

# Get list of files to be committed (exclude deleted files)
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACMR)

# Check if any requirements.txt in agent dirs are staged
if echo "$STAGED_FILES" | grep -qE "${AGENT_PATH_REGEX}.*/requirements.txt$"; then
    echo -e "${RED}BLOCKED${NC}"
    echo ""
    echo -e "${RED}❌ VIOLATION: requirements.txt found in agent directory${NC}"
    echo ""
    echo "Agent directories must use pyproject.toml for dependencies."
    echo "After Phase 2 migration, requirements.txt is prohibited."
    echo ""
    echo "To fix:"
    echo "  1. Remove the requirements.txt file"
    echo "  2. Add dependencies to pyproject.toml instead"
    echo "  3. Use agent.system.add_dependency() at runtime"
    echo ""
    exit 1
fi

echo -e "${GREEN}OK${NC}"

# ============================================================================
# GUARD 2: Block direct Path("data/...") patterns
# ============================================================================
echo -n "  🔍 Checking for direct Path('data/...') calls... "

# Only check Python files in agent directories that are staged
PYTHON_FILES=$(echo "$STAGED_FILES" | grep -E "${AGENT_PATH_REGEX}.*\.py$" || true)

if [ -n "$PYTHON_FILES" ]; then
    # Check for Path("data/ or Path('data/ patterns
    VIOLATIONS=$(echo "$PYTHON_FILES" | xargs grep -n "Path([\"']data/" 2>/dev/null || true)

    if [ -n "$VIOLATIONS" ]; then
        echo -e "${RED}BLOCKED${NC}"
        echo ""
        echo -e "${RED}❌ VIOLATION: Direct Path('data/...') detected${NC}"
        echo ""
        echo "Agents must use sandboxed filesystem access."
        echo "Direct Path('data/...') bypasses VFS isolation."
        echo ""
        echo "Violations found:"
        echo "$VIOLATIONS" | while read line; do
            echo "  • $line"
        done
        echo ""
        echo "To fix:"
        echo "  1. Use agent.system.get_sandbox_path() instead"
        echo "  2. Convert to lazy-loading @property pattern"
        echo ""
        exit 1
    fi
fi

echo -e "${GREEN}OK${NC}"

# ============================================================================
# GUARD 3: Block direct open() calls with hardcoded paths in __init__
# ============================================================================
echo -n "  🔍 Checking for hardcoded paths in __init__... "

if [ -n "$PYTHON_FILES" ]; then
    # Look for suspicious patterns like Path(".") or Path("steward") in __init__ methods
    INIT_VIOLATIONS=$(echo "$PYTHON_FILES" | xargs grep -n "def __init__" -A 20 2>/dev/null | \
        grep -E "Path\([\"']\.|Path\([\"']steward|Path\([\"']vibe_core" | \
        grep -v "# PHASE 2" | \
        grep -v "lazy-load" || true)

    if [ -n "$INIT_VIOLATIONS" ]; then
        echo -e "${YELLOW}WARNING${NC}"
        echo ""
        echo -e "${YELLOW}⚠️  SUSPICIOUS: Hardcoded paths detected in __init__${NC}"
        echo ""
        echo "After Phase 2.3, agents should use lazy-loading for paths."
        echo "Paths initialized in __init__ may execute before system interface injection."
        echo ""
        echo "Suspicious patterns:"
        echo "$INIT_VIOLATIONS" | head -10
        echo ""
        echo -e "${YELLOW}This is a WARNING, not a blocker. Review carefully.${NC}"
        echo ""
    fi
fi

echo -e "${GREEN}OK${NC}"

# ============================================================================
# GUARD 8: OPUS-175 Iron Dome - Block Direct Kernel Imports (Runtime)
# ============================================================================
# Plugins must go through Envoy API, not import kernel internals directly.
# TYPE_CHECKING imports are OK (for type hints only).
# Runtime imports are HIGH TREASON in federal architecture.
# ============================================================================
echo -n "  🛡️  OPUS-175 Iron Dome (Kernel Border)... "

PLUGIN_PYTHON_FILES=$(echo "$STAGED_FILES" | grep -E "^vibe_core/plugins/.*\.py$" || true)

# Exclude test infrastructure files (fixtures, test helpers) from runtime import checks
# Tests need direct kernel access - they're not runtime plugins
PLUGIN_PYTHON_FILES=$(echo "$PLUGIN_PYTHON_FILES" | grep -v "/fixtures\.py$" | grep -v "/tests/" | grep -v "_test\.py$" || true)

if [ -n "$PLUGIN_PYTHON_FILES" ]; then
    IRON_DOME_VIOLATIONS=""

    for file in $PLUGIN_PYTHON_FILES; do
        if [ -f "$file" ]; then
            # Find kernel imports NOT inside TYPE_CHECKING blocks
            # Look for lines with kernel import and check context
            while IFS= read -r import_line; do
                LINE_NUM=$(echo "$import_line" | cut -d: -f1)
                # Check previous 5 lines for TYPE_CHECKING
                START=$((LINE_NUM - 5))
                if [ $START -lt 1 ]; then START=1; fi
                CONTEXT=$(sed -n "${START},${LINE_NUM}p" "$file" 2>/dev/null)

                if ! echo "$CONTEXT" | grep -q "TYPE_CHECKING"; then
                    IRON_DOME_VIOLATIONS="${IRON_DOME_VIOLATIONS}  ${file}:${import_line}\n"
                fi
            done < <(grep -n "from vibe_core\.kernel" "$file" 2>/dev/null || true)
        fi
    done

    if [ -n "$IRON_DOME_VIOLATIONS" ]; then
        echo -e "${RED}BLOCKED${NC}"
        echo ""
        echo -e "${RED}❌ OPUS-175 IRON DOME: Direct Kernel Import at Runtime${NC}"
        echo ""
        echo "Plugins must NOT import kernel internals at runtime!"
        echo "Only TYPE_CHECKING imports are allowed (for type hints)."
        echo ""
        echo "Violations:"
        echo -e "$IRON_DOME_VIOLATIONS"
        echo ""
        echo "To fix:"
        echo "  1. Move import inside 'if TYPE_CHECKING:' block"
        echo "  2. Use Envoy API for runtime kernel access"
        echo "  3. Receive kernel via plugin init(kernel) method"
        echo ""
        exit 1
    fi
fi

echo -e "${GREEN}OK${NC}"

# ============================================================================
# GUARD 4: Auto-format and auto-fix with ruff
# ============================================================================
echo -n "  🎨 Running ruff format + check... "

# Get ALL staged Python files (not just agent dirs)
ALL_PYTHON_FILES=$(echo "$STAGED_FILES" | grep "\.py$" || true)

if [ -n "$ALL_PYTHON_FILES" ]; then
    # Auto-format staged Python files
    echo "$ALL_PYTHON_FILES" | xargs ruff format --quiet 2>/dev/null || true

    # Auto-fix safe linting issues
    echo "$ALL_PYTHON_FILES" | xargs ruff check --fix --quiet 2>/dev/null || true

    # Restage formatted/fixed files
    echo "$ALL_PYTHON_FILES" | xargs git add 2>/dev/null || true

    # Check for CRITICAL errors that cannot be auto-fixed
    RUFF_ERRORS=$(echo "$ALL_PYTHON_FILES" | xargs ruff check --select=E9,F63,F7,F82 --quiet 2>/dev/null || true)

    if [ -n "$RUFF_ERRORS" ]; then
        echo -e "${RED}BLOCKED${NC}"
        echo ""
        echo -e "${RED}❌ CRITICAL SYNTAX ERRORS DETECTED${NC}"
        echo ""
        echo "$RUFF_ERRORS"
        echo ""
        echo "Fix these errors before committing."
        exit 1
    fi

    echo -e "${GREEN}OK (auto-formatted + checked)${NC}"
else
    echo -e "${GREEN}SKIP (no Python files)${NC}"
fi

# ============================================================================
# GUARD 5: PANOPTICON+ Test Validation
# ============================================================================
echo -n "  🔍 Validating test files (PANOPTICON+)... "

# Get staged test files
TEST_FILES=$(echo "$STAGED_FILES" | grep -E "^tests/.*test_.*\.py$" || true)

if [ -n "$TEST_FILES" ]; then
    # Run TestValidator on staged test files
    VALIDATION_OUTPUT=$(echo "$TEST_FILES" | tr '\n' ' ' | xargs python -m vibe_core.plugins.test_orchestration.test_validator 2>&1 || true)
    VALIDATION_EXIT=$?

    if [ $VALIDATION_EXIT -ne 0 ]; then
        echo -e "${RED}BLOCKED${NC}"
        echo ""
        echo -e "${RED}❌ PANOPTICON+ TEST VALIDATION FAILED${NC}"
        echo ""
        echo "$VALIDATION_OUTPUT"
        echo ""
        echo "Fix the violations before committing."
        echo "Use standardized fixtures from vibe_core.plugins.test_orchestration"
        echo ""
        exit 1
    fi

    echo -e "${GREEN}OK${NC}"
else
    echo -e "${GREEN}SKIP (no test files)${NC}"
fi

# ============================================================================
# GUARD 6: VISNU Kernel Protection (TOTAL LOCKDOWN)
# ============================================================================
# Security Ring 0: 7 kernel + 3 governance + 10 workflows + 1 config = 21 files
# See: docs/architecture/OPUS/024-KERNEL-PROTECTION-AUDIT.md
# GAD-000: Machine-parseable JSON output for AI operators
# ============================================================================
echo -n "  ☢️  VISNU Kernel Protection (21 files)... "

RESTORE_SCRIPT="$REPO_ROOT/scripts/governance/restore_kernel.sh"

if [ -x "$RESTORE_SCRIPT" ]; then
    # Run restore script - it auto-restores any protected file changes
    OUTPUT=$("$RESTORE_SCRIPT" 2>&1)

    if echo "$OUTPUT" | grep -q "NUCLEAR RESET EXECUTED"; then
        echo -e "${RED}RESTORED${NC}"
        echo ""

        # GAD-000: Extract restored files for machine-readable output
        RESTORED_FILES=$(echo "$OUTPUT" | grep "RESTORED:" | sed 's/.*RESTORED: //' | sed 's/ →.*//' | tr '\n' ',' | sed 's/,$//')

        # GAD-000 compliant JSON output for AI operators
        echo "{"
        echo "  \"guard\": \"VISNU_KERNEL_PROTECTION\","
        echo "  \"status\": \"RESTORED\","
        echo "  \"action\": \"auto_reverted_to_origin_main\","
        echo "  \"protected_files_count\": 21,"
        echo "  \"restored_files\": [\"${RESTORED_FILES//,/\", \"}\"],"
        echo "  \"reason\": \"Security Ring 0 files are immutable\","
        echo "  \"solution\": \"Create a plugin in vibe_core/plugins/your_feature/ instead\","
        echo "  \"documentation\": \"docs/architecture/OPUS/024-KERNEL-PROTECTION-AUDIT.md\""
        echo "}"
        echo ""

        # Human-readable output
        echo "$OUTPUT"
        echo ""
        echo -e "${YELLOW}AI AGENT: You attempted to modify protected kernel files.${NC}"
        echo -e "${YELLOW}Your changes were AUTO-REVERTED. This is by design.${NC}"
        echo -e "${YELLOW}To add functionality: Create a PLUGIN in vibe_core/plugins/${NC}"
        echo ""
    else
        echo -e "${GREEN}OK${NC}"
    fi
else
    echo -e "${YELLOW}SKIP (restore_kernel.sh not found)${NC}"
fi

# ============================================================================
# GUARD 7: OPUS-076 - Block Simulation Mode (No Pussy Mode!)
# ============================================================================
echo -n "  🔥 OPUS-076 Live Fire Guard... "

# Check if providers.yaml is being modified with simulation mode
if echo "$STAGED_FILES" | grep -q "config/providers.yaml"; then
    # Check if the change sets live_fire_enabled to false
    if git diff --cached config/providers.yaml | grep -qE "^\+.*live_fire_enabled.*false"; then
        echo -e "${RED}BLOCKED${NC}"
        echo ""
        echo -e "${RED}❌ OPUS-076 VIOLATION: Attempt to enable SIMULATION MODE${NC}"
        echo ""
        echo "  live_fire_enabled: false  ← FORBIDDEN"
        echo ""
        echo "MANAS needs REAL execution mode to DO REAL WORK."
        echo "Simulation mode is for cowards. Don't be a coward."
        echo ""
        echo "See: docs/architecture/OPUS/076-NO-PUSSY-MODE.md"
        echo ""
        exit 1
    fi
fi

echo -e "${GREEN}OK${NC}"

# ============================================================================
# All guards passed
# ============================================================================
echo -e "${GREEN}✅ All pre-commit guards passed${NC}"
echo ""

exit 0
