#!/bin/sh
# ATDD pre-commit hook — blocks commits on main/master and unregistered branches.
# Installed by `atdd init`.
#
# All ATDD_SKIP_* bypass env vars have been retired (E030, 2026-05-26).
# For genuine emergencies: atdd emergency --reason "<reason>"

set -e

# --- Emergency bypass check (E031) ---
_REPO_ROOT="${ATDD_REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || echo "")}"
if [ -n "$_REPO_ROOT" ]; then
    _BYPASS_FILE="${_REPO_ROOT}/.atdd/EMERGENCY_BYPASS"
    if [ -f "$_BYPASS_FILE" ]; then
        if find "$_BYPASS_FILE" -mmin -5 2>/dev/null | grep -q .; then
            printf "ATDD: Emergency bypass active (pre-commit). Reason: %s\n" \
                "$(head -1 "$_BYPASS_FILE" 2>/dev/null | sed 's/^reason=//' || echo 'see .atdd/EMERGENCY_BYPASS')" >&2
            exit 0
        else
            printf "ATDD: Emergency bypass file found but expired (> 5 min). Ignored.\n" >&2
        fi
    fi
fi

# --- Resolve current branch ---
BRANCH=$(git symbolic-ref --short HEAD 2>/dev/null || echo "")

# Allow: detached HEAD (CI)
if [ -z "$BRANCH" ]; then
    exit 0
fi

# --- Block all direct commits on main/master ---
case "$BRANCH" in
    main|master)
        # Allow: CI-only env bypass
        if [ "${CI:-}" = "true" ] && [ "${ATDD_ALLOW_MAIN_COMMIT:-0}" = "1" ]; then
            exit 0
        fi
        # Allow: manifest-only registration commit (atdd issue <slug> runs on main)
        # A commit whose staged set is exactly .atdd/manifest.yaml cannot cause the
        # harm this guard exists to prevent (mass code edits, bare-mode contamination).
        _STAGED=$(git diff --cached --name-only 2>/dev/null || echo "")
        if [ "$_STAGED" = ".atdd/manifest.yaml" ]; then
            exit 0
        fi
        cat >&2 <<EOF

ATDD: Commit blocked — you are on $BRANCH.

NEVER edit files directly on $BRANCH.
Always create a worktree branch FIRST, before making any changes:

  atdd branch <issue-number>

If you already have uncommitted changes, recover them:

  git stash
  atdd branch <issue-number>
  cd ../<worktree-dir>
  git stash pop

CI bypass (requires CI=true):
  CI=true ATDD_ALLOW_MAIN_COMMIT=1 git commit ...

EOF
        exit 1
        ;;
esac

# --- Verify branch is registered in manifest ---
# Extract slug from branch name (strip prefix: feat/my-slug → my-slug)
SLUG=$(echo "$BRANCH" | sed 's|^[^/]*/||')

# Find manifest file (walk up to repo root)
REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || echo "")
MANIFEST="$REPO_ROOT/.atdd/manifest.yaml"

if [ -f "$MANIFEST" ]; then
    # Check if slug appears in manifest sessions
    if ! grep -q "slug:.*$SLUG" "$MANIFEST" 2>/dev/null; then
        cat >&2 <<EOF

ATDD: Branch '$BRANCH' is not registered in .atdd/manifest.yaml.

Manifest drift detected — run to self-heal:
  atdd issue reconcile

Every branch must be created through the ATDD workflow:
  1. atdd issue <slug>    # Create issue first
  2. atdd branch <N>      # Create branch from issue

This ensures issues use the standard template, are tracked in
the manifest, and have Project v2 fields set up correctly.

For genuine emergencies: atdd emergency --reason "<reason>"

EOF
        exit 1
    fi
fi

# --- Staged file count warning (advisory only — never blocks) ---
STAGED=$(git diff --cached --name-only | wc -l | tr -d ' ')
MAX_STAGED=${ATDD_MAX_STAGED:-20}

if [ "$STAGED" -gt "$MAX_STAGED" ]; then
    echo "ATDD WARNING: $STAGED files staged. Consider splitting into smaller commits." >&2
fi

exit 0
