#!/usr/bin/env bash
# Pre-push hook — block push of commits that touch per-machine state.
#
# Defense-in-depth: even if someone bypasses the pre-commit hook with
# `git commit --no-verify`, this hook catches per-session Bizar state
# changes before they reach the remote.
#
# Bypass: git push --no-verify (NOT recommended).

set -euo pipefail

REMOTE="$1"
URL="$2"

# Read ref updates from stdin (format: <local-ref> <local-sha> <remote-ref> <remote-sha>)
# For a force-push or new branch, the "local-sha" may be the new tip.
# We scan the names of changed files in all commits being pushed.
COMMITS=""
while read -r LOCAL_REF LOCAL_SHA REMOTE_REF REMOTE_SHA; do
  if [ -z "$LOCAL_SHA" ] || [ "$LOCAL_SHA" = "0000000000000000000000000000000000000000" ]; then
    continue
  fi
  # Tag pushes (refs/tags/*) point at existing commits; they don't introduce
  # new file changes. Skip tag-only ref updates so an annotated tag pointing
  # at a commit already pushed via master doesn't scan the full history.
  case "$LOCAL_REF" in
    refs/tags/*) continue ;;
  esac
  if [ -z "$REMOTE_SHA" ] || [ "$REMOTE_SHA" = "0000000000000000000000000000000000000000" ]; then
    # New branch — scan only the delta from the parent of LOCAL_SHA, not the
    # full reachable history (which `git log <sha>` would otherwise walk).
    PARENT_SHA=$(git rev-parse "$LOCAL_SHA^" 2>/dev/null || echo "")
    if [ -n "$PARENT_SHA" ]; then
      RANGE="$PARENT_SHA..$LOCAL_SHA"
    else
      RANGE="$LOCAL_SHA"
    fi
  else
    RANGE="$REMOTE_SHA..$LOCAL_SHA"
  fi
  if [ -z "$COMMITS" ]; then
    COMMITS="$RANGE"
  else
    COMMITS="$COMMITS $RANGE"
  fi
done

if [ -z "$COMMITS" ]; then
  exit 0
fi

BAD=$(git log --name-only --no-merges --pretty=format: $COMMITS 2>/dev/null \
  | grep -E "(^|/)\.bizar/(session-state\.json|sessions/|learning/)|(^|/)\.config/bizar/" \
  | sort -u || true)

if [ -n "$BAD" ]; then
  echo "" >&2
  echo "❌ Refusing to push to $REMOTE — these files in the commit range are per-machine and must not be pushed:" >&2
  echo "$BAD" | sed 's/^/    /' >&2
  echo "" >&2
  echo "  .bizar/ contains per-project state (memory.json, graph/, plans, scripts)." >&2
  echo "  These paths contain per-session state or local telemetry." >&2
  echo "" >&2
  echo "  To override (NOT recommended): git push --no-verify" >&2
  exit 1
fi
