#!/usr/bin/env bash
#
# update-rtnode.sh — download & repackage the latest RTNode firmware release.
#
# Pulls the *_merged.bin assets from the RTNode-HeltecV4 GitHub releases, wraps
# each in the rtnode_heltec_vX.zip layout the web flasher expects (a single
# *_merged.bin flashed at 0x0), drops them in a version directory next to this
# script, and repoints the latest/ symlinks.
#
# Usage:
#   ./update-rtnode.sh                 # latest stable release
#   ./update-rtnode.sh --pre           # newest release, incl. pre-releases
#   ./update-rtnode.sh --tag v1.0.42   # a specific tag
#   ./update-rtnode.sh --force         # rebuild even if the version dir exists
#
# Env:
#   GITHUB_TOKEN   optional; raises the GitHub API rate limit if set.
#
set -euo pipefail

REPO="jrl290/RTNode-HeltecV4"
API="https://api.github.com/repos/${REPO}"

# Board map: "<release asset .bin>:<output .zip>". The .bin is stored inside the
# .zip at its root, matching the flasher's fcRTMerged() expectation.
BOARDS=(
  "rtnode_heltec_v3_merged.bin:rtnode_heltec_v3.zip"
  "rtnode_heltec_v4_merged.bin:rtnode_heltec_v4.zip"
)

# Root = directory this script lives in.
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

TAG=""
INCLUDE_PRE=0
FORCE=0

log()  { printf '\033[1;34m==>\033[0m %s\n' "$*"; }
warn() { printf '\033[1;33mwarn:\033[0m %s\n' "$*" >&2; }
die()  { printf '\033[1;31merror:\033[0m %s\n' "$*" >&2; exit 1; }

# --- args -------------------------------------------------------------------
while [[ $# -gt 0 ]]; do
  case "$1" in
    --tag)   TAG="${2:?--tag needs a value}"; shift 2 ;;
    --pre)   INCLUDE_PRE=1; shift ;;
    --force) FORCE=1; shift ;;
    -h|--help)
      sed -n '2,20p' "${BASH_SOURCE[0]}" | sed 's/^# \?//'
      exit 0 ;;
    *) die "unknown argument: $1" ;;
  esac
done

for bin in curl jq zip; do
  command -v "$bin" >/dev/null 2>&1 || die "'$bin' is required but not installed"
done

# --- curl helper (optional auth) -------------------------------------------
gh_curl() {
  local -a auth=()
  [[ -n "${GITHUB_TOKEN:-}" ]] && auth=(-H "Authorization: Bearer ${GITHUB_TOKEN}")
  curl -fsSL "${auth[@]}" -H "Accept: application/vnd.github+json" "$@"
}

# --- resolve the release ----------------------------------------------------
if [[ -n "$TAG" ]]; then
  log "Fetching release $TAG"
  RELEASE="$(gh_curl "${API}/releases/tags/${TAG}")" \
    || die "no release found for tag '$TAG'"
elif [[ "$INCLUDE_PRE" -eq 1 ]]; then
  log "Fetching newest release (pre-releases included)"
  RELEASE="$(gh_curl "${API}/releases?per_page=1" | jq -e '.[0]')" \
    || die "could not list releases"
else
  log "Fetching latest stable release"
  RELEASE="$(gh_curl "${API}/releases/latest")" \
    || die "could not fetch latest release"
fi

TAG="$(jq -er '.tag_name' <<<"$RELEASE")" || die "release has no tag_name"
VERSION="${TAG#v}"                       # v1.0.42 -> 1.0.42
[[ -n "$VERSION" ]] || die "empty version from tag '$TAG'"

DEST="${ROOT}/${VERSION}"
log "Release $TAG -> version directory $DEST"

if [[ -d "$DEST" && "$FORCE" -ne 1 ]]; then
  warn "$DEST already exists; use --force to rebuild. Refreshing symlinks only."
else
  # --- download + repackage each board -------------------------------------
  TMP="$(mktemp -d)"
  trap 'rm -rf "$TMP"' EXIT
  mkdir -p "$DEST"

  for entry in "${BOARDS[@]}"; do
    asset="${entry%%:*}"
    outzip="${entry##*:}"

    url="$(jq -er --arg n "$asset" \
      '.assets[] | select(.name == $n) | .browser_download_url' <<<"$RELEASE")" \
      || die "release $TAG has no asset named '$asset'"
    want_size="$(jq -er --arg n "$asset" \
      '.assets[] | select(.name == $n) | .size' <<<"$RELEASE")"

    log "Downloading $asset"
    curl -fsSL -o "${TMP}/${asset}" "$url" || die "download failed: $url"

    got_size="$(stat -c %s "${TMP}/${asset}")"
    [[ "$got_size" == "$want_size" ]] \
      || die "$asset size mismatch (got $got_size, expected $want_size)"

    log "Packaging -> ${VERSION}/${outzip}"
    rm -f "${DEST}/${outzip}"
    ( cd "$TMP" && zip -jq "${DEST}/${outzip}" "$asset" )
  done

  # Record which release this directory came from.
  jq -n --arg tag "$TAG" --arg ver "$VERSION" \
        --arg name "$(jq -r '.name // .tag_name' <<<"$RELEASE")" \
        --arg pub "$(jq -r '.published_at' <<<"$RELEASE")" \
        --argjson pre "$(jq '.prerelease' <<<"$RELEASE")" \
        '{tag:$tag, version:$ver, name:$name, published_at:$pub, prerelease:$pre}' \
        > "${DEST}/release.json"
fi

# --- repoint latest/ symlinks ----------------------------------------------
LATEST="${ROOT}/latest"
mkdir -p "$LATEST"
for entry in "${BOARDS[@]}"; do
  outzip="${entry##*:}"
  [[ -f "${DEST}/${outzip}" ]] || die "missing ${DEST}/${outzip}; cannot link"
  ln -sfn "../${VERSION}/${outzip}" "${LATEST}/${outzip}"
  log "latest/${outzip} -> ../${VERSION}/${outzip}"
done

log "Done. RTNode firmware at version ${VERSION}."
