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

# Pre-push hook: validates v* tag pushes before they reach the remote.
#
# Checks:
#   1. package.json version matches the tag
#   2. CHANGELOG.md has a "## [{version}] - {date}" entry
#   3. CI passed upstream on GitHub for the tagged commit
#
# In non-interactive shells (no tty), warnings auto-proceed instead of
# prompting. Hard failures (version mismatch, missing changelog) always block.

# Detect if we can prompt
CAN_PROMPT=false
if [[ -t 0 ]] || [[ -e /dev/tty ]]; then
  # Verify /dev/tty is actually usable
  if echo -n "" > /dev/tty 2>/dev/null; then
    CAN_PROMPT=true
  fi
fi

prompt_or_continue() {
  local msg="$1"
  if $CAN_PROMPT; then
    read -p "$msg [y/N] " -n 1 -r </dev/tty
    echo ""
    [[ $REPLY =~ ^[Yy]$ ]] || exit 1
  else
    echo "$msg — auto-proceeding (non-interactive)"
  fi
}

while read -r local_ref local_sha remote_ref remote_sha; do
  # Only validate v* tag pushes
  if [[ "$local_ref" != refs/tags/v* ]]; then
    continue
  fi

  # Skip tag deletions
  if [[ "$local_sha" == "0000000000000000000000000000000000000000" ]]; then
    continue
  fi

  TAG="${local_ref#refs/tags/}"
  VERSION="${TAG#v}"

  echo "Validating release $TAG..."

  # --- 1. package.json version must match the tag ---
  PKG_VERSION=$(jq -r .version package.json)
  if [[ "$PKG_VERSION" != "$VERSION" ]]; then
    echo ""
    echo "ABORT: package.json version is $PKG_VERSION but tag is $TAG"
    echo "Run: jq --arg v '$VERSION' '.version = \$v' package.json > tmp && mv tmp package.json"
    exit 1
  fi
  echo "  package.json version: $PKG_VERSION ✓"

  # --- 2. CHANGELOG.md must have an entry for this version ---
  if [[ ! -f CHANGELOG.md ]]; then
    echo ""
    echo "ABORT: CHANGELOG.md not found"
    exit 1
  fi

  if ! grep -q "^## \[$VERSION\] - " CHANGELOG.md; then
    echo ""
    echo "ABORT: CHANGELOG.md has no entry for this release"
    echo "Expected heading: ## [$VERSION] - $(date +%Y-%m-%d)"
    echo ""
    echo "Write the changelog entry first. See CLAUDE.md for guidelines."
    exit 1
  fi
  echo "  CHANGELOG.md: entry found ✓"

  # --- 3. CI must have passed on GitHub for this commit ---
  # Resolve annotated tag to its underlying commit
  COMMIT=$(git rev-list -n 1 "$TAG" 2>/dev/null || git rev-parse HEAD)

  if ! command -v gh &>/dev/null; then
    echo "  CI check: skipped (gh CLI not installed)"
    continue
  fi

  CHECK_JSON=$(gh api "repos/{owner}/{repo}/commits/$COMMIT/check-runs" 2>/dev/null || echo "")

  if [[ -z "$CHECK_JSON" ]]; then
    echo "  CI check: skipped (could not reach GitHub API)"
    continue
  fi

  TOTAL=$(echo "$CHECK_JSON" | jq -r '.total_count // 0' 2>/dev/null || echo "0")

  if [[ "$TOTAL" -eq 0 ]] 2>/dev/null; then
    MAIN_SHA=$(git rev-parse origin/main 2>/dev/null || echo "")
    if [[ "$COMMIT" != "$MAIN_SHA" ]]; then
      echo ""
      echo "WARNING: No CI runs found for $COMMIT"
      prompt_or_continue "Push tag anyway?"
    else
      echo "  CI check: no runs yet (commit is tip of origin/main)"
    fi
  else
    FAILED=$(echo "$CHECK_JSON" | jq '[.check_runs // [] | .[] | select(.conclusion == "failure")] | length' 2>/dev/null || echo "0")
    PENDING=$(echo "$CHECK_JSON" | jq '[.check_runs // [] | .[] | select(.status != "completed")] | length' 2>/dev/null || echo "0")

    if [[ "$FAILED" -gt 0 ]] 2>/dev/null; then
      echo ""
      echo "ABORT: CI failed for commit $COMMIT"
      echo "Check: https://github.com/tobi/qmd/commit/$COMMIT"
      exit 1
    fi

    if [[ "$PENDING" -gt 0 ]] 2>/dev/null; then
      echo ""
      echo "WARNING: CI still running for commit $COMMIT ($PENDING pending)"
      prompt_or_continue "Push tag anyway?"
    else
      echo "  CI check: all passed ✓"
    fi
  fi

  echo "All checks passed for $TAG ✓"
done

exit 0
