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

usage() {
  cat >&2 <<'USAGE'
Usage: tools/new-change <slug>

Creates a numbered branch and sibling worktree for a new Blackcurrant change,
then installs dependencies in the new worktree.

Examples:
  cd "$(tools/new-change manifest-cache)"
  cd (./tools/new-change manifest-cache)   # fish

The script prints only the new worktree path to stdout. Status and guidance go
to stderr.
USAGE
}

die() {
  printf 'new-change: %s\n' "$*" >&2
  exit 1
}

if [[ $# -ne 1 ]]; then
  usage
  exit 2
fi

input_slug=$1

if ! [[ $input_slug =~ ^[a-z0-9][a-z0-9-]*[a-z0-9]$|^[a-z0-9]$ ]]; then
  die "slug must use lowercase letters, digits, and hyphens only"
fi

repo_root=$(git rev-parse --show-toplevel 2>/dev/null) ||
  die "must be run from the Blackcurrant main worktree"
current_branch=$(git -C "$repo_root" branch --show-current)

if [[ $current_branch != main ]]; then
  die "must be run from the main branch, not '$current_branch'"
fi

if [[ -n $(git -C "$repo_root" status --short) ]]; then
  die "main worktree must be clean before creating a change worktree"
fi

parent_dir=$(dirname "$repo_root")

if [[ $input_slug =~ ^[0-9]{4}-.+ ]]; then
  change_slug=$input_slug
else
  max_number=0

  while IFS= read -r branch_name; do
    if [[ $branch_name =~ ^([0-9]{4})- ]]; then
      number=$((10#${BASH_REMATCH[1]}))
      if (( number > max_number )); then
        max_number=$number
      fi
    fi
  done < <(git -C "$repo_root" for-each-ref --format='%(refname:short)' refs/heads)

  for path in "$parent_dir"/*; do
    [[ -d $path ]] || continue
    name=${path##*/}
    if [[ $name =~ ^([0-9]{4})- ]]; then
      number=$((10#${BASH_REMATCH[1]}))
      if (( number > max_number )); then
        max_number=$number
      fi
    fi
  done

  printf -v change_slug '%04d-%s' "$((max_number + 1))" "$input_slug"
fi

target_dir="$parent_dir/$change_slug"

if git -C "$repo_root" rev-parse --verify --quiet "refs/heads/$change_slug" >/dev/null; then
  die "branch '$change_slug' already exists"
fi

if [[ -e $target_dir ]]; then
  die "target worktree path already exists: $target_dir"
fi

printf 'Creating branch and worktree: %s\n' "$change_slug" >&2
git -C "$repo_root" worktree add -b "$change_slug" "$target_dir" HEAD >&2

printf 'Installing dependencies in %s\n' "$target_dir" >&2
npm --prefix "$target_dir" install >&2

printf 'Created %s\n' "$target_dir" >&2
printf 'Next:\n  cd %q\n  codex\n' "$target_dir" >&2

printf '%s\n' "$target_dir"
