#!/bin/bash
#######################################################################
#         ___    _    _   _ _____    ____           _     _   _
#        |_ _|  / \  | \ | |_   _|  / ___|_ __ ___ | |__ | | | |
#         | |  / _ \ |  \| | | |   | |  _| '_ ` _ \| '_ \| |_| |
#         | | / ___ \| |\  | | |   | |_| | | | | | | |_) |  _  |
#        |___/_/   \_\_| \_| |_|    \____|_| |_| |_|_.__/|_| |_|
#
#######################################################################
#
#       Eigentum der IANT GmbH. Darf nur verwendet werden im
#       Zusammenhang mit einem gültigen Wartungsvertrag mit der IANT GmbH
#       Es dürfen keine Änderungen an den Dateien ohne Zustimmung der
#       IANT GmbH durchgeführt werden.
#
#######################################################################
# Author: Benedikt Machens
# Datum: 17.07.2026
# Wingman: Gemini
#######################################################################
# wget -qO- https://download.iant.de/iant_debian12to13.sh | bash
#######################################################################

LOCKFILE="/var/run/iant_debian12to13.lock"
exec 9>"$LOCKFILE"
if ! flock -n 9; then
    echo "FEHLER: Dieses Upgrade-Skript läuft bereits auf diesem System!" >&2
    exit 1
fi

export DEBIAN_FRONTEND=noninteractive
export APT_LISTCHANGES_FRONTEND=none

LOG_UPDATE="/tmp/DEBIAN_UPGRADE.log"
exec &> >(tee -a "$LOG_UPDATE")

# 1. OS-Version prüfen (nur Debian 12 zulässig)
if [ -f /etc/os-release ]; then
    . /etc/os-release
    
    if [ "${VERSION_ID%%.*}" -ge 13 ] 2>/dev/null; then
        echo "====== SYSTEM-CHECK: Das System läuft bereits auf Debian ${VERSION_ID} (${VERSION_CODENAME})."
        echo "Kein Upgrade erforderlich. Beende Skript sicher."
        flock -u 9
        exit 0
    fi
    
    if [ "${VERSION_ID%%.*}" -ne 12 ] 2>/dev/null; then
        echo "FEHLER: Dieses Upgrade-Skript unterstützt ausschließlich Debian 12 (Bookworm) als Ausgangsbasis!"
        echo "Erkanntes System: Debian ${VERSION_ID:-unbekannt} (${VERSION_CODENAME:-unbekannt})"
        flock -u 9
        exit 1
    fi
    
    ARCHITECTURE=$(dpkg --print-architecture)
    case "$ARCHITECTURE" in
        amd64|arm64)
            # Architektur ist zulässig, mache nichts und fahre fort
            ;;
        *)
            echo "FEHLER: Unzulässige Systemarchitektur erkannt!" >&2
            echo "Dieses Skript unterstützt ausschließlich 64-Bit-Systeme (amd64 oder arm64)." >&2
            echo "Erkannte Architektur: $ARCHITECTURE" >&2
            flock -u 9
            exit 1
            ;;
    esac
else
    echo "FEHLER: Betriebssystem-Version konnte nicht ermittelt werden (/etc/os-release fehlt)." >&2
    flock -u 9
    exit 1
fi

SBC_PRESENT=0
if dpkg-query -W -f='${Status}' 3cxsbc 2>/dev/null | grep -q "ok installed"; then
    SBC_PRESENT=1
fi

ACTIVE_TIMERS=$(systemctl list-units --type=timer --state=active --no-legend | awk '{print $1}' || true)

stop_active_timers() {
    if [ -n "$ACTIVE_TIMERS" ]; then
        echo "Stoppe aktive Hintergrund-Timer..."
        for timer in $ACTIVE_TIMERS; do
            echo "  -> systemctl stop $timer"
            systemctl stop "$timer" 2>/dev/null || true
        done
    fi
}

start_active_timers() {
    if [ -n "$ACTIVE_TIMERS" ]; then
        echo "Reaktiviere Hintergrund-Timer..."
        for timer in $ACTIVE_TIMERS; do
            echo "  -> systemctl start $timer"
            systemctl start "$timer" 2>/dev/null || true
        done
    fi
}

cleanup_upgrade_service() {
    if [ -f /etc/systemd/system/iant-debian13-upgrade.service ]; then
        rm -f /etc/systemd/system/iant-debian13-upgrade.service
    fi
}

error_handler() {
    local error_msg="$1"
    echo "FEHLER: $error_msg"
    
    # Repositories bei Fehler auf Bookworm zurückrollen
    echo "Führe Rollback des Quell-Zustands auf Debian 12 (Bookworm) durch..."
    if [ -f /etc/apt/sources.list ]; then
        sed -i 's/trixie/bookworm/g' /etc/apt/sources.list
    fi
    find /etc/apt/sources.list.d/ -type f \( -name "*.list" -o -name "*.sources" \) -exec sed -i 's/trixie/bookworm/g' {} + 2>/dev/null || true
    
    start_active_timers
    cleanup_upgrade_service
    
    if [ -x /usr/lib/iant/auto-update/state-manager ]; then
        /usr/lib/iant/auto-update/state-manager "iant_debian12to13" "2" "ERROR: $error_msg" || true
    fi
    exit 1
}

# 2. Dynamische Ermittlung und Prüfung der Boot-Partition
BOOT_PATH=""
if grep -q " /boot/firmware " /proc/mounts; then
    BOOT_PATH="/boot/firmware"
    MIN_BOOT_SPACE=100
elif grep -q " /boot " /proc/mounts; then
    BOOT_PATH="/boot"
    MIN_BOOT_SPACE=150
else
    BOOT_PATH="/"
    MIN_BOOT_SPACE=150
fi

if [ -d "$BOOT_PATH" ]; then
    free_space=$(df -m --output=avail "$BOOT_PATH" | tail -n1 | tr -d '[:space:]')
    
    if [[ "$free_space" =~ ^[0-9]+$ ]]; then
        if [ "$free_space" -lt "$MIN_BOOT_SPACE" ]; then
            error_handler "Zu wenig freier Speicherplatz auf der Boot-Partition ($BOOT_PATH)! Vorhanden: ${free_space}MB, Benötigt mindestens: ${MIN_BOOT_SPACE}MB"
        fi
    else
        error_handler "Speicherplatzprüfung für $BOOT_PATH failed (unerwartetes Ausgabeformat)."
    fi
else
    error_handler "Ermittelter Boot-Pfad $BOOT_PATH existiert nicht auf diesem System."
fi

echo "====== [$(date +"%H:%M:%S")] START: Upgrade auf Debian 13 (Trixie)"

stop_active_timers

# 3. SBC-Dienst vor Upgrade stoppen
if [ "$SBC_PRESENT" -eq 1 ]; then
    echo "3CX SBC erkannt. Stoppe Dienst vor Upgrade..."
    systemctl stop 3cxsbc || true
fi

# 4. Debian 12 Pakete aktualisieren
echo "Aktualisiere Debian 12 Pakete..."
apt-get update || error_handler "Paketlisten-Update fehlgeschlagen (Debian 12)"
apt-get upgrade -y -o Dpkg::Options::="--force-confold" || error_handler "Vorbereitendes Paket-Upgrade fehlgeschlagen"

# 5. GRUB-Optionen für nicht-interaktiven Ablauf setzen
BOOT_DEV=$(lsblk -ndpo NAME,TYPE 2>/dev/null | awk '$2=="disk" {print $1}' | head -n1 || true)
if [ -n "$BOOT_DEV" ]; then
    apt-get install -y debconf-utils || error_handler "Installation von debconf-utils fehlgeschlagen"
    echo "grub-pc grub-pc/install_devices multiselect $BOOT_DEV" | devconf-set-selections
    echo "grub-pc grub-pc/install_devices_empty boolean false" | devconf-set-selections
fi

# 6. Paketquellen auf Debian 13 (Trixie) umstellen
echo "Passe Paketquellen auf Debian 13 (Trixie) an..."
if [ -f /etc/apt/sources.list ]; then
    sed -i 's/bookworm/trixie/g' /etc/apt/sources.list
fi
find /etc/apt/sources.list.d/ -type f \( -name "*.list" -o -name "*.sources" \) -exec sed -i 's/bookworm/trixie/g' {} + 2>/dev/null || true

# 7. GPG-Schlüssel für 3CX aktualisieren
if [ "$SBC_PRESENT" -eq 1 ]; then
    echo "Aktualisiere GPG-Schlüssel für das 3CX-Repository..."
    wget -O- https://repo.3cx.com/key.pub 2>/dev/null | gpg --dearmor | tee /usr/share/keyrings/3cx-archive-keyring.gpg > /dev/null
fi

# 8. Distribution-Upgrade durchführen
echo "Führe dist-upgrade auf Debian 13 durch..."
apt-get update || error_handler "Paketlisten-Update für Trixie fehlgeschlagen"
apt-get dist-upgrade -y \
  -o Dpkg::Options::="--force-confdef" \
  -o Dpkg::Options::="--force-confold" \
  -o APT::listchanges::Frontend=none || error_handler "Dist-Upgrade auf Debian 13 fehlgeschlagen"

# 9. Unbenötigte Abhängigkeiten entfernen
apt-get autoremove -y && apt-get clean

# 10. Paketquellen in DEB822-Format konvertieren und bereinigen
if apt --help 2>&1 | grep -q "modernize-sources"; then
    echo "Überführe Paketquellen in das DEB822-Format (.sources)..."
    apt modernize-sources -y || true

    if [ -f /etc/apt/sources.list.d/raspi.sources ]; then
        if grep -qE "^[[:space:]]*Signed-By:[[:space:]]*$" /etc/apt/sources.list.d/raspi.sources; then
            echo "Ergänze fehlenden GPG-Schlüsselpfad in raspi.sources..."
            sed -i 's|^[[:space:]]*Signed-By:[[:space:]]*$|Signed-By: /usr/share/keyrings/raspberrypi-archive-keyring.gpg|' /etc/apt/sources.list.d/raspi.sources
        fi
    fi

    echo "Bereinige veraltete .bak, .save, .list und temporäre Paketdateien..."
    rm -f /etc/apt/sources.list.bak /etc/apt/sources.list~ /etc/apt/sources.list
    find /etc/apt/sources.list.d/ -type f \( -name "*.list" -o -name "*.bak" -o -name "*.save" -o -name "*.dpkg-*" \) -delete
else
    echo "Befehl 'apt modernize-sources' nicht verfügbar. Überspringe Konvertierung..."
fi

# 11. DHCP-Identifikation (Hardware-MAC) erzwingen
echo "Sichere DHCP-Client-Identifikation (Hardware-MAC)..."
if [ -f /etc/dhcp/dhclient.conf ]; then
    if ! grep -qE "^[[:space:]]*send[[:space:]]+dhcp-client-identifier" /etc/dhcp/dhclient.conf; then
        echo "send dhcp-client-identifier = hardware;" >> /etc/dhcp/dhclient.conf
    fi
fi

TARGET_CONF="/etc/dhcpcd.conf"
if [ -f "$TARGET_CONF" ]; then
    sed -i 's/^[[:space:]]*duid/# duid/g' "$TARGET_CONF"
    if grep -qE "^[[:space:]]*#[[:space:]]*clientid" "$TARGET_CONF"; then
        sed -i 's/^[[:space:]]*#[[:space:]]*clientid/clientid/g' "$TARGET_CONF"
    elif ! grep -qE "^[[:space:]]*clientid" "$TARGET_CONF"; then
        echo "clientid" >> "$TARGET_CONF"
    fi
fi

start_active_timers
cleanup_upgrade_service

# Status an State-Manager melden
echo "Melde Status an State-Manager..."
if [ -x /usr/lib/iant/auto-update/state-manager ]; then
    /usr/lib/iant/auto-update/state-manager "iant_debian12to13" "0" "SUCCESS" || true
fi

flock -u 9

echo "====== [$(date +"%H:%M:%S")] UPGRADE ERFOLGREICH: System-Neustart erfolgt in 30 Sekunden."
sleep 30
reboot
