#!/usr/bin/env bash
# pre-push hook — runs the EXACT same lint + test commands as GitHub Actions CI.
# Catches failures BEFORE CI, not after.
#
# To bypass in an emergency: git push --no-verify
# To install: cp scripts/hooks/pre-push .git/hooks/pre-push && chmod +x .git/hooks/pre-push
#
# CI equivalence:
#   Lint:  .github/workflows/ci.yml → lint job → ruff check src/ --select E,F,W --ignore E501
#   Tests: .github/workflows/ci.yml → unit-tests job → pytest (matches pyproject testpaths)
#
# Layer 0 discipline (per docs/working/ci-hygiene-plan-2026-04-28.md):
#   - Warns when origin/main's last CI run was a failure.
#   - Refuses to push onto red main without --no-verify.

set -euo pipefail

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

# Activate venv if not already active
if [ -z "${VIRTUAL_ENV:-}" ]; then
  if [ -f "$REPO_ROOT/../.venv/bin/activate" ]; then
    # shellcheck disable=SC1091
    source "$REPO_ROOT/../.venv/bin/activate"
  elif [ -f "$REPO_ROOT/.venv/bin/activate" ]; then
    source "$REPO_ROOT/.venv/bin/activate"
  fi
fi

# ── CI status check on origin/main — Layer 0 discipline ────────────────
# Warn if last CI run on main was a failure. Cheap; uses gh CLI auth that's
# already configured. Skip gracefully if gh isn't available or repo isn't on
# GitHub.
if command -v gh >/dev/null 2>&1; then
  echo "▶ pre-push: checking origin/main CI status..."
  last_status=$(gh run list --branch main --limit 1 --json conclusion --jq '.[0].conclusion' 2>/dev/null || echo "unknown")
  if [ "$last_status" = "failure" ]; then
    echo ""
    echo "⚠ pre-push: origin/main is RED (last CI run failed)."
    echo "   View: gh run list --branch main --limit 5"
    echo ""
    echo "   Per ci-hygiene-plan-2026-04-28.md Rule 1: never push onto red main."
    echo "   Fix or revert is the next commit, not a new feature."
    echo ""
    echo "   To bypass intentionally: git push --no-verify"
    echo ""
    exit 1
  elif [ "$last_status" = "success" ]; then
    echo "✓ pre-push: origin/main is GREEN"
  else
    echo "  (origin/main status: ${last_status} — proceeding)"
  fi
fi

# ── ADR-number collision lint ───────────────────────────────────────────
echo "▶ pre-push: ADR number collision lint..."
if python scripts/lint_adr_numbers.py; then
  echo "✓ pre-push: ADR numbers unique"
else
  echo ""
  echo "✗ pre-push: ADR number collision detected — push blocked"
  echo "  Pick the next free number with: python scripts/lint_adr_numbers.py --next"
  exit 1
fi

# ── Ruff lint (EXACT match with CI lint job) ────────────────────────────
echo "▶ pre-push: running ruff linter..."

if ruff check src/ --select E,F,W --ignore E501; then
  echo "✓ pre-push: ruff passed"
else
  echo ""
  echo "✗ pre-push: ruff found errors — push blocked"
  echo "  Run: ruff check src/ --select E,F,W --ignore E501 --fix"
  exit 1
fi

# ── Test suite (matches CI unit-tests job — both testpaths) ────────────
# CI uses pyproject.toml's testpaths: ["tests", "src/axiom/extensions/builtins"].
# Earlier this hook only ran tests/ which missed ~2000 extension tests; that
# gap let test_standard collection errors + classroom test failures slip
# past pre-push for ~9 days. Now we run both, matching CI exactly.
echo "▶ pre-push: running test suite (unit only, no integration)..."

# --timeout=90 gives LLM-call tests headroom — the previous 30s gate
# fail-timed every LLM-touching test in the suite (the 18 "failures"
# bypassed with --no-verify across 2026-05-29's PR sweep were ALL
# timeouts, not assertion failures: each test passes in 40-60s
# standalone). The proper fix — mark LLM-touching tests and mock the
# endpoint in pre-push — is tracked separately.
if python -m pytest tests/ src/axiom/extensions/builtins/ \
    -m "not integration" \
    --tb=short -q \
    --no-header \
    --timeout=90 \
    2>&1; then
  echo "✓ pre-push: all tests passed"
else
  echo ""
  echo "✗ pre-push: tests failed — push blocked"
  echo "  Fix the failures above, or use --no-verify to bypass"
  exit 1
fi
