#!/usr/bin/env bash
# JellyTau pre-commit hook — the fast half of CLAUDE.md's "Before Committing"
# list, enforced instead of remembered.
#
# TRACES: | DR-207
#
# Install with:   bun run hooks:install      (sets core.hooksPath=scripts/hooks)
# Skip once with: git commit --no-verify
#
# What runs here is deliberately limited to gates that finish in seconds:
#
#   bun run check                        svelte-check (types)
#   bun run test                         vitest, single pass
#   scripts/check-frontend-boundary.sh   domain-taxonomy tripwire (DR-094)
#   cargo fmt --all -- --check           only when src-tauri/ is staged
#
# NOT here, on purpose: `cargo clippy` and `cargo test`. Both take minutes on a
# cold target dir, which turns every commit into a coffee break and trains
# people to reach for --no-verify. CI (.gitea/workflows/build-and-test.yml) is
# where those run; `bun run test:all` is the local equivalent.

set -uo pipefail

# Merge and rebase commits carry someone else's changes, and conflict resolution
# is exactly when a slow gate is least welcome. Let them through — CI still
# gates the merge result.
GIT_DIR_PATH="$(git rev-parse --git-dir 2>/dev/null)" || exit 0
if [ -e "$GIT_DIR_PATH/MERGE_HEAD" ] ||
  [ -d "$GIT_DIR_PATH/rebase-merge" ] ||
  [ -d "$GIT_DIR_PATH/rebase-apply" ] ||
  [ -e "$GIT_DIR_PATH/CHERRY_PICK_HEAD" ]; then
  echo "pre-commit: merge/rebase in progress — skipping checks (CI still gates the result)."
  exit 0
fi

# Nothing staged (e.g. `git commit --amend` that only edits the message): nothing
# to check.
STAGED="$(git diff --cached --name-only --diff-filter=ACMR)"
if [ -z "$STAGED" ]; then
  exit 0
fi

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

FAILED=0

run_gate() {
  label="$1"
  shift
  echo ""
  echo "🔎 pre-commit: $label"
  if ! "$@"; then
    echo "❌ pre-commit: $label failed"
    FAILED=1
  fi
}

run_gate "svelte-check (bun run check)" bun run check
run_gate "frontend tests (bun run test)" bun run test
run_gate "frontend/backend boundary" bash scripts/check-frontend-boundary.sh

# rustfmt only matters when Rust actually changed, and `cargo fmt --check` is
# cheap (no compilation) whenever it does.
if printf '%s\n' "$STAGED" | grep -q '^src-tauri/'; then
  if command -v cargo >/dev/null 2>&1; then
    echo ""
    echo "🔎 pre-commit: rustfmt (src-tauri/ is staged)"
    if ! (cd src-tauri && cargo fmt --all -- --check); then
      echo "❌ pre-commit: cargo fmt --all -- --check failed"
      echo "   fix with: cd src-tauri && cargo fmt"
      FAILED=1
    fi
  else
    echo "⚠️  pre-commit: src-tauri/ staged but cargo is not on PATH — skipping rustfmt."
  fi
fi

if [ "$FAILED" -ne 0 ]; then
  echo ""
  echo "🛑 pre-commit checks failed. Fix them, or bypass deliberately with:"
  echo "     git commit --no-verify"
  exit 1
fi

echo ""
echo "✅ pre-commit checks passed."
