# ==============================================================================
# Pre-commit Configuration - Multi-language Linting & Formatting
# ==============================================================================
# Install:       pre-commit install && pre-commit install --hook-type pre-push
# Fast lint:     pre-commit run --all-files            (linters only, ~10 s)
# Full suite:    pre-commit run --all-files --hook-stage pre-push  (+ tests)
# Update hooks:  pre-commit autoupdate
# ==============================================================================

# Global settings
default_language_version:
  python: python3

# By default every hook runs ONLY at commit-time. Pre-push runs only the
# hooks that explicitly opt in via `stages: [pre-push]` (currently
# pytest-coverage + prettier). This keeps `git push` cheap; commit-time
# already enforces the full lint suite.
default_stages: [pre-commit]

# Fail fast on first error (set to false to see all errors)
fail_fast: false

# Configuration
ci:
  autofix_commit_msg: "style: auto-fix by pre-commit hooks"
  autoupdate_commit_msg: "chore: update pre-commit hooks"

repos:
  # ===========================================================================
  # GENERAL HOOKS - File formatting and validation
  # ===========================================================================
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.6.0
    hooks:
      - id: trailing-whitespace
        args: [--markdown-linebreak-ext=md]
      - id: end-of-file-fixer
      - id: check-yaml
        args: [--unsafe]
      - id: check-json
        # Exclude JSONC files (VS Code configs, TypeScript configs)
        exclude: ^(\.vscode/|.*/\.vscode/|.*tsconfig.*\.json)
      - id: check-toml
      - id: check-xml
      - id: check-added-large-files
        args: [--maxkb=2000]
      - id: check-merge-conflict
      - id: check-case-conflict
      - id: check-symlinks
      - id: check-executables-have-shebangs
      - id: check-shebang-scripts-are-executable
      - id: detect-private-key
      - id: debug-statements
      - id: name-tests-test
        args: [--pytest-test-first]
      - id: check-ast
      - id: check-builtin-literals
      - id: check-docstring-first
      - id: fix-byte-order-marker
      - id: mixed-line-ending
        args: [--fix=lf]
      - id: requirements-txt-fixer

  # ===========================================================================
  # BINARY BLOCKER - Prevent binary/image files from being committed
  # ===========================================================================
  - repo: local
    hooks:
      - id: no-binaries
        name: Block binary/image files
        entry: scripts/check_no_binaries.sh
        language: script
        always_run: false
      - id: ai-evidence-contract
        name: Require AI evidence artifacts for code changes
        entry: scripts/check_ai_evidence.sh
        language: script
        pass_filenames: false
        always_run: true
      - id: ai-multifile-contract
        name: Require workflow contract for multi-file code changes
        entry: scripts/check_agent_contract.sh
        language: script
        pass_filenames: false
        always_run: true
      - id: append-only-sessions
        name: Enforce append-only session logs
        entry: scripts/check_append_only_sessions.sh
        language: script
        pass_filenames: false
        always_run: true

  # ===========================================================================
  # POLLING SCRIPT LINTER - Detect fork-storm anti-patterns in shell scripts
  # ===========================================================================
  - repo: local
    hooks:
      - id: no-polling-antipatterns
        name: Block polling script anti-patterns
        entry: scripts/check_polling_antipatterns.sh
        language: script
        types: [shell]
        require_serial: true
        exclude: ^(\.git/|phone_focus_mode/lib/tests/|tests/)

  # ===========================================================================
  # NOQA BLOCKER - Zero tolerance for noqa/type:ignore suppression comments
  # ===========================================================================
  - repo: local
    hooks:
      - id: no-noqa
        name: Block noqa comments
        entry: '(?i)#\s*(noqa|type:\s*ignore)'
        language: pygrep
        types: [python]
      - id: no-ruff-noqa
        name: Block ruff noqa file-level comments
        entry: '(?i)#\s*ruff:\s*noqa'
        language: pygrep
        types: [python]

  # ===========================================================================
  # RUFF - Fast Python linter and formatter (replaces black, isort, flake8, etc.)
  # ===========================================================================
  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.15.2
    hooks:
      # Linter - run first to catch issues
      - id: ruff
        args:
          - --fix
          - --unsafe-fixes
          - --exit-non-zero-on-fix
          - --show-fixes
        types_or: [python, pyi]
      # Formatter - run after linting
      - id: ruff-format
        types_or: [python, pyi]

  # ===========================================================================
  # MYPY - Static type checking (per-commit on changed files only)
  # Was on pre-push, but force-push diffs caused full-repo scans + OOM. On
  # pre-commit it sees only the file(s) currently staged → near-instant.
  # ===========================================================================
  - repo: https://github.com/pre-commit/mirrors-mypy
    rev: v1.13.0
    hooks:
      - id: mypy
        stages: [pre-commit]
        args:
          - --ignore-missing-imports
          - --no-error-summary
          - --disable-error-code=no-untyped-def
          - --disable-error-code=no-untyped-call
          - --disable-error-code=var-annotated
          - --disable-error-code=no-any-unimported
          - --disable-error-code=type-arg
          - --disable-error-code=no-any-return
          - --disable-error-code=misc
          - --disable-error-code=unused-ignore
          - --disable-error-code=unreachable
          - --disable-error-code=assignment
          - --disable-error-code=no-redef
          - --disable-error-code=attr-defined
          - --disable-error-code=arg-type
          - --disable-error-code=union-attr
          - --disable-error-code=call-overload
          - --disable-error-code=return-value
          - --disable-error-code=redundant-cast
          - --disable-error-code=empty-body
          - --disable-error-code=list-item
        exclude: >-
          (?x)^(
            Bash/.*|
            \.venv/.*|
            linux_configuration/scripts/single_use/misc/testsAndMisc-bash/tools/.*
          )$
        additional_dependencies:
          - types-requests
          - types-PyYAML
          - types-python-dateutil

  # ===========================================================================
  # PYLINT - Comprehensive Python linter (per-commit on changed files only)
  # Was on pre-push, but force-push diffs caused full-repo scans + OOM.
  # ===========================================================================
  - repo: https://github.com/pylint-dev/pylint
    rev: v3.3.2
    hooks:
      - id: pylint
        stages: [pre-commit]
        args:
          - --rcfile=pyproject.toml
          - --fail-under=8.0
          - --jobs=0
        additional_dependencies:
          - pytest
          - python-chess
          - requests
          - pygame
        exclude: ^(Bash/|\.venv/)

  # ===========================================================================
  # BANDIT - Security linter (per-commit on changed files only)
  # Was on pre-push, but force-push diffs caused full-repo scans + OOM.
  # ===========================================================================
  - repo: https://github.com/PyCQA/bandit
    rev: 1.7.10
    hooks:
      - id: bandit
        stages: [pre-commit]
        args:
          - -c
          - pyproject.toml
          - --severity-level=high
          - --confidence-level=medium
          - --skip=B113
        additional_dependencies: ["bandit[toml]"]
        exclude: ^(Bash/|\.venv/|tests/|.*test.*\.py$)

  # ===========================================================================
  # PYTEST + COVERAGE - Run tests and enforce 100% code coverage
  # Only tests for subpackages with changed files are run (see script).
  # Uses pytest-xdist (-n auto) to parallelize across all CPUs.
  # ===========================================================================
  - repo: local
    hooks:
      - id: pytest-coverage
        name: pytest with coverage enforcement
        entry: python scripts/pytest_changed_packages.py
        language: system
        types: [python]
        pass_filenames: true
        require_serial: true
        stages: [pre-commit]

  # ===========================================================================
  # VULTURE - Dead code detection (disabled - doesn't work well with pre-commit)
  # ===========================================================================
  # - repo: https://github.com/jendrikseipp/vulture
  #   rev: v2.13
  #   hooks:
  #     - id: vulture
  #       args:
  #         - --min-confidence=80
  #         - --exclude=.venv,Bash,__pycache__
  #       exclude: ^(Bash/|\.venv/)

  # ===========================================================================
  # PYUPGRADE - Upgrade Python syntax (disabled - incompatible with Python 3.14)
  # ===========================================================================
  # - repo: https://github.com/asottile/pyupgrade
  #   rev: v3.19.0
  #   hooks:
  #     - id: pyupgrade
  #       args:
  #         - --py310-plus

  # ===========================================================================
  # CODESPELL - Spell checking in code (expanded ignore list for non-English)
  # ===========================================================================
  - repo: https://github.com/codespell-project/codespell
    rev: v2.3.0
    hooks:
      - id: codespell
        args:
          - --skip=*.json,*.lock,*.min.js,*.min.css,.git,__pycache__,.venv,*.txt
          - --ignore-words-list=als,ans,ect,nd,som,sur,te,nam,numer,lew,sie,wil,postion,clen,ther,folow,derrive,ony,tje,noe,theses,crate,doubleclick,wile,tabel,pary,blok,bloc,proces,serwer,parametr,adres,hart,dout,metod,tekst,synonim,grup,mosty,lokal,skalar,milion,nowe,tre,hel,alph
        exclude: ^(Bash/ffmpeg-build/|LaTeX/|.*\.geojson$)

  # ===========================================================================
  # DOCFORMATTER - Format docstrings (disabled - causes recursion errors)
  # ===========================================================================
  # - repo: local
  #   hooks:
  #     - id: docformatter
  #       name: docformatter
  #       entry: docformatter
  #       language: system
  #       types: [python]
  #       args:
  #         - --in-place
  #         - --wrap-summaries=88
  #         - --wrap-descriptions=88

  # ===========================================================================
  # INTERROGATE - Docstring coverage (disabled - causes recursion on large files)
  # ===========================================================================
  # - repo: https://github.com/econchick/interrogate
  #   rev: 1.7.0
  #   hooks:
  #     - id: interrogate
  #       args:
  #         - --fail-under=0
  #         - --verbose
  #         - --ignore-init-method
  #         - --ignore-init-module
  #         - --ignore-magic
  #         - --ignore-private
  #         - --ignore-semiprivate
  #         - --exclude=Bash,.venv,__pycache__
  #       pass_filenames: false

  # ===========================================================================
  # AUTOFLAKE - Remove unused imports/variables
  # Disabled: fully redundant with ruff (F401, F841, F811) + --fix
  # ===========================================================================
  # - repo: https://github.com/PyCQA/autoflake
  #   rev: v2.3.1
  #   hooks:
  #     - id: autoflake
  #       args:
  #         - --in-place
  #         - --remove-all-unused-imports
  #         - --remove-unused-variables
  #         - --remove-duplicate-keys
  #         - --expand-star-imports

  # ===========================================================================
  # SAFETY - Check for security vulnerabilities in dependencies
  # ===========================================================================
  # Note: Safety requires API key for full functionality, disabled by default
  # - repo: https://github.com/Lucas-C/pre-commit-hooks-safety
  #   rev: v1.3.2
  #   hooks:
  #     - id: python-safety-dependencies-check
  #       files: requirements.*\.txt$

  # ===========================================================================
  # PYRIGHT - Microsoft's type checker (very strict, optional)
  # ===========================================================================
  # Uncomment to enable - can be slow and very strict
  # - repo: https://github.com/RobertCraiworthy/pyright-action
  #   rev: v1.1.350
  #   hooks:
  #     - id: pyright

  # ===========================================================================
  # CHECK JSON/YAML/TOML formatting (runs on push only — slow Node.js startup)
  # ===========================================================================
  - repo: local
    hooks:
      - id: prettier
        name: prettier (capped scope)
        # Wrapper runs prettier inside its own systemd-run scope so its
        # memory budget is independent of the outer pre-push cgroup that
        # has already accumulated page cache from pytest/mypy/pylint.
        entry: scripts/run_prettier_capped.sh
        language: system
        types_or: [yaml, json, markdown]
        exclude: >-
          (?x)^(
            Bash/.*|
            \.venv/.*|
            third_party/.*|
            \.github/skills/.*|
            docs/superpowers/(plans|specs)/.*|
            linux_configuration/report/.*|
            .*\.lock
          )$
        stages: [pre-push]

  # ===========================================================================
  # SHELLCHECK - Shell script linting
  # Wrapper batches files to avoid OOM on large repos.
  # ===========================================================================
  - repo: local
    hooks:
      - id: shellcheck
        name: shellcheck
        entry: bash -c 'printf "%s\0" "$@" | xargs -0 -n 40 shellcheck --severity=warning' --
        language: system
        types: [shell]

  # ===========================================================================
  # CHECK PYTHON LOCATION - All Python files must be under python_pkg/
  # ===========================================================================
  - repo: local
    hooks:
      - id: check-python-location
        name: check Python files are under python_pkg/
        entry: scripts/check_python_location.sh
        language: script
        types: [python]

  # ===========================================================================
  # REMOVE EMPTY DIRECTORIES - Clean up empty folders in the repo
  # ===========================================================================
  - repo: local
    hooks:
      - id: remove-empty-dirs
        name: remove empty directories
        entry: find . -type d -empty -not -path './.git/*' -delete -print
        language: system
        pass_filenames: false
        always_run: true

  # ===========================================================================
  # SECRET PATTERNS - Block commits containing sensitive data
  # ===========================================================================
  - repo: local
    hooks:
      - id: check-no-secrets
        name: check for leaked secrets
        entry: scripts/check_no_secrets.sh
        language: script
        exclude: ^(\.secret-patterns|\.pre-commit-config\.yaml|.*\.geojson)$

  # ===========================================================================
  # COMMITIZEN - Conventional commits (optional)
  # ===========================================================================
  # - repo: https://github.com/commitizen-tools/commitizen
  #   rev: v3.13.0
  #   hooks:
  #     - id: commitizen
  #     - id: commitizen-branch
  #       stages: [push]
