#!/bin/bash
# Aktualizacja nivato-logger (suite bookworm).
# Exit: 0 = zainstalowano nowszą wersję, 10 = już aktualne, inne = błąd.
# Po sukcesie: marker reboot + restart usługi + reboot za 10 s (panel pokazuje odliczanie).
set -euo pipefail

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"
REBOOT_DELAY_SEC=10
LOG_DIR="/opt/nivato-logger/logs"
LOG_FILE="$LOG_DIR/apt-self-upgrade.log"

# Uruchom poza usługą Java — dpkg stopuje nivato-logger w trakcie upgrade.
# --pipe: stdout/stderr jednostki wraca do wywołującego (widać błąd apt w logach panelu).
if [ "${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" "$@"
fi

mkdir -p "$LOG_DIR"
# Duplikuj logi do pliku (przydatne po restarcie usługi).
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() {
    # Nie nadpisuj działającego Signed-By / bookworm — tylko migruj stary suite
    # albo brakujący plik. Trusted:yes zamień na Signed-By gdy jest keyring.
    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 }'
}

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; 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() {
    # Nie przerywaj całego upgrade przy chwilowym błędzie update — użyj cache listy.
    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
}

ensure_sources
wait_for_apt_locks

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

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)"
    exit 10
fi

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

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

mkdir -p "$DATA_DIR"
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)"

# Anuluj poprzednie zaplanowane restarty z update, potem zaplanuj nowy.
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

# Podnieś panel na te ~10 s, żeby UI pokazało odliczanie przed restartem.
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
