#!/usr/bin/env bash
# Pre-push hook: auto-bump a vX.Y.Z patch tag whenever HEAD has commits past
# the latest version tag. Keeps setuptools-scm's derived version in lockstep
# with what's deployed, so we never ship `0.0.0+unknown` or get mismatched
# health-endpoint version strings again.
#
# Bumps once per push. Skipped when:
#   - The push is itself a tag push (avoids loops)
#   - HEAD is already tagged
#   - Env SKIP_AUTOTAG=1 is set
#
# Install:  scripts/hooks/install.sh
set -euo pipefail

if [[ "${SKIP_AUTOTAG:-0}" == "1" ]]; then
  exit 0
fi

# Read refs being pushed from stdin. If only tags are being pushed, skip.
# Format: <local-ref> <local-sha> <remote-ref> <remote-sha>
pushing_branch=0
while read -r local_ref local_sha remote_ref remote_sha; do
  [[ -z "${local_ref:-}" ]] && continue
  case "$local_ref" in
    refs/tags/*) continue ;;
    refs/heads/*) pushing_branch=1 ;;
  esac
done

if [[ "$pushing_branch" -eq 0 ]]; then
  exit 0
fi

# Find the most recent vX.Y.Z tag reachable from HEAD.
latest=$(git describe --tags --abbrev=0 --match 'v[0-9]*' 2>/dev/null || echo "")
head_sha=$(git rev-parse HEAD)

if [[ -n "$latest" ]]; then
  tag_sha=$(git rev-list -n 1 "$latest")
  if [[ "$tag_sha" == "$head_sha" ]]; then
    # HEAD already tagged — nothing to do.
    exit 0
  fi
fi

# Default to v0.0.0 if no prior tag exists.
base="${latest:-v0.0.0}"
ver="${base#v}"
IFS='.' read -r major minor patch <<<"$ver"
major="${major:-0}"; minor="${minor:-0}"; patch="${patch:-0}"
patch=$((patch + 1))
next="v${major}.${minor}.${patch}"

# Avoid collisions if the tag already exists somehow.
while git rev-parse -q --verify "refs/tags/$next" >/dev/null 2>&1; do
  patch=$((patch + 1))
  next="v${major}.${minor}.${patch}"
done

echo "[auto-tag] $base -> $next at ${head_sha:0:8}" >&2
git tag -a "$next" -m "auto-bump on push"

# Push the tag alongside the branch so they land together. Use the same
# remote the user is pushing to (first arg to pre-push).
remote="${1:-origin}"
if ! SKIP_AUTOTAG=1 git push "$remote" "$next" >&2; then
  echo "[auto-tag] failed to push tag $next; rolling back local tag" >&2
  git tag -d "$next" >&2 || true
  exit 1
fi

# If multiple remotes exist (e.g., origin + forgejo), push to all configured
# remotes so we don't end up with one mirror behind on tags.
for r in $(git remote); do
  if [[ "$r" != "$remote" ]]; then
    SKIP_AUTOTAG=1 git push "$r" "$next" >&2 || \
      echo "[auto-tag] WARN: tag $next not pushed to $r" >&2
  fi
done

exit 0
