#!/bin/bash
# PromptPhotoBooth self-updater
# ----------------------------------------------------------------------
# Fetches the latest-rpi.yml manifest from the release bucket, compares
# its `version` field to /usr/share/promptphotobooth/VERSION, downloads
# the new .deb if different, verifies sha256, and apt-installs it.
#
# Usage:
#   sudo pptb-update               check + install if newer
#   sudo pptb-update --force       reinstall even if versions match
#   sudo pptb-update --reboot      reboot automatically after install
#   sudo pptb-update --dry-run     show what would happen, change nothing
#
# This script is shipped inside the .deb itself (installed to
# /usr/local/bin/pptb-update), so once a Pi has any version with this
# script installed, all future updates can be pulled over the network.
# ----------------------------------------------------------------------

set -euo pipefail

MANIFEST_URL="https://promptphotobooth.com/releases/latest-rpi.yml"
DEB_BASE_URL="https://promptphotobooth.com/releases"
LOCAL_VERSION_FILE="/usr/share/promptphotobooth/VERSION"

FORCE=0
REBOOT=0
DRY_RUN=0
URL_OVERRIDE=""
SHA_OVERRIDE=""
VERSION_OVERRIDE=""

while [ $# -gt 0 ]; do
    case "$1" in
        --force)   FORCE=1 ;;
        --reboot)  REBOOT=1 ;;
        --dry-run) DRY_RUN=1 ;;
        # Direct-install mode: the in-app updater passes the .deb URL + sha256
        # it already received from /api/updates/latest, so we skip the
        # latest-rpi.yml manifest fetch. --version is the advertised version
        # (used for the up-to-date comparison + logging).
        --url)       URL_OVERRIDE="$2"; shift ;;
        --url=*)     URL_OVERRIDE="${1#*=}" ;;
        --sha256)    SHA_OVERRIDE="$2"; shift ;;
        --sha256=*)  SHA_OVERRIDE="${1#*=}" ;;
        --version)   VERSION_OVERRIDE="$2"; shift ;;
        --version=*) VERSION_OVERRIDE="${1#*=}" ;;
        -h|--help)
            sed -n '2,20p' "$0" | sed 's/^# \{0,1\}//'
            exit 0
            ;;
        *)
            echo "Unknown argument: $1" >&2
            echo "Try: pptb-update --help" >&2
            exit 1
            ;;
    esac
    shift
done

if [ $DRY_RUN -eq 0 ] && [ "$(id -u)" -ne 0 ]; then
    echo "pptb-update must be run as root (try: sudo pptb-update)" >&2
    exit 1
fi

# ── tiny YAML scalar extractor ────────────────────────────────────────
# Not a real parser — just enough for our flat manifest. Handles quoted
# and unquoted values, ignores comments and blank lines.
yaml_get() {
    local field="$1" file="$2"
    awk -v key="$field" '
        /^[[:space:]]*#/ { next }
        $0 ~ "^"key":" {
            sub("^"key":[[:space:]]*", "")
            gsub("^[\"'\'']|[\"'\'']$", "")
            print
            exit
        }
    ' "$file"
}

# ── resolve target release ────────────────────────────────────────────
MANIFEST=""
DEB_PATH=""
cleanup() { rm -f "${MANIFEST:-}" "${DEB_PATH:-}"; }
trap cleanup EXIT

if [ -n "$URL_OVERRIDE" ]; then
    # Direct mode (in-app "Update Now" on a .deb install): use the URL/sha/
    # version we were handed; no manifest fetch.
    DEB_URL="$URL_OVERRIDE"
    REMOTE_FILE="$(basename "${DEB_URL%%\?*}")"   # strip any query string
    REMOTE_VERSION="${VERSION_OVERRIDE:-unknown}"
    REMOTE_SHA256="$SHA_OVERRIDE"
    if [ -z "$REMOTE_SHA256" ]; then
        echo "[pptb-update] ERROR: --url requires --sha256 for integrity verification." >&2
        exit 3
    fi
    echo "[pptb-update] Direct install: $REMOTE_FILE (version $REMOTE_VERSION)"
else
    echo "[pptb-update] Fetching manifest from $MANIFEST_URL"
    MANIFEST=$(mktemp)
    if ! curl -sSfL --max-time 30 -o "$MANIFEST" "$MANIFEST_URL"; then
        echo "[pptb-update] ERROR: could not fetch manifest. Check network + URL." >&2
        exit 2
    fi

    REMOTE_VERSION=$(yaml_get version "$MANIFEST")
    REMOTE_FILE=$(yaml_get file "$MANIFEST")
    REMOTE_SHA256=$(yaml_get sha256 "$MANIFEST")

    if [ -z "$REMOTE_VERSION" ] || [ -z "$REMOTE_FILE" ] || [ -z "$REMOTE_SHA256" ]; then
        echo "[pptb-update] ERROR: manifest missing required fields" >&2
        echo "  required: version, file, sha256" >&2
        echo "  manifest contents:" >&2
        sed 's/^/    /' "$MANIFEST" >&2
        exit 3
    fi
    DEB_URL="$DEB_BASE_URL/$REMOTE_FILE"
fi

# ── compare with local ────────────────────────────────────────────────
LOCAL_VERSION="$(cat "$LOCAL_VERSION_FILE" 2>/dev/null || echo "0.0.0")"

echo "[pptb-update] Installed: $LOCAL_VERSION"
echo "[pptb-update] Available: $REMOTE_VERSION"

if [ "$LOCAL_VERSION" = "$REMOTE_VERSION" ] && [ $FORCE -eq 0 ]; then
    echo "[pptb-update] Already up to date."
    exit 0
fi

# If local is NEWER than remote (e.g. dev build), bail unless --force
if dpkg --compare-versions "$LOCAL_VERSION" gt "$REMOTE_VERSION" && [ $FORCE -eq 0 ]; then
    echo "[pptb-update] Local version is newer than remote. Use --force to downgrade."
    exit 0
fi

if [ $DRY_RUN -eq 1 ]; then
    echo "[pptb-update] DRY RUN: would download $REMOTE_FILE and install $REMOTE_VERSION"
    exit 0
fi

# ── download ──────────────────────────────────────────────────────────
DEB_PATH="/tmp/$REMOTE_FILE"
echo "[pptb-update] Downloading $REMOTE_FILE..."
if ! curl -fL --progress-bar -o "$DEB_PATH" "$DEB_URL"; then
    echo "[pptb-update] ERROR: download failed." >&2
    exit 4
fi

# ── verify sha256 ─────────────────────────────────────────────────────
echo "[pptb-update] Verifying sha256..."
ACTUAL_SHA256=$(sha256sum "$DEB_PATH" | awk '{print $1}')
if [ "$ACTUAL_SHA256" != "$REMOTE_SHA256" ]; then
    echo "[pptb-update] ERROR: sha256 mismatch!" >&2
    echo "  expected: $REMOTE_SHA256" >&2
    echo "  got:      $ACTUAL_SHA256" >&2
    echo "  refusing to install a tampered or corrupted package." >&2
    exit 5
fi
echo "[pptb-update] sha256 OK."

# ── install ───────────────────────────────────────────────────────────
echo "[pptb-update] Installing $REMOTE_FILE via apt..."
# noninteractive so apt doesn't prompt for conffile diffs over SSH
DEBIAN_FRONTEND=noninteractive apt install -y "$DEB_PATH"

echo ""
echo "[pptb-update] ✓ Installed version $REMOTE_VERSION"

if [ $REBOOT -eq 1 ]; then
    echo "[pptb-update] Rebooting in 5 seconds..."
    sleep 5
    systemctl reboot
else
    echo ""
    echo "  A reboot is recommended to fully apply changes"
    echo "  (especially kiosk autostart and service updates)."
    echo "  Run: sudo reboot"
    echo "  Or rerun with: sudo pptb-update --reboot"
fi
