#!/usr/bin/env bash
# .githooks/pre-commit
#
# Governance loop pre-commit hook.
# Runs categorical compliance verification before every commit.
#
# Install: git config core.hooksPath .githooks
# Or via plugin-bundle: morphism install  (sets this automatically)

set -euo pipefail

MORPHISM_BIN="${MORPHISM_BIN:-npx morphism}"
KAPPA_THRESHOLD="${MORPHISM_KAPPA_THRESHOLD:-0.35}"
PROOF_DIR=".morphism/proofs"
STATE_FILE=".morphism/state.json"

# ── Detect working Python ─────────────────────────────────────────────────
if python --version >/dev/null 2>&1; then PYTHON=python;
elif python3 --version >/dev/null 2>&1; then PYTHON=python3;
else echo "No Python found, skipping governance check"; exit 0; fi

# ── Colours ────────────────────────────────────────────────────────────────
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m'

echo ""
echo "╔══════════════════════════════════════════════════════╗"
echo "║          Morphism Governance Pre-commit Check        ║"
echo "╚══════════════════════════════════════════════════════╝"

# ── 1. Gather staged file paths ────────────────────────────────────────────
STAGED=$(git diff --cached --name-only --diff-filter=ACM 2>/dev/null | tr '\n' ' ')
if [[ -z "$STAGED" ]]; then
  echo -e "${YELLOW}No staged files — skipping governance check.${NC}"
  exit 0
fi

# ── 1a. Blocking secret scan ─────────────────────────────────────────────
if [[ "${MORPHISM_SKIP_SECRET_SCAN:-0}" != "1" ]]; then
  echo "  Scanning staged diff for secrets..."
  SECRET_PATTERNS='AKIA[0-9A-Z]{16}|ghp_[A-Za-z0-9_]{36}|github_pat_[A-Za-z0-9_]{60,}|sk_(test|live)_[A-Za-z0-9_]{20,}|sk-ant-[A-Za-z0-9_-]{20,}|sk-proj-[A-Za-z0-9_-]{16,}|whsec_[A-Za-z0-9_]{20,}|xoxb-[A-Za-z0-9-]{20,}|-----BEGIN (RSA|OPENSSH|EC|DSA) PRIVATE KEY-----|pcsk_[A-Za-z0-9_]{20,}|lin_api_[A-Za-z0-9]{20,}|sntrys_[A-Za-z0-9]{20,}|sbp_[A-Za-z0-9]{20,}'
  if git diff --cached -U0 | grep -qE "$SECRET_PATTERNS"; then
    echo -e "${RED}✗ COMMIT BLOCKED: Potential secret detected in staged changes${NC}"
    echo "  Run: git diff --cached | grep -nE '$SECRET_PATTERNS'"
    echo "  If false positive, use MORPHISM_SKIP_SECRET_SCAN=1 git commit"
    exit 1
  fi
  echo -e "${GREEN}  ✓ No secrets in staged diff${NC}"
fi

# ── 1b. Layout check on newly added root-level files ─────────────────────
NEW_ROOT_FILES=$(git diff --cached --diff-filter=A --name-only 2>/dev/null | grep -v '/' || true)
if [[ -n "$NEW_ROOT_FILES" ]]; then
  LAYOUT_SCRIPT="scripts/layout_check.py"
  if [[ -f "$LAYOUT_SCRIPT" ]]; then
    echo "  Checking new root files against layout allowlist..."
    if ! $PYTHON "$LAYOUT_SCRIPT" --check-files $NEW_ROOT_FILES; then
      echo -e "${RED}✗ New root file(s) not in layout allowlist${NC}"
      echo "  Add the file to ALLOWED_ROOT_FILES in scripts/layout_check.py"
      echo "  or move it to the appropriate subdirectory."
      exit 1
    fi
  fi
fi

# ── 2. Get current commit SHA ──────────────────────────────────────────────
COMMIT_SHA=$(git rev-parse HEAD 2>/dev/null || echo "initial")

# ── 3. Run governance validate (calls governance MCP server internally) ───
echo -e "Validating ${STAGED}..."

# Check if morphism CLI is available; skip gracefully if not installed
if ! command -v morphism >/dev/null 2>&1; then
  echo -e "${YELLOW}⚠ morphism CLI not available — running lightweight checks only.${NC}"
  echo -e "${YELLOW}  Full governance validation (kappa gate, naturality, sheaf) is skipped.${NC}"
  echo -e "${YELLOW}  Install: npm install -g @morphism-systems/cli${NC}"

  # Lightweight fallback: run ruff on staged Python files
  PY_FILES=$(echo "$STAGED" | tr ' ' '\n' | grep '\.py$' | tr '\n' ' ' || true)
  if [[ -n "$PY_FILES" ]]; then
    if command -v ruff >/dev/null 2>&1 || $PYTHON -m ruff --version >/dev/null 2>&1; then
      echo "  Running ruff on staged Python files..."
      $PYTHON -m ruff check $PY_FILES || { echo -e "${RED}✗ ruff check failed${NC}"; exit 1; }
    fi
  fi

  echo -e "${GREEN}✓ Lightweight governance check passed${NC}"
  echo ""
  exit 0
fi

RESULT=$($MORPHISM_BIN validate \
  --commit "$COMMIT_SHA" \
  --format json \
  --proof-dir "$PROOF_DIR" \
  2>&1)

EXIT_CODE=$?

if [[ $EXIT_CODE -ne 0 ]]; then
  echo -e "${RED}✗ governance validate failed:${NC}"
  echo "$RESULT"
  echo ""
  echo "Fix governance violations and retry.  Run:"
  echo "  morphism validate --format text"
  exit 1
fi

# ── 4. Parse kappa from JSON result ───────────────────────────────────────
KAPPA=$(echo "$RESULT" | $PYTHON -c "
import sys, json
data = json.load(sys.stdin)
print(data.get('kappa', 1.0))
" 2>/dev/null || echo "1.0")

MATURITY=$(echo "$RESULT" | $PYTHON -c "
import sys, json
data = json.load(sys.stdin)
print(data.get('maturity_level', 'initial'))
" 2>/dev/null || echo "initial")

CONVERGING=$(echo "$RESULT" | $PYTHON -c "
import sys, json
data = json.load(sys.stdin)
print(data.get('converging', False))
" 2>/dev/null || echo "False")

VIOLATIONS=$(echo "$RESULT" | $PYTHON -c "
import sys, json
data = json.load(sys.stdin)
print(data.get('violation_count', 0))
" 2>/dev/null || echo "0")

SIG=$(echo "$RESULT" | $PYTHON -c "
import sys, json
data = json.load(sys.stdin)
print(data.get('proof_signature', 'n/a')[:16])
" 2>/dev/null || echo "n/a")

# ── 5. Display metrics ─────────────────────────────────────────────────────
echo ""
printf "  %-20s %s\n" "κ (kappa):"      "$KAPPA"
printf "  %-20s %s\n" "Maturity:"       "$MATURITY"
printf "  %-20s %s\n" "Converging:"     "$CONVERGING"
printf "  %-20s %s\n" "Violations:"     "$VIOLATIONS"
printf "  %-20s %s\n" "Proof sig:"      "${SIG}…"

# ── 6. Gate on kappa threshold ─────────────────────────────────────────────
KAPPA_FAIL=$($PYTHON -c "
import sys
k = float('$KAPPA')
t = float('$KAPPA_THRESHOLD')
print('1' if k > t else '0')
" 2>/dev/null || echo "0")

if [[ "$KAPPA_FAIL" == "1" ]]; then
  echo ""
  echo -e "${RED}✗ COMMIT BLOCKED: κ = $KAPPA exceeds threshold $KAPPA_THRESHOLD${NC}"
  echo "  Resolve governance violations before committing."
  echo "  Run: morphism validate --verbose --heal-dry-run"
  exit 1
fi

if [[ "$VIOLATIONS" != "0" ]]; then
  echo ""
  echo -e "${RED}✗ COMMIT BLOCKED: $VIOLATIONS naturality violation(s) detected${NC}"
  echo "  Policy enforcement is context-order-dependent."
  echo "  Run: morphism validate --verbose to see details."
  exit 1
fi

# ── 7. Update state.json ───────────────────────────────────────────────────
mkdir -p .morphism
$PYTHON - "$STATE_FILE" "$KAPPA" "$MATURITY" "$COMMIT_SHA" <<'PYEOF'
import sys, json, time, os

state_file = sys.argv[1]
kappa      = float(sys.argv[2])
maturity   = sys.argv[3]
commit     = sys.argv[4]

state = {}
if os.path.exists(state_file):
    try:
        with open(state_file) as f:
            state = json.load(f)
    except Exception:
        pass

history = state.get("kappa_history", [])
history.append(kappa)
history = history[-50:]   # keep last 50

state.update({
    "kappa": kappa,
    "maturity_level": maturity,
    "last_commit": commit,
    "updated_at": time.time(),
    "kappa_history": history,
})

with open(state_file, "w") as f:
    json.dump(state, f, indent=2)
PYEOF

# Stage state.json so it's included in the commit
git add "$STATE_FILE" 2>/dev/null || true

echo ""
echo -e "${GREEN}✓ Governance check passed (κ = $KAPPA, $MATURITY)${NC}"
echo ""
