#!/usr/bin/env bash
# TurboQuantDB pre-commit hook
# Runs fast checks on every commit; runs a performance check when src/ changes.
#
# Install once with:  bash scripts/install_hooks.sh
# Or on Windows:      pwsh scripts/install_hooks.ps1

set -euo pipefail

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

pass() { echo -e "${GREEN}[pre-commit] $*${NC}"; }
warn() { echo -e "${YELLOW}[pre-commit] $*${NC}"; }
fail() { echo -e "${RED}[pre-commit] FAIL — $*${NC}"; exit 1; }

# ── 0. Skip all checks for documentation-only commits ─────────────────────────
# A commit is doc-only when every staged file matches one of these patterns:
#   *.md, *.txt, docs/*, website/*, .github/ISSUE_TEMPLATE/*, PULL_REQUEST_TEMPLATE.md
STAGED=$(git diff --cached --name-only)
NON_DOC=$(echo "$STAGED" | grep -Ev \
    '^(docs/|website/|\.github/ISSUE_TEMPLATE/|\.github/PULL_REQUEST_TEMPLATE\.md|CHANGELOG\.md|README\.md|CODE_OF_CONDUCT\.md|CONTRIBUTING\.md|.*\.txt$|.*\.md$)' \
    || true)

if [ -z "$NON_DOC" ] && [ -n "$STAGED" ]; then
    pass "doc-only commit — skipping Rust checks"
    exit 0
fi

# ── 0b. Version sync — pyproject.toml is the single source of truth ───────────
# Read the version from pyproject.toml and auto-update Cargo.toml if they differ.
PY_VER=$(grep '^version = ' pyproject.toml 2>/dev/null | head -1 | sed 's/^version = "//;s/"$//')
CARGO_VER=$(grep '^version = ' Cargo.toml 2>/dev/null | head -1 | sed 's/^version = "//;s/"$//')
if [ -n "$PY_VER" ] && [ "$PY_VER" != "$CARGO_VER" ]; then
    warn "version mismatch — syncing Cargo.toml ($CARGO_VER → $PY_VER)"
    if [[ "$OSTYPE" == "darwin"* ]]; then
        sed -i '' "s/^version = \"${CARGO_VER}\"/version = \"${PY_VER}\"/" Cargo.toml
    else
        sed -i "s/^version = \"${CARGO_VER}\"/version = \"${PY_VER}\"/" Cargo.toml
    fi
    git add Cargo.toml
    pass "Cargo.toml synced to $PY_VER"
fi

# ── 1. Formatting ──────────────────────────────────────────────────────────────
echo -n "[pre-commit] cargo fmt check ... "
if ! cargo fmt --all -- --check 2>/dev/null; then
    echo ""
    fail "unformatted Rust code. Run: cargo fmt --all"
fi
pass "fmt ok"

# ── 2. Compile check ───────────────────────────────────────────────────────────
echo -n "[pre-commit] cargo check ... "
if ! cargo check -q 2>/dev/null; then
    echo ""
    fail "compilation error"
fi
pass "compile ok"

# ── 3. Unit tests ──────────────────────────────────────────────────────────────
echo -n "[pre-commit] cargo test --lib ... "
if ! cargo test -q --lib 2>/dev/null; then
    echo ""
    fail "unit tests failed"
fi
pass "unit tests ok"

# ── 4. Build & reinstall into active env when src/ is touched ────────────────
SRC_CHANGED=$(git diff --cached --name-only | grep -c '^src/' || true)

if [ "${SRC_CHANGED}" -gt 0 ]; then
    command -v maturin &>/dev/null || fail "maturin not found in PATH (install with: pip install maturin)"

    # Detect Python executable — prefer the active venv if present.
    if [ -n "${VIRTUAL_ENV:-}${CONDA_PREFIX:-}" ]; then
        PYTHON="python"
    else
        PYTHON=""
        for py in python python3; do
            if command -v "$py" &>/dev/null; then
                PYTHON="$py"
                break
            fi
        done
    fi
    [ -n "$PYTHON" ] || fail "python not found in PATH"

    echo "[pre-commit] building and installing into $("$PYTHON" -c 'import sys; print(sys.executable)') (${SRC_CHANGED} src/ file(s) changed)"
    echo -n "[pre-commit] maturin develop --release ... "
    if ! maturin develop --release >/dev/null 2>&1; then
        echo ""
        fail "maturin develop failed"
    fi
    pass "maturin develop ok"

    echo -n "[pre-commit] python import smoke ... "
    if ! "$PYTHON" -c "import tqdb; _=tqdb.Database; print('ok')" >/dev/null 2>&1; then
        echo ""
        fail "installed wheel import smoke failed"
    fi
    pass "python smoke ok"

    # ── 5. Performance check (still only when src/ is touched) ──────────────
    if [ -f "benchmarks/precommit_perf_check.py" ]; then
        echo -n "[pre-commit] perf check ... "
        if ! "$PYTHON" benchmarks/precommit_perf_check.py \
                --baseline benchmarks/perf_baseline.json 2>&1; then
            exit 1
        fi
    else
        warn "skipping perf check — benchmarks/precommit_perf_check.py not found"
    fi
else
    warn "skipping wheel build/install + perf check — no src/ files staged"
fi

pass "all checks passed"
