#!/bin/bash
# Aktualizacja nivato-logger (suite bookworm).
#
# Użycie:
#   apt-self-upgrade download  — pobiera paczkę do cache APT (usługa Java działa dalej)
#   apt-self-upgrade apply     — instaluje z cache i planuje reboot
#
# Exit download/apply: 0 = OK, 10 = już aktualne, inne = błąd.
set -euo pipefail

MODE="${1:-download}"
case "$MODE" in
    download|apply) ;;
    *)
        echo "Użycie: $0 download|apply" >&2
        exit 64
        ;;
esac

export DEBIAN_FRONTEND=noninteractive
export NIVATO_SKIP_REBOOT=1
SOURCES="/etc/apt/sources.list.d/nivato-logger.sources"
KEYRING="/usr/share/keyrings/nivato-logger.gpg"
PACKAGE="nivato-logger"
DATA_DIR="${NIVATO_DATA_DIR:-/opt/nivato-logger/data}"
REBOOT_MARKER="$DATA_DIR/update-reboot-at"
READY_MARKER="$DATA_DIR/update-ready-version"
REBOOT_DELAY_SEC=10
LOG_DIR="/opt/nivato-logger/logs"
LOG_FILE="$LOG_DIR/apt-self-upgrade.log"

# Instalacja (apply) poza usługą Java — dpkg stopuje nivato-logger.
# Download zostaje w procesie wywołującym (nie wyłącza panelu).
if [ "$MODE" = "apply" ] && [ "${NIVATO_APT_UPGRADE_TRANSIENT:-}" != "1" ]; then
    systemctl reset-failed nivato-logger-apt-upgrade.service 2>/dev/null || true
    systemctl stop nivato-logger-apt-upgrade.service 2>/dev/null || true
    exec /usr/bin/systemd-run --wait --pipe --collect \
        --unit=nivato-logger-apt-upgrade \
        -p Type=oneshot \
        -p TimeoutStartSec=1800 \
        --setenv=NIVATO_APT_UPGRADE_TRANSIENT=1 \
        --setenv=NIVATO_SKIP_REBOOT=1 \
        --setenv=NIVATO_DATA_DIR="$DATA_DIR" \
        "$0" apply
fi

mkdir -p "$LOG_DIR" "$DATA_DIR"
exec > >(tee -a "$LOG_FILE") 2>&1

write_sources() {
    mkdir -p "$(dirname "$SOURCES")"
    if [ -f "$KEYRING" ]; then
        cat > "$SOURCES" <<EOF
Types: deb
URIs: https://apt.nivato.app/
Suites: bookworm
Components: main
Architectures: arm64
Signed-By: $KEYRING
EOF
        echo "Źródło APT: suite bookworm + Signed-By $KEYRING"
    else
        cat > "$SOURCES" <<'EOF'
Types: deb
URIs: https://apt.nivato.app/
Suites: bookworm
Components: main
Architectures: arm64
Trusted: yes
EOF
        echo "Źródło APT: suite bookworm (Trusted:yes — brak keyringu $KEYRING)" >&2
    fi
    chmod 644 "$SOURCES"
}

upgrade_trusted_to_signed_by() {
    [ -f "$SOURCES" ] || return 0
    [ -f "$KEYRING" ] || return 0
    grep -q '^Trusted: yes' "$SOURCES" 2>/dev/null || return 0
    tmp=$(mktemp)
    sed '/^Trusted: yes/d' "$SOURCES" > "$tmp"
    if ! grep -q '^Signed-By:' "$tmp"; then
        printf 'Signed-By: %s\n' "$KEYRING" >> "$tmp"
    fi
    mv "$tmp" "$SOURCES"
    chmod 644 "$SOURCES"
    echo "APT: Trusted:yes → Signed-By $KEYRING"
}

ensure_sources() {
    if [ ! -f "$SOURCES" ]; then
        write_sources
        return
    fi
    if grep -qE '^Suites:.*(nivato-logger|stable)' "$SOURCES" 2>/dev/null \
        || ! grep -q '^Suites: bookworm' "$SOURCES" 2>/dev/null; then
        write_sources
        return
    fi
    upgrade_trusted_to_signed_by
    echo "Źródło APT bez zmian ($SOURCES)"
}

pkg_version() {
    dpkg-query -W -f='${Version}' "$PACKAGE" 2>/dev/null || echo ""
}

candidate_version() {
    apt-cache policy "$PACKAGE" 2>/dev/null | awk '/Candidate:/ { print $2; exit }'
}

deb_cached_for() {
    local ver="$1"
    compgen -G "/var/cache/apt/archives/${PACKAGE}_${ver}_*.deb" > /dev/null 2>&1
}

wait_for_apt_locks() {
    local i=0
    while fuser /var/lib/dpkg/lock-frontend >/dev/null 2>&1 \
        || fuser /var/lib/dpkg/lock >/dev/null 2>&1 \
        || fuser /var/lib/apt/lists/lock >/dev/null 2>&1 \
        || fuser /var/cache/apt/archives/lock >/dev/null 2>&1; do
        i=$((i + 1))
        if [ "$i" -gt 90 ]; then
            echo "Timeout czekania na blokadę APT/dpkg" >&2
            exit 5
        fi
        echo "Czekam na zwolnienie blokady APT ($i)…"
        sleep 2
    done
}

run_apt_update() {
    set +e
    /usr/bin/apt-get update -o Acquire::Retries=3
    local rc=$?
    set -e
    if [ "$rc" -ne 0 ]; then
        echo "Ostrzeżenie: apt-get update zakończone kodem $rc — kontynuuję z cache (jeśli jest kandydat)" >&2
    fi
    return 0
}

mark_ready() {
    local ver="$1"
    printf '%s\n' "$ver" > "$READY_MARKER"
    chmod 644 "$READY_MARKER"
    echo "READY_VERSION=$ver"
}

ensure_sources
wait_for_apt_locks

BEFORE="$(pkg_version)"
echo "Zainstalowana wersja: ${BEFORE:-brak}"
echo "Tryb: $MODE"

run_apt_update
CANDIDATE="$(candidate_version)"
echo "Kandydat w repo: ${CANDIDATE:-brak}"

if [ -z "$CANDIDATE" ] || [ "$CANDIDATE" = "(none)" ]; then
    echo "Brak kandydata pakietu $PACKAGE w repozytorium (sprawdź sieć i https://apt.nivato.app/)" >&2
    exit 2
fi

if [ -n "$BEFORE" ] && dpkg --compare-versions "$BEFORE" ge "$CANDIDATE"; then
    echo "Pakiet jest już aktualny ($BEFORE)"
    rm -f "$READY_MARKER"
    exit 10
fi

if [ "$MODE" = "download" ]; then
    if deb_cached_for "$CANDIDATE"; then
        echo "Paczka ${PACKAGE}=${CANDIDATE} już jest w cache APT"
        mark_ready "$CANDIDATE"
        exit 0
    fi
    wait_for_apt_locks
    echo "Pobieram ${PACKAGE}=${CANDIDATE} (download-only)…"
    set +e
    /usr/bin/apt-get install -y --download-only --allow-change-held-packages \
        "${PACKAGE}=${CANDIDATE}"
    DOWNLOAD_RC=$?
    set -e
    if [ "$DOWNLOAD_RC" -ne 0 ]; then
        echo "apt-get download zakończone kodem $DOWNLOAD_RC" >&2
        exit "$DOWNLOAD_RC"
    fi
    if ! deb_cached_for "$CANDIDATE"; then
        echo "Brak pliku .deb w cache po pobraniu (${PACKAGE}=${CANDIDATE})" >&2
        exit 3
    fi
    mark_ready "$CANDIDATE"
    echo "Pobranie OK: ${BEFORE:-none} → $CANDIDATE (oczekuje na apply/reboot)"
    exit 0
fi

# ── apply: instalacja + reboot ──
wait_for_apt_locks
echo "Instaluję ${PACKAGE}=${CANDIDATE}…"
set +e
/usr/bin/apt-get install -y --allow-change-held-packages \
    -o Dpkg::Options::=--force-confdef \
    -o Dpkg::Options::=--force-confold \
    "${PACKAGE}=${CANDIDATE}"
INSTALL_RC=$?
set -e
if [ "$INSTALL_RC" -ne 0 ]; then
    echo "apt-get install zakończone kodem $INSTALL_RC" >&2
    exit "$INSTALL_RC"
fi

AFTER="$(pkg_version)"
echo "Wersja po aktualizacji: ${AFTER:-brak}"

if [ -z "$AFTER" ]; then
    echo "Pakiet nie jest zainstalowany po apt-get install" >&2
    exit 3
fi

if [ -n "$BEFORE" ] && [ "$BEFORE" = "$AFTER" ]; then
    echo "Wersja nie zmieniła się mimo nowszego kandydata ($CANDIDATE)" >&2
    exit 4
fi

rm -f "$READY_MARKER"
echo "Aktualizacja OK: ${BEFORE:-none} -> $AFTER"

reboot_at=$(( $(date +%s) + REBOOT_DELAY_SEC ))
printf '%s\n' "$reboot_at" > "$REBOOT_MARKER"
chmod 644 "$REBOOT_MARKER"
echo "Restart systemu zaplanowany za ${REBOOT_DELAY_SEC}s (marker $REBOOT_MARKER)"

systemctl reset-failed nivato-logger-update-reboot.service 2>/dev/null || true
systemctl stop nivato-logger-update-reboot.service 2>/dev/null || true
if ! systemd-run --unit=nivato-logger-update-reboot --on-active="${REBOOT_DELAY_SEC}s" /sbin/reboot \
        >/dev/null 2>&1; then
    (sleep "$REBOOT_DELAY_SEC"; /sbin/reboot) >/dev/null 2>&1 &
fi

systemctl daemon-reload 2>/dev/null || true
systemctl restart nivato-logger.service 2>/dev/null \
    || systemctl start nivato-logger.service 2>/dev/null \
    || true

exit 0
