#!/usr/bin/env bash
# ============================================================
# PedScribe release helper — one command to tag a new version.
#
# Usage:
#   scripts/release.sh 6.1.1                 # bump to 6.1.1
#   scripts/release.sh 6.1.1 --push          # also git push + tag push
#
# What it does:
#   1. Updates version in root package.json
#   2. Updates version in mobile/package.json
#   3. Updates versionName + bumps versionCode in Android build.gradle
#   4. Commits the version bump
#   5. (optional) git push + push the new tag
#
# It does NOT:
#   - Build the Docker image (run `docker compose build`/`up -d` yourself
#     or wire it to a deploy script / CI hook)
#   - Build the Android APK itself. Forgejo CI does that
#     (.forgejo/workflows/android-apk.yml): any branch push builds a signed
#     APK as a 30-day workflow artifact, and a v* tag push additionally
#     attaches it to a Forgejo release, which is what Obtainium tracks for
#     updates. So --push is all you need to ship a build.
#   - Publish the release itself. CI does that on the tag push; there is no
#     manual publish step to run.
# ============================================================

set -euo pipefail

VERSION="${1:-}"
PUSH=false
for arg in "${@:2}"; do
  case "$arg" in
    --push) PUSH=true ;;
  esac
done

if [[ -z "$VERSION" ]]; then
  echo "usage: $0 <version>  [--push]"
  echo "       example: $0 6.1.1 --push"
  exit 1
fi
if ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
  echo "ERROR: version must be semver X.Y.Z (e.g. 6.1.1). got: $VERSION" >&2
  exit 1
fi

ROOT="$(cd "$(dirname "$0")/.." && pwd)"
cd "$ROOT"

if [[ -n "$(git status --porcelain)" ]]; then
  echo "ERROR: working tree has uncommitted changes. commit or stash first." >&2
  git status --short >&2
  exit 1
fi

echo "==> Bumping to v$VERSION"

# Bump a package.json "version" field without needing node/jq.
# Only touches the first top-level "version": "…" line, which is the
# canonical location npm puts it. Fragile only if someone hand-wrote
# a nested "version" ABOVE the top-level one.
bump_pkg_version() {
  local file="$1" new="$2"
  sed -i -E "0,/(\"version\"[[:space:]]*:[[:space:]]*\")[^\"]+(\")/ s//\1${new}\2/" "$file"
}

bump_pkg_version package.json "$VERSION"
echo "    updated package.json"
bump_pkg_version mobile/package.json "$VERSION"
echo "    updated mobile/package.json"

# Android build.gradle
# versionCode: encode X.Y.Z as X*100000 + Y*1000 + Z (room for 999 patches)
IFS='.' read -r MAJ MIN PAT <<< "$VERSION"
ANDROID_CODE=$(( MAJ * 100000 + MIN * 1000 + PAT ))
sed -i -E \
  -e "s/versionCode +[0-9]+/versionCode ${ANDROID_CODE}/" \
  -e "s/versionName +\"[^\"]+\"/versionName \"${VERSION}\"/" \
  mobile/android/app/build.gradle
echo "    updated mobile/android/app/build.gradle (code=$ANDROID_CODE, name=$VERSION)"

# Commit
git add package.json mobile/package.json mobile/android/app/build.gradle
git commit -m "Release v${VERSION}"
echo "    committed"

# Tag
git tag -a "v${VERSION}" -m "Release v${VERSION}"
echo "    tagged v${VERSION}"

if $PUSH; then
  # This repo's remote is "forgejo", not "origin". Prefer forgejo, fall back
  # to origin, otherwise use the only remote there is — so this keeps working
  # if the remote is ever renamed. Pushing the tag is what makes CI attach the
  # signed APK to a Forgejo release for Obtainium; the branch push alone only
  # builds it as a 30-day workflow artifact.
  REMOTE=""
  for candidate in forgejo origin; do
    if git remote get-url "$candidate" >/dev/null 2>&1; then REMOTE="$candidate"; break; fi
  done
  if [[ -z "$REMOTE" ]]; then
    REMOTE=$(git remote | head -1)
  fi
  if [[ -z "$REMOTE" ]]; then
    echo "ERROR: no git remote configured — cannot push. Commit and tag are still local." >&2
    exit 1
  fi
  git push "$REMOTE" HEAD
  git push "$REMOTE" "v${VERSION}"
  echo "    pushed to $REMOTE"
fi

echo "==> Done. v$VERSION."
