#!/usr/bin/env bash
#
# Chump pre-push hook: gap-preflight guard + auto-merge armed guard.
#
# Guard 1 (gap-preflight): Automatically extracts gap IDs from commits being
# pushed and runs gap-preflight.sh against them. Aborts if any gap is already
# `done` on origin/main or claimed by another session — preventing wasted CI
# runs and duplicate work landing.
# Bypass: CHUMP_GAP_CHECK=0 git push  (use when gap IDs in commit bodies cause false positives)
#
# Guard 2 (auto-merge armed): Queries `gh pr view` for the target branch and
# aborts if the PR already has auto-merge armed. This prevents the PR #52
# footgun where 11 commits were lost because an agent kept pushing after
# auto-merge was armed and GitHub captured the branch at first-CI-green.
# Bypass: CHUMP_AUTOMERGE_OVERRIDE=1 git push  (emergency use only)
#
# Install once: ./scripts/install-hooks.sh

set -euo pipefail

# Never block pushes to main/master — those go through PR only.
REMOTE="$1"
# $2 is the remote URL; unused here.

# Read the list of refs being pushed from stdin (format: local_ref local_sha remote_ref remote_sha)
while read -r local_ref local_sha remote_ref remote_sha; do
    branch="${remote_ref#refs/heads/}"

    # Skip if pushing to main/master (branch protection handles that).
    [[ "$branch" == "main" || "$branch" == "master" ]] && continue

    # -----------------------------------------------------------------------
    # Guard 2: Auto-merge armed check (INFRA-PUSH-LOCK)
    # Check before gap-preflight so a fast fail doesn't require running the
    # slower preflight script when auto-merge is the real problem.
    # -----------------------------------------------------------------------
    if [[ "${CHUMP_AUTOMERGE_OVERRIDE:-0}" == "1" ]]; then
        echo "[pre-push] CHUMP_AUTOMERGE_OVERRIDE=1 — skipping auto-merge armed check for $branch" >&2
    elif command -v gh &>/dev/null; then
        # gh pr view exits non-zero when no PR exists — we catch that and allow.
        automerge_armed=$(gh pr view "$branch" --json state,autoMergeRequest \
            --jq 'if .state == "OPEN" then (.autoMergeRequest != null | tostring) else "false" end' 2>/dev/null || echo "no_pr")

        if [[ "$automerge_armed" == "true" ]]; then
            echo "" >&2
            echo "[pre-push] BLOCKED: PR for branch '$branch' already has auto-merge armed." >&2
            echo "[pre-push] Pushing more commits after auto-merge is armed can cause commit" >&2
            echo "[pre-push] loss — GitHub captures the branch at first-CI-green and drops" >&2
            echo "[pre-push] anything pushed afterward (PR #52 incident, 2026-04-18, lost 11 commits)." >&2
            echo "" >&2
            echo "[pre-push] Options:" >&2
            echo "[pre-push]   • Open a NEW PR from a fresh worktree for additional work." >&2
            echo "[pre-push]   • Emergency bypass: CHUMP_AUTOMERGE_OVERRIDE=1 git push" >&2
            echo "" >&2
            exit 1
        fi
        # "false" → PR exists but no auto-merge → allow
        # "no_pr" → gh errored (no PR) → allow
    else
        # gh not installed or not authenticated — warn but do not block.
        echo "[pre-push] WARNING: 'gh' not found or not authenticated; skipping auto-merge armed check." >&2
    fi

    # -----------------------------------------------------------------------
    # Guard 1: Gap-preflight check
    # -----------------------------------------------------------------------

    # Skip if bypassed.
    [[ "${CHUMP_GAP_CHECK:-1}" == "0" ]] && continue

    # Determine the range of new commits being pushed.
    # If remote sha is all zeros, it's a new branch — compare against origin/main.
    if [[ "$remote_sha" == "0000000000000000000000000000000000000000" ]]; then
        base=$(git merge-base HEAD "origin/main" 2>/dev/null || echo "")
        [[ -z "$base" ]] && continue
        range="${base}..${local_sha}"
    else
        range="${remote_sha}..${local_sha}"
    fi

    # Extract gap IDs from commit subjects only (%s), not bodies.
    # Using %s %b caused false positives when commit bodies mentioned gap IDs
    # in passing (e.g. cleanup commits referencing a gap they didn't implement).
    GAP_IDS=$(git log "$range" --format="%s" 2>/dev/null \
        | grep -oE '\b[A-Z]+-[0-9]+\b' | sort -u || true)

    [[ -z "$GAP_IDS" ]] && continue

    REPO_ROOT="$(git rev-parse --show-toplevel)"
    PREFLIGHT="$REPO_ROOT/scripts/gap-preflight.sh"

    [[ ! -x "$PREFLIGHT" ]] && continue

    echo "[pre-push] Checking gap status for: $(echo $GAP_IDS | tr '\n' ' ')" >&2

    # shellcheck disable=SC2086
    if ! "$PREFLIGHT" $GAP_IDS; then
        echo "[pre-push] Push blocked: one or more gaps already done or claimed." >&2
        echo "[pre-push] This branch's work may already be on main." >&2
        echo "[pre-push] Run: git show origin/main:docs/gaps.yaml | grep -A8 'id: GAP-XYZ'" >&2
        echo "[pre-push] Bypass (when commit bodies cause false positives): CHUMP_GAP_CHECK=0 git push" >&2
        exit 1
    fi
done

exit 0
