#!/usr/bin/env bash
# Description: one-click command to check for a new mise version and create a PR to update core/mise/version.txt.

set -euo pipefail

repo_root="$(git rev-parse --show-toplevel)"
cd "$repo_root"

# Check that we're on the main branch
current_branch="$(git branch --show-current)"
if [[ "$current_branch" != "main" ]]; then
  echo "Error: must be on 'main' branch, currently on '$current_branch'" >&2
  exit 1
fi

# Pull latest changes from the canonical railpack remote
canonical_repo="railwayapp/railpack"
canonical_url="https://github.com/$canonical_repo"
remote_name=$(git remote -v | grep "$canonical_repo" | head -n1 | awk '{print $1}')

if [[ -n "$remote_name" ]]; then
  echo "Updating from remote: $remote_name ($canonical_url)"
  git fetch "$remote_name" main
  git pull "$remote_name" main
  base_branch="$remote_name/main"
else
  echo "Updating from URL: $canonical_url"
  git fetch "$canonical_url" main
  git pull "$canonical_url" main
  base_branch="FETCH_HEAD"
fi

# Require clean working tree for tracked files
if [[ -n "$(git status --porcelain --untracked-files=no)" ]]; then
  echo "Error: tracked files are dirty. Commit or stash first." >&2
  exit 1
fi

# Tooling checks
if ! command -v gh >/dev/null 2>&1; then
  echo "Error: gh CLI is required (brew install gh)." >&2
  exit 1
fi

# Get latest mise tag via GitHub API
latest_tag="$(gh release view --repo jdx/mise --json tagName --jq .tagName)"
if [[ -z "$latest_tag" ]]; then
  echo "Error: could not determine latest mise release tag" >&2
  exit 1
fi
latest="${latest_tag#v}"

file="$repo_root/core/mise/version.txt"
if [[ ! -f "$file" ]]; then
  echo "Error: $file not found" >&2
  exit 1
fi

branch="chore/update-mise-$latest"
if git show-ref --verify --quiet "refs/heads/$branch"; then
  echo "Local branch $branch already exists." >&2
  exit 1
fi

git switch -c "$branch" "$base_branch"

# Write the new version to version.txt
printf "%s" "$latest" > "$file"

new="$(cat "$file")"
if [[ "$new" != "$latest" ]]; then
  echo "Error: failed to update version in $file" >&2
  exit 1
fi

# although there are other updates below that are NOT tied to mise, linking all maint work to a mise upgrade
# eliminates daily PRs which would be annoying and groups these changes with important updates (mise versions)
# which impact our users.
if git diff --quiet -- "$file"; then
  echo "mise version already set to $latest. Nothing to do."
  exit 0
fi

# `fix` scope because mise versions do impact the end-user functionality
git add -- "$file"
git commit -m "fix: update mise to $latest"

# Update snapshots before running any assertion tests — a new mise version
# will always produce different snapshots, so assertions must come after.
mise run test-update-snapshots
if ! git diff --cached --quiet; then
  git commit -F "$(git rev-parse --git-dir)/COMMIT_EDITMSG"
fi

echo "Upgrading go and mise packages..."
mise run upgrade
if [[ -n "$(git status --porcelain go.mod go.sum)" ]]; then
  git add go.mod go.sum docs/package.json mise.lock docs/bun.lock
  git commit -m "chore: update go, mise, and bun packages"
fi

echo "Running autofix fixes..."
mise run fix
if [[ -n "$(git status --porcelain --untracked-files=no)" ]]; then
  git add .
  git commit -m "refactor: modernize code with go fix"
fi

echo "Running checks and linting..."
mise run check
if [[ -n "$(git status --porcelain --untracked-files=no)" ]]; then
  git add .
  git commit -m "style: fix formatting"
fi

echo "Updating test files..."
mise --cd examples/python-uv-latest-locked upgrade --local
if [[ -n "$(git status --porcelain --untracked-files=no)" ]]; then
  git add examples/python-uv-latest-locked
  git commit -m "test: update mise lock with latest version"
fi

echo "Updating docs changelog from GitHub releases..."
changelog_file="docs/src/content/docs/changelog.md"
if mise run docs-generate-changelog; then
  if [[ -n "$(git status --porcelain -- "$changelog_file")" ]]; then
    git add -- "$changelog_file"
    git commit -m "docs: updated changelog"
  fi
else
  echo "Error: failed to generate docs changelog (continuing upgrade)" >&2
fi

# Push the branch (needed in CI and good practice locally)
git push -u origin "$branch"

gh pr create \
  --repo "$canonical_repo" \
  --title "chore: mise update $latest" \
  --body "Update mise to $latest"
