#!/usr/bin/env bash
# git-hooks/branch-name-check.sh
#
# Validates the current branch name against the platform convention:
#   {type}/{slug}[_CU-{id}]
#
#   type = feature | fix | bug | hotfix | infra | chore | refactor | docs | proposal
#          (fix and bug are both ordinary bug fixes off develop; hotfix = an
#           URGENT fix branched from master/production)
#          Source of truth for this list: CONTRIBUTING.md "Branch naming".
#   slug = lowercase alphanumeric + hyphens (must start with alphanumeric)
#   id   = ClickUp task id — when present, must satisfy
#          scripts/checks/check-cu-id.sh (≥6 chars, ≥1 digit, ≥1 letter).
#          Placeholders like CU-pending / CU-tbd / CU-xxx are rejected.
#
# Two modes, driven by REQUIRE_CU_ID from git-hooks/config.env
# (the orchestrator sources it before invoking this hook):
#   - REQUIRE_CU_ID=true   → branch MUST include _CU-{valid-id}
#   - REQUIRE_CU_ID=false  → _CU-{id} is optional; when present the id is
#                            still validated (no placeholder workarounds)
#
# Invoked from .git/hooks/pre-commit AND .git/hooks/pre-push (see
# scripts/install-git-hooks.sh).
#
# Skipped when on master/main/develop/release/*.
#
# Exit codes:
#   0 = pass (or skipped for shared branches)
#   1 = block (prints fix hint to stderr)

set -euo pipefail

BRANCH="$(git symbolic-ref --short HEAD 2>/dev/null || echo '')"

# Detached HEAD or no branch — let other hooks handle it.
if [[ -z "$BRANCH" ]]; then
  exit 0
fi

# Shared branches are not the concern of this hook.
case "$BRANCH" in
  master|main|develop) exit 0 ;;
  release/*)           exit 0 ;;
esac

REQUIRE_CU_ID="${REQUIRE_CU_ID:-false}"

# Structural regexes. Capture groups:
#   strict  → [1] = type, [2] = id
#   lenient → [1] = type, [2] = "_CU-{id}" (whole optional group), [3] = id
# Type list mirrors CONTRIBUTING.md "Branch naming" (the source of truth) — keep in sync.
STRICT_REGEX='^(feature|fix|bug|hotfix|infra|chore|refactor|docs|proposal)/[a-z0-9][a-z0-9-]*_CU-([a-zA-Z0-9]+)$'
LENIENT_REGEX='^(feature|fix|bug|hotfix|infra|chore|refactor|docs|proposal)/[a-z0-9][a-z0-9-]*(_CU-([a-zA-Z0-9]+))?$'

# The CU-id validator lives in the PLATFORM, not in the consumer repo —
# resolve self-relative so this script works both in the bewith-docs repo
# itself and from `~/.claude/plugins/cache/bewith/git-hooks/` when invoked
# via `core.hooksPath` in any consumer repo.
SCRIPT_PATH="$(readlink -f "${BASH_SOURCE[0]}" 2>/dev/null || python3 -c 'import os,sys; print(os.path.realpath(sys.argv[1]))' "${BASH_SOURCE[0]}")"
PLATFORM_DIR="$(cd "$(dirname "$SCRIPT_PATH")/.." && pwd)"
VALIDATOR="${PLATFORM_DIR}/scripts/checks/check-cu-id.sh"

validate_cu_id() {
  local id="$1"
  if [[ ! -f "$VALIDATOR" ]]; then
    echo "✗ branch-name-check: shared CU-id validator missing at $VALIDATOR" >&2
    return 2
  fi
  echo "CU-${id}" | bash "$VALIDATOR" --label "branch '$BRANCH'" >/dev/null 2>&1
}

fail_structure() {
  local required_form="$1"
  cat >&2 <<EOF
✗ branch-name-check: branch '${BRANCH}' does not match the platform structure.

Required format:
  ${required_form}

Where:
  type = feature | fix | bug | hotfix | infra | chore | refactor | docs | proposal
  slug = lowercase alphanumeric + hyphens (must start with alphanumeric)
  id   = ClickUp task id (≥6 chars, ≥1 digit, ≥1 letter — placeholders rejected)

Examples:
  feature/csv-export_CU-86c8aa123
  bug/invoice-rounding_CU-86c8bb456

To rename the current branch:
  git branch -m {type}/{slug}[_CU-{id}]
EOF
  exit 1
}

fail_cu_id() {
  local bad_id="$1"
  cat >&2 <<EOF
✗ branch-name-check: branch '${BRANCH}' uses an invalid CU-id (CU-${bad_id}).

The CU-id must be ≥6 alphanumeric chars and contain at least one digit AND
at least one letter. Placeholders like CU-pending, CU-tbd, CU-xxx, or
CU-000000 are rejected by design — they don't reference a real ClickUp task.

If this branch isn't tied to a ClickUp task, drop the suffix entirely:
  git branch -m {type}/{slug}

Otherwise rename with a real CU-id:
  git branch -m {type}/{slug}_CU-<real-id>
EOF
  exit 1
}

if [[ "$REQUIRE_CU_ID" == "true" ]]; then
  if [[ ! "$BRANCH" =~ $STRICT_REGEX ]]; then
    fail_structure "{type}/{slug}_CU-{id}"
  fi
  CU_ID="${BASH_REMATCH[2]}"
  if ! validate_cu_id "$CU_ID"; then
    fail_cu_id "$CU_ID"
  fi
  exit 0
fi

# Lenient mode: suffix optional, but if present the id must still validate.
if [[ ! "$BRANCH" =~ $LENIENT_REGEX ]]; then
  fail_structure "{type}/{slug}[_CU-{id}]"
fi

CU_ID="${BASH_REMATCH[3]:-}"
if [[ -n "$CU_ID" ]]; then
  if ! validate_cu_id "$CU_ID"; then
    fail_cu_id "$CU_ID"
  fi
fi

exit 0
