#!/usr/bin/env bash
set -euo pipefail

# Fast, non-compiling by default: pre-push only runs the M5 reader-inventory
# freshness check (pure Python, no compile). Set WENLAN_PUSH_FULL=1 to also
# run the local affected-closure run (route-catalog test + the fail-closed
# ci_test_plan.py planner). CI owns clippy, tests, the route-catalog check,
# and platform proofs on every push regardless of this setting.

ZERO_SHA="0000000000000000000000000000000000000000"
all_changed=""

while read -r local_ref local_sha remote_ref remote_sha; do
    [ -z "${local_ref:-}" ] && continue
    [ "$local_sha" = "$ZERO_SHA" ] && continue
    [ "$local_ref" = "(delete)" ] && continue
    case "$local_ref" in
        refs/tags/*) continue ;;
    esac

    if [ "$remote_sha" = "$ZERO_SHA" ]; then
        base=$(git merge-base "$local_sha" origin/main 2>/dev/null \
            || git rev-list --max-parents=0 "$local_sha" | head -n 1)
    else
        base=$(git merge-base "$local_sha" origin/main 2>/dev/null || echo "$remote_sha")
    fi
    changed=$(git diff --name-only --diff-filter=ACMRD "$base" "$local_sha")
    [ -n "$changed" ] && all_changed=$(printf '%s\n%s' "$all_changed" "$changed")
done

all_changed=$(printf '%s' "$all_changed" | sed '/^$/d' | sort -u)
if [ -z "$all_changed" ]; then
    echo "Pre-push: no changed branch files; skipping local checks."
    exit 0
fi

if command -v python3 >/dev/null 2>&1; then
    PYTHON_BIN=python3
elif command -v python >/dev/null 2>&1; then
    PYTHON_BIN=python
else
    echo "FAIL: Python is required for affected-test planning." >&2
    exit 1
fi

if printf '%s' "$all_changed" | grep -Eq '^crates/(wenlan-core|wenlan-server)/|^scripts/m5-reader-sweep\.py$'; then
    "$PYTHON_BIN" scripts/m5-reader-sweep.py --check || {
        echo "FAIL: the M5 reader inventory is stale. Run python3 scripts/m5-reader-sweep.py --update-inventory, review the diff, and stage crates/wenlan-core/contracts/m5-reader-manifest-inventory.md."
        exit 1
    }

    echo "Pre-push: fast drift gates passed."
fi

if [ "${WENLAN_PUSH_FULL:-}" != "1" ]; then
    echo "Pre-push: fast checks only (set WENLAN_PUSH_FULL=1 for the local affected-closure run); CI owns clippy, tests, and the route catalog."
    exit 0
fi

if printf '%s' "$all_changed" | grep -Eq '^crates/(wenlan-core|wenlan-server)/|^scripts/m5-reader-sweep\.py$'; then
    route_catalog_test='lint::serving::tests::review_tests::route_catalog_freezes_exact_global_and_scoped_keys'
    route_catalog_out=$(cargo test -p wenlan-core --lib -- "$route_catalog_test" 2>&1) && route_catalog_rc=0 || route_catalog_rc=$?
    echo "$route_catalog_out"
    if [ "$route_catalog_rc" -eq 0 ] && printf '%s' "$route_catalog_out" | grep -Fq 'test result: ok. 1 passed'; then
        :
    elif printf '%s' "$route_catalog_out" | grep -Fq 'running 0 tests'; then
        echo "FAIL: the route-catalog gate matched no test; the test was renamed or moved. Update the filter in .githooks/pre-push and scripts/git-hooks.test.sh."
        exit 1
    else
        echo "FAIL: the sensitive-read route catalog changed. Add or move the route in SCOPED/GLOBAL in crates/wenlan-core/src/lint/serving_review_test.rs (see crates/wenlan-server/AGENTS.md, \"Adding or rescoping a route\")."
        exit 1
    fi
fi

changed_json=$(printf '%s\n' "$all_changed" | "$PYTHON_BIN" -c \
    'import json, sys; print(json.dumps([line.rstrip("\n") for line in sys.stdin if line.rstrip("\n")]))')

echo "Pre-push: running affected package closure checks..."
"$PYTHON_BIN" scripts/ci_test_plan.py local \
    --changed-files-json "$changed_json" \
    --level push
echo "Pre-push: affected checks passed; CI owns broader integration/platform proofs."
