#!/usr/bin/env sh
# Pre-commit hook — the repository's own gates, run before a commit lands.
#
# Installed by: mise run install-hooks   (sets core.hooksPath=.githooks)
#
# 1. Forbidden ruff rules (hard block, no auto-fix):
#      ANN001  — missing type annotation for function argument
#      ANN201  — missing return type annotation for public function
#      ANN202  — missing return type annotation for private function
#      PLC0415 — import placed outside module top level
# 2. Gates that linting cannot express (see .agents/CHECKS.md):
#      check_field_consistency — bare-string cross-file contract keys
#      check_antipatterns      — magic crops, banned noqa, global state
#      check_dox               — DOX size budgets, cross-file duplication
# 3. Whatever the tool-managed hooks want to run (_delegate.sh: beads, repowise).
#
# Scans 2 and 3 are whole-repo and run unconditionally — they are cheap and
# they catch drift introduced by an untracked edit as well as a staged one.

set -e

root=$(git rev-parse --show-toplevel 2>/dev/null) || exit 0

staged=$(git diff --cached --name-only --diff-filter=ACM -- '*.py')
if [ -n "$staged" ]; then
    echo "--- ruff: checking forbidden rules (ANN001, ANN201, ANN202, PLC0415) ---"
    if ! echo "$staged" | tr '\n' '\0' | xargs -0 uv run ruff check \
        --select ANN001,ANN201,ANN202,PLC0415 \
        --no-fix \
        --quiet; then
        echo ""
        echo "✗ Commit blocked — fix the violations above, then commit again."
        echo "  Run: uv run ruff check --select ANN001,ANN201,ANN202,PLC0415 <file>"
        exit 1
    fi
    echo "✓ No forbidden rule violations in staged files."
fi

echo "--- gates: field consistency, antipatterns, DOX budgets ---"
uv run "$root/scripts/checks/check_field_consistency.py" || exit 1
uv run "$root/scripts/checks/check_antipatterns.py" || exit 1
uv run "$root/scripts/checks/check_dox.py" || exit 1
echo "✓ No field-consistency, antipattern, or DOX violations."

# --- BEGIN BEADS INTEGRATION v1.3.1 ---
# This section is managed by beads. Do not remove these markers.
if command -v bd >/dev/null 2>&1; then
  export BD_GIT_HOOK=1
  _bd_timeout=${BEADS_HOOK_TIMEOUT:-300}
  case "$_bd_timeout" in
    *[!0-9]*|'') _bd_timeout_invalid=1 ;;
    *[1-9]*) _bd_timeout_invalid=0 ;;
    *) _bd_timeout_invalid=1 ;;
  esac
  if [ "$_bd_timeout_invalid" -eq 1 ]; then
    echo >&2 "beads: invalid BEADS_HOOK_TIMEOUT; using 300 seconds"
    _bd_timeout=300
  fi
  _bd_timeout_backend=none
  _bd_timeout_command=
  for _bd_timeout_candidate in timeout gtimeout; do
    if command -v "$_bd_timeout_candidate" >/dev/null 2>&1; then
      if _bd_timeout_version="$("$_bd_timeout_candidate" --version 2>/dev/null)"; then
        case "$_bd_timeout_version" in
          "timeout (GNU coreutils) "*) _bd_timeout_command=$_bd_timeout_candidate; break ;;
        esac
      fi
    fi
  done
  if [ -n "$_bd_timeout_command" ]; then
    _bd_timeout_backend=coreutils
    if "$_bd_timeout_command" -- "$_bd_timeout" bd hooks run pre-commit "$@"; then
      _bd_exit=0
    else
      _bd_exit=$?
    fi
  elif command -v perl >/dev/null 2>&1; then
    _bd_timeout_backend=perl
    if perl -e 'alarm shift; exec @ARGV' -- "$_bd_timeout" bd hooks run pre-commit "$@"; then
      _bd_exit=0
    else
      _bd_exit=$?
    fi
  else
    echo >&2 "beads: hook 'pre-commit' running without timeout; install coreutils or perl to enable BEADS_HOOK_TIMEOUT"
    if bd hooks run pre-commit "$@"; then
      _bd_exit=0
    else
      _bd_exit=$?
    fi
  fi
  if { [ "$_bd_timeout_backend" = coreutils ] && [ "$_bd_exit" -eq 124 ]; } || { [ "$_bd_timeout_backend" = perl ] && [ "$_bd_exit" -eq 142 ]; }; then
    echo >&2 "beads: hook 'pre-commit' timed out after ${_bd_timeout}s — continuing without beads"
    _bd_exit=0
  fi
  if [ "$_bd_exit" -eq 3 ]; then
    echo >&2 "beads: database not initialized — skipping hook 'pre-commit'"
    _bd_exit=0
  fi
  if [ "$_bd_exit" -ne 0 ]; then exit "$_bd_exit"; fi
fi
# --- END BEADS INTEGRATION v1.3.1 ---

exec "$(dirname "$0")/_delegate.sh" pre-commit "$@"
