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

# Usage ------------------------------------------------------------------
usage() {
  cat <<EOF
Usage: $(basename "$0") <bump>

  bump      Version bump kind passed to 'uv version --bump'
            (patch, minor, major, etc.)

Examples:
  $(basename "$0") patch
  $(basename "$0") minor
EOF
  exit 1
}

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

PROJECT_DIR="$(cd "$(dirname "$(realpath "${BASH_SOURCE[0]}")")/.." && pwd)"
cd "$PROJECT_DIR"

BUMP="$1"

# Helpers ----------------------------------------------------------------
is_jj() { [[ -d "$PROJECT_DIR/.jj" ]]; }

check_clean() {
  if is_jj; then
    if [[ -n "$(jj diff --summary 2>/dev/null)" ]]; then
      echo "error: working copy is not clean (jj diff shows changes)" >&2
      exit 1
    fi
  else
    if [[ -n "$(git status --porcelain)" ]]; then
      echo "error: working copy is not clean (git status shows changes)" >&2
      exit 1
    fi
  fi
}

# Lint & type-check
echo "==> Running linters and type checkers..."
just lint

# Ensure working copy is clean
echo -n "==> Checking working copy is clean... "
check_clean
echo "    OK"

# CHANGELOG.md is hand-authored under an `## Unreleased` heading; this
# script promotes that heading to the new version and dates it.
# Make sure that the Unreleased section is correctly there

UNRELEASED_COUNT="$(grep -c '^## Unreleased$' CHANGELOG.md || true)"
if [[ "$UNRELEASED_COUNT" -eq 0 ]]; then
  echo "error: CHANGELOG.md has no '## Unreleased' section to promote" >&2
  exit 1
elif [[ "$UNRELEASED_COUNT" -gt 1 ]]; then
  echo "error: CHANGELOG.md has ${UNRELEASED_COUNT} '## Unreleased' sections; expected exactly one" >&2
  exit 1
fi

# Bump version and check tag
OLD_VERSION="$(uv version --short)"
NEW_VERSION="$(uv version --bump "$BUMP" --dry-run --short)"
TAG="v${NEW_VERSION}"
RELEASE_DATE="$(date +%Y-%m-%d)"

echo "==> Bumping $BUMP version..."
echo "    Current version: $OLD_VERSION"
echo "    New version:     $NEW_VERSION"
echo "    Tag:             $TAG"
echo "    Date:            $RELEASE_DATE"

if git rev-parse -q --verify "refs/tags/$TAG" >/dev/null 2>&1; then
  echo "error: tag '$TAG' already exists" >&2
  echo "error: refusing to bump $BUMP version" >&2
  exit 1
fi
uv version --bump "$BUMP"

# Promote CHANGELOG `Unreleased` to the new version
echo "==> Promoting CHANGELOG Unreleased -> ${NEW_VERSION} (${RELEASE_DATE})"
sed -i "s/^## Unreleased$/## ${NEW_VERSION} \xe2\x80\x94 ${RELEASE_DATE}/" CHANGELOG.md

# Commit
COMMIT_MSG="chore(release): $(uv version)"
echo "==> Committing: $COMMIT_MSG"

if is_jj; then
  jj commit -m "$COMMIT_MSG"
else
  git add pyproject.toml CHANGELOG.md
  git commit -m "$COMMIT_MSG"
fi

# Build the tag annotation from the just-promoted CHANGELOG section.
# Title is "release: $(uv version)"; body is the section content (the
# lines between the new `## <ver> ...` heading and the next `## ` heading).
TAG_TITLE="release: $(uv version)"
TAG_BODY="$(awk -v ver="$NEW_VERSION" -v prev="$OLD_VERSION" '
  $0 ~ "^## " ver "( |$)" { capture = 1; next }
  capture && /^## / {
    if ($0 !~ "^## " prev "( |$)") {
      printf "error: expected next changelog heading to be %s, got: %s\n", \
        "## " prev, $0 > "/dev/stderr"
      exit 2
    }
    exit
  }
  capture { print }
' CHANGELOG.md)"

# Tag
echo "==> Tagging $TAG"
if is_jj; then
  jj git import 2>/dev/null || true
fi
printf '%s\n\n%s\n' "$TAG_TITLE" "$TAG_BODY" |
  git tag -a "$TAG" --cleanup=verbatim -F -
if is_jj; then
  jj git import 2>/dev/null || true
fi

echo ""
echo "Done! Created tag: ${TAG}"
echo "To publish, push the tag:  git push origin ${TAG}"
