#!/bin/sh
# keyboot-update-check — is the installed keyboot older than the published release?
# For admins (run it) and scripts/cron (check the exit code). Compares the
# installed keyboot boot-image version against the channel's `latest` pointer
# (the same pointer install.sh resolves: <base>/keyboot/latest).
#
# Installed version is read (first hit wins) from:
#   1. --installed X            (override; also how tests drive it)
#   2. /usr/lib/keyboot/version (the keyboot-boot package writes pkgver here)
#   3. apk / dpkg-query         (if keyboot came from the native repo)
#   4. the ESP good-slot version via `keyboot-install keyboot list --json`
# If none resolve, that's an error (pass --installed).
#
# Usage:
#   keyboot-update-check [--base URL] [--installed VER] [--quiet] [--json]
#     --base URL    channel base (default https://packages.osterman.co/keyboot)
#     --installed   override the detected installed version
#     --quiet       print only when an update is available (or on error)
#     --json        machine-readable output
#
# Exit codes (for scripts/cron):
#   0  up to date (or installed is ahead of the channel)
#   10 update available (installed < latest)
#   1  error (couldn't determine installed or latest version)

set -u
PROG=keyboot-update-check
BASE="${KEYBOOT_PKG_BASE:-https://packages.osterman.co/keyboot}"
INSTALLED=""
QUIET=0
JSON=0

say()  { [ "$QUIET" -eq 1 ] || printf '%s\n' "$*"; }
err()  { printf '%s: error: %s\n' "$PROG" "$*" >&2; }
die()  { err "$*"; [ "$JSON" -eq 1 ] && printf '{"status":"error","message":"%s"}\n' "$*"; exit 1; }

while [ $# -gt 0 ]; do
    case "$1" in
        --base)      BASE="${2:?--base needs a value}"; shift 2 ;;
        --base=*)    BASE="${1#*=}"; shift ;;
        --installed) INSTALLED="${2:?--installed needs a value}"; shift 2 ;;
        --installed=*) INSTALLED="${1#*=}"; shift ;;
        --quiet)     QUIET=1; shift ;;
        --json)      JSON=1; shift ;;
        -h|--help)   awk '/^# *Usage:/{f=1} f{ if(!/^#/) exit; print }' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;;
        *)           die "unknown option: $1 (try --help)" ;;
    esac
done

# normalize: strip a leading 'v', surrounding whitespace.
norm() { printf '%s' "$1" | tr -d ' \r\n' | sed 's/^v//'; }

fetch() {  # fetch URL -> stdout
    if command -v curl >/dev/null 2>&1; then curl -fsS "$1" 2>/dev/null
    elif command -v wget >/dev/null 2>&1; then wget -qO- "$1" 2>/dev/null
    else die "need curl or wget to reach $1"; fi
}

detect_installed() {
    [ -n "$INSTALLED" ] && { printf '%s' "$INSTALLED"; return 0; }
    if [ -r /usr/lib/keyboot/version ]; then
        v="$(cat /usr/lib/keyboot/version 2>/dev/null)"; [ -n "$v" ] && { printf '%s' "$v"; return 0; }
    fi
    if command -v apk >/dev/null 2>&1; then
        v="$(apk info -e keyboot 2>/dev/null >/dev/null && apk version keyboot 2>/dev/null | sed -n 's/^keyboot-\([0-9][^ ]*\).*/\1/p')"
        [ -n "$v" ] && { printf '%s' "$v"; return 0; }
    fi
    if command -v dpkg-query >/dev/null 2>&1; then
        v="$(dpkg-query -W -f='${Version}' keyboot 2>/dev/null)"; [ -n "$v" ] && { printf '%s' "$v"; return 0; }
    fi
    if command -v keyboot-install >/dev/null 2>&1; then
        v="$(keyboot-install keyboot list --json 2>/dev/null | sed -n 's/.*"role":"good".*"version":"\([^"]*\)".*/\1/p' | head -1)"
        [ -n "$v" ] && { printf '%s' "$v"; return 0; }
    fi
    return 1
}

inst_raw="$(detect_installed)" || die "could not determine the installed keyboot version (pass --installed)"
latest_raw="$(fetch "$BASE/latest")" || true
[ -n "$latest_raw" ] || die "could not fetch the latest version from $BASE/latest"

inst="$(norm "$inst_raw")"; latest="$(norm "$latest_raw")"
[ -n "$inst" ] && [ -n "$latest" ] || die "empty version (installed='$inst_raw' latest='$latest_raw')"

# Determine relationship via version sort.
if [ "$inst" = "$latest" ]; then
    status=current
elif [ "$(printf '%s\n%s\n' "$inst" "$latest" | sort -V 2>/dev/null | tail -n1)" = "$latest" ]; then
    status=update-available
else
    status=ahead          # installed newer than the channel (dev/pre-release)
fi

if [ "$JSON" -eq 1 ]; then
    printf '{"status":"%s","installed":"%s","latest":"%s"}\n' "$status" "$inst" "$latest"
else
    case "$status" in
        current)          say "keyboot v$inst is up to date (latest v$latest)" ;;
        update-available) printf '%s\n' "keyboot update available: v$inst -> v$latest  (update with the package manager or keyboot-install)" ;;
        ahead)            say "keyboot v$inst is newer than the channel (latest v$latest)" ;;
    esac
fi

case "$status" in update-available) exit 10 ;; *) exit 0 ;; esac
