#!/usr/bin/env sh
set -eu

BASE_URL="${BMCLI_BASE_URL:-https://download.busmust.com/bmcli}"
CURRENT_VERSION=""
RESULT_PATH=""

while [ "$#" -gt 0 ]; do
    case "$1" in
        --current-version) CURRENT_VERSION="$2"; shift 2 ;;
        --result-path) RESULT_PATH="$2"; shift 2 ;;
        --base-url) BASE_URL="$2"; shift 2 ;;
        *) echo "Unknown option: $1" >&2; exit 1 ;;
    esac
done

printf '%s\n' "$CURRENT_VERSION" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+$' || {
    echo "Invalid current BMCLI version" >&2; exit 1;
}
[ -n "$RESULT_PATH" ] || { echo "--result-path is required" >&2; exit 1; }
command -v curl >/dev/null 2>&1 || { echo "curl is required" >&2; exit 1; }
command -v sha256sum >/dev/null 2>&1 || { echo "sha256sum is required" >&2; exit 1; }
if command -v python3 >/dev/null 2>&1; then PYTHON=python3
elif command -v python >/dev/null 2>&1; then PYTHON=python
else echo "python3 is required to check BMCLI updates" >&2; exit 1
fi

TMP=$(mktemp -d)
trap 'rm -rf "$TMP"' EXIT HUP INT TERM
MANIFEST="$TMP/manifest.json"
NOTES="$TMP/changelist.txt"
curl -fsSL "$BASE_URL/releases/latest/manifest.json" -o "$MANIFEST"

"$PYTHON" - "$MANIFEST" "$CURRENT_VERSION" "$RESULT_PATH" "$NOTES" <<'PY'
import hashlib
import json
import pathlib
import re
import subprocess
import sys

manifest_path, current, result_path, notes_path = sys.argv[1:]
with open(manifest_path, encoding="utf-8-sig") as stream:
    manifest = json.load(stream)
if manifest.get("schema_version") != 1:
    raise SystemExit("unsupported manifest schema")
latest = str(manifest.get("version", ""))
if not re.fullmatch(r"[0-9]+\.[0-9]+\.[0-9]+", latest):
    raise SystemExit("manifest contains an invalid version")

release_notes = ""
release_notes_url = ""
notes = manifest.get("release_notes")
if notes:
    release_notes_url = str(notes.get("url", ""))
    expected = str(notes.get("sha256", ""))
    if not re.fullmatch(r"[0-9a-fA-F]{64}", expected):
        raise SystemExit("release notes contain an invalid SHA-256")
    subprocess.run(["curl", "-fsSL", release_notes_url, "-o", notes_path], check=True)
    payload = pathlib.Path(notes_path).read_bytes()
    if hashlib.sha256(payload).hexdigest().lower() != expected.lower():
        raise SystemExit("release notes SHA-256 mismatch")
    release_notes = payload.decode("utf-8-sig")

current_tuple = tuple(int(value) for value in current.split("."))
latest_tuple = tuple(int(value) for value in latest.split("."))
state = "update_available" if current_tuple < latest_tuple else (
    "up_to_date" if current_tuple == latest_tuple else "local_newer")
relevant_notes = ""
if current_tuple < latest_tuple and release_notes:
    collected = []
    for line in release_notes.splitlines():
        if re.match(r"^" + re.escape(current) + r"(?:\s|$)", line):
            break
        collected.append(line)
    relevant_notes = "\n".join(collected).strip()
result = {
    "status": "ok",
    "action": "update_check",
    "current_version": current,
    "latest_version": latest,
    "update_available": current_tuple < latest_tuple,
    "state": state,
    "release_notes_url": release_notes_url,
    "release_notes": relevant_notes,
}
pathlib.Path(result_path).write_text(
    json.dumps(result, ensure_ascii=False, separators=(",", ":")) + "\n",
    encoding="utf-8",
)
PY
