#!/bin/bash

####################################################################
# SnowTV Player – Remote Reinstall via debootstrap
#
# Robustere Alternative zu remote_reinstall.sh (kexec):
# Installiert Debian 13 ins laufende System via debootstrap.
# Das alte System bleibt bis zum Reboot aktiv → bei Netzabbruch
# ist ein Retry via SSH möglich, kein physischer Eingriff nötig.
#
# Ablauf:
#   1. mcid + mcdomain aus bestehender Konfiguration lesen
#   2. UEFI vs. BIOS und SATA vs. NVMe erkennen
#   3. Disk neu partitionieren + formatieren    ← Punkt of no return
#   4. debootstrap Debian 13 → /mnt/newroot     ← retry bei Fehler
#   5. chroot: Kernel, GRUB, SSH, User, firstboot-Service
#   6. Reboot → Debian 13 bootet, swinstall.sh läuft automatisch
#
# ACHTUNG: Nach Schritt 3 ist die alte Disk-Partition gelöscht.
# Das laufende System bleibt noch im RAM aktiv (retry möglich),
# aber ein Stromausfall nach Schritt 3 erfordert physischen Zugriff.
####################################################################

MIRROR="http://deb.debian.org/debian"
SUITE="trixie"
TARGET="/mnt/newroot"
LOG="/tmp/reinstall_dbs.log"

_log()  { echo "$(date)  INFO: $*" | tee -a "$LOG"; }
_err()  { printf '%s ERROR: %b\n' "$(date)" "$*" | tee -a "$LOG"; exit 1; }
_warn() { echo "$(date)  WARN: $*" | tee -a "$LOG"; }
_sep()  { echo "--------------------------------------------------------" | tee -a "$LOG"; }

mkdir -p "$TARGET"
_log "=== SnowTV Remote Reinstall (debootstrap) ==="
_log "Läuft auf: $(hostname) | $(uname -r) | Debian $(cat /etc/debian_version 2>/dev/null || echo '?')"

# ----------------------------------------------------------------
# 1. mcid lesen (mcid.cfg → mc.cfg → manuelle Eingabe)
# ----------------------------------------------------------------
MCID=$(grep '^ID=' /home/snowtv/bin/mcid.cfg 2>/dev/null | cut -d= -f2 | tr -d '\r')
if [ -z "$MCID" ] || [ "$MCID" = "102" ]; then
    _warn "mcid.cfg fehlt oder Default – suche in mc.cfg..."
    MCID=$(grep '^ID=' /home/snowtv/bin/mc.cfg 2>/dev/null | cut -d= -f2 | awk '{print $1}' | tr -d '\r')
fi
if [ -z "$MCID" ] || [ "$MCID" = "102" ]; then
    _warn "ID nicht gefunden."
    echo ""
    echo "  Bitte Player-ID eingeben (Etikett auf Gerät oder infosnow.ch-Backend):"
    read -r -p "  Player-ID: " MCID
fi
if [ -z "$MCID" ] || ! [[ "$MCID" =~ ^[1-9][0-9]{0,2}$ ]]; then
    _err "Keine gültige Player-ID (1–999) – Abbruch."
fi
_log "Player-ID: $MCID"

# ----------------------------------------------------------------
# 2. mcdomain lesen (mcdomain.cfg → mc.cfg → Auswahl-Menü)
# ----------------------------------------------------------------
MCDOMAIN=$(grep '^DOMAIN=' /home/snowtv/bin/mcdomain.cfg 2>/dev/null | cut -d= -f2 | tr -d '\r')
if [ -z "$MCDOMAIN" ]; then
    _warn "mcdomain.cfg fehlt – suche in mc.cfg..."
    MCDOMAIN=$(grep '^DOMAIN=' /home/snowtv/bin/mc.cfg 2>/dev/null | cut -d= -f2 | awk '{print $1}' | tr -d '\r')
fi
if [ -z "$MCDOMAIN" ]; then
    _warn "Domain nicht gefunden – bitte manuell wählen."
    echo ""
    select INST in "infosnow (https://infosnow.ch)" "zbag (https://infosnow.zbag.ch)" "Andere"; do
        case $INST in
            "infosnow (https://infosnow.ch)")  MCDOMAIN="https://infosnow.ch"; break ;;
            "zbag (https://infosnow.zbag.ch)") MCDOMAIN="https://infosnow.zbag.ch"; break ;;
            "Andere") read -r -p "  Domain: " MCDOMAIN; break ;;
            *) echo "Ungültige Auswahl" ;;
        esac
    done
fi
[ -z "$MCDOMAIN" ] && _err "Keine Domain – Abbruch."
_log "Domain: $MCDOMAIN"

# ----------------------------------------------------------------
# 3. UEFI vs. BIOS erkennen
# ----------------------------------------------------------------
if [ -d /sys/firmware/efi ]; then
    BOOT_MODE="uefi"
    _log "Boot-Modus: UEFI"
else
    BOOT_MODE="bios"
    _log "Boot-Modus: BIOS/Legacy"
fi

# ----------------------------------------------------------------
# 4. SATA vs. NVMe erkennen
# ----------------------------------------------------------------
if [ -e /dev/nvme0n1 ]; then
    DISK="/dev/nvme0n1"
    PART1="${DISK}p1"
    PART2="${DISK}p2"
    _log "Disk: NVMe ($DISK)"
elif [ -e /dev/sda ]; then
    DISK="/dev/sda"
    PART1="${DISK}1"
    PART2="${DISK}2"
    _log "Disk: SATA ($DISK)"
else
    _err "Weder /dev/nvme0n1 noch /dev/sda gefunden – Abbruch."
fi

# ----------------------------------------------------------------
# 5. Bestätigung
# ----------------------------------------------------------------
_sep
echo ""
echo "  ########################################################"
echo "  #  ACHTUNG – DIESER VORGANG LÖSCHT DAS SYSTEM          #"
echo "  ########################################################"
echo ""
echo "  Player-ID   : $MCID"
echo "  Domain      : $MCDOMAIN"
echo "  Disk        : $DISK"
echo "  Boot-Modus  : $BOOT_MODE"
echo "  Ziel-OS     : Debian 13 (Trixie)"
echo ""
echo "  Vorteil gegenüber kexec: Bei Netzabbruch bleibt das"
echo "  laufende System im RAM aktiv – Retry via SSH möglich."
echo ""
echo "  Nach Schritt 'Disk formatieren' ist die alte Partition"
echo "  gelöscht. Stromausfall ab dann → physischer Zugriff nötig."
echo ""
read -r -p "  Fortfahren? (ja/NEIN): " CONFIRM
[ "$CONFIRM" != "ja" ] && { echo "Abgebrochen."; exit 0; }

# ----------------------------------------------------------------
# 6. EOL-Sources patchen (Buster, Stretch, etc.)
# ----------------------------------------------------------------
_fix_eol_sources() {
    local CODENAME
    CODENAME=$(grep -oP '(?<=DISTRIB_CODENAME=)\S+' /etc/lsb-release 2>/dev/null)
    [ -z "$CODENAME" ] && { . /etc/os-release 2>/dev/null; CODENAME="$VERSION_CODENAME"; }
    case "$CODENAME" in
        jessie|stretch|buster)
            _warn "EOL-System erkannt ($CODENAME) – wechsle auf archive.debian.org..."
            # jessie/stretch/buster: ${CODENAME}/updates  |  bullseye+: ${CODENAME}-security
            case "$CODENAME" in
                jessie|stretch|buster) SEC_SUFFIX="${CODENAME}/updates" ;;
                *)                     SEC_SUFFIX="${CODENAME}-security" ;;
            esac
            sudo tee /etc/apt/sources.list > /dev/null << EOF
deb http://archive.debian.org/debian ${CODENAME} main contrib non-free
deb http://archive.debian.org/debian-security ${SEC_SUFFIX} main contrib non-free
EOF
            sudo apt-get update -qq >> "$LOG" 2>&1 \
                || _err "apt-get update auf archive.debian.org fehlgeschlagen."
            _log "Sources auf archive.debian.org umgestellt."
            ;;
        *)
            sudo apt-get update -qq >> "$LOG" 2>&1 \
                || _err "apt-get update fehlgeschlagen – Netz prüfen."
            ;;
    esac
}
_fix_eol_sources

# ----------------------------------------------------------------
# 7. Benötigte Tools installieren
# ----------------------------------------------------------------
_log "Installiere debootstrap parted busybox-static..."
# Broken state vom ggf. vorherigen Upgrade (distro-info missing) reparieren
sudo DEBIAN_FRONTEND=noninteractive apt-get install -f -y >> "$LOG" 2>&1 || true
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y \
    debootstrap parted busybox-static >> "$LOG" 2>&1 \
    || _err "apt-get install fehlgeschlagen – Netz prüfen."

# Altes debootstrap (Buster 1.0.114) kennt usr-merge in trixie/sid nicht
# → neueste Version direkt von deb.debian.org laden
DBS_VER=$(dpkg-query -W -f='${Version}' debootstrap 2>/dev/null || echo "0")
_log "debootstrap installiert: $DBS_VER"
if dpkg --compare-versions "$DBS_VER" lt "1.0.130" 2>/dev/null; then
    _log "debootstrap zu alt für trixie – lade aktuelle Version von deb.debian.org..."
    DBS_DEB_URL="https://deb.debian.org/debian/pool/main/d/debootstrap"
    DBS_DEB=$(wget -qO- "${DBS_DEB_URL}/" \
        | grep -oP 'debootstrap_[\d.]+_all\.deb' | sort -V | tail -1)
    if [ -n "$DBS_DEB" ]; then
        wget -q "${DBS_DEB_URL}/${DBS_DEB}" -O /tmp/debootstrap-new.deb >> "$LOG" 2>&1 \
            || _warn "debootstrap-Download fehlgeschlagen – versuche es mit alter Version."
        if [ -f /tmp/debootstrap-new.deb ]; then
            # --force-depends: distro-info fehlt auf Buster, ist für debootstrap nicht nötig
            sudo dpkg -i --force-depends /tmp/debootstrap-new.deb >> "$LOG" 2>&1
            # Broken state reparieren (distro-info installieren falls verfügbar)
            sudo DEBIAN_FRONTEND=noninteractive apt-get install -f -y >> "$LOG" 2>&1 || true
            _log "debootstrap aktualisiert auf: $(dpkg-query -W -f='${Version}' debootstrap)"
        fi
    else
        _warn "Kein debootstrap-Paket gefunden – versuche es mit alter Version."
    fi
fi

DBS_PACKAGES="sudo,wget,curl,openssh-server,ca-certificates,locales,systemd-sysv"
# network-manager wird NICHT per debootstrap installiert (postinst braucht DBus,
# der im Chroot nicht läuft → Konfigurationsfehler). swinstall.sh übernimmt das.
# Netzwerk via systemd-networkd (in systemd enthalten) – kein ifupdown nötig.

# Altes debootstrap (Buster 1.0.114) kennt trixie nicht → DBS_SUITE auf sid setzen
DBS_SUITE="$SUITE"
if [ ! -e /usr/share/debootstrap/scripts/"$SUITE" ]; then
    DBS_SUITE="sid"
    _warn "debootstrap kennt '$SUITE' nicht – nutze 'sid' als Alias."
fi

# ----------------------------------------------------------------
# 7b. tmpfs-Fallback: wenn Ziel-Partition = laufender Root
# ----------------------------------------------------------------
# Kernel kann mkfs auf gemounteter Root-Partition nicht erzwingen.
# Lösung: debootstrap → tmpfs, Snapshot → EFI, GRUB bootet Trixie-Kernel mit
# local-premount Script: formatiert Root-Partition, entpackt Snapshot, bootet Debian 13.

_deploy_via_tmpfs() {
    _sep
    _warn "Ziel-Partition $PART2 ist aktiver Root – nutze tmpfs-Staging."

    # BIOS-Modus nicht unterstützt: Snapshot braucht EFI-Partition als Zwischenspeicher
    [ "$BOOT_MODE" = "bios" ] && \
        _err "tmpfs-Pfad erfordert UEFI (EFI-Partition als Snapshot-Speicher). Verwende remote_reinstall.sh für BIOS-Systeme."

    # RAM prüfen
    local FREE_MB
    FREE_MB=$(awk '/MemAvailable/{print int($2/1024)}' /proc/meminfo)
    [ "$FREE_MB" -lt 1500 ] && \
        _err "Zu wenig RAM (${FREE_MB}MB frei, min. 1500MB). Verwende remote_reinstall.sh."
    _log "Verfügbarer RAM: ${FREE_MB}MB – OK."

    # Altes tmpfs aufräumen (bei Retry wären sonst Dateien vom Vorversuch vorhanden)
    sudo umount -l "$TARGET" 2>/dev/null || true
    sudo umount -l "$TARGET" 2>/dev/null || true
    sudo rm -rf "$TARGET"
    sudo mkdir -p "$TARGET"

    # tmpfs mounten
    sudo mount -t tmpfs -o size=1400M tmpfs "$TARGET" \
        || _err "tmpfs mount fehlgeschlagen."

    # debootstrap mit Kernel (minbase + nötige Pakete)
    # Altes debootstrap (Buster 1.0.114) kennt trixie nicht → sid als Alias
    local DBS_SUITE="$SUITE"
    if [ ! -e /usr/share/debootstrap/scripts/"$SUITE" ]; then
        DBS_SUITE="sid"
        _log "debootstrap kennt '$SUITE' nicht – nutze 'sid' als Alias."
    fi
    _log "debootstrap Debian 13 in tmpfs (suite=$DBS_SUITE, minbase + linux-image-amd64)..."
    local TMPFS_PKGS="${DBS_PACKAGES},linux-image-amd64,grub-efi-amd64,e2fsprogs,xz-utils"
    sudo debootstrap \
        --variant=minbase \
        --include="$TMPFS_PKGS" \
        "$DBS_SUITE" "$TARGET" "$MIRROR" >> "$LOG" 2>&1 || _err "debootstrap fehlgeschlagen."
    _log "debootstrap abgeschlossen."

    # chroot konfigurieren (sources, locale, fstab, user, mcid, firstboot)
    sudo tee "$TARGET/etc/apt/sources.list" > /dev/null << EOF
deb $MIRROR $SUITE main contrib non-free non-free-firmware
deb http://security.debian.org/debian-security ${SUITE}-security main contrib non-free non-free-firmware
EOF
    local HN
    HN=$(hostname)
    echo "$HN" | sudo tee "$TARGET/etc/hostname" > /dev/null
    printf "127.0.0.1\tlocalhost\n127.0.1.1\t%s\n" "$HN" | sudo tee "$TARGET/etc/hosts" > /dev/null
    echo "Europe/Zurich" | sudo tee "$TARGET/etc/timezone" > /dev/null
    sudo ln -sf /usr/share/zoneinfo/Europe/Zurich "$TARGET/etc/localtime"
    echo "de_CH.UTF-8 UTF-8" | sudo tee -a "$TARGET/etc/locale.gen" > /dev/null
    # LABEL statt UUID: initrd formatiert PART2 neu (mke2fs -L snowtv-root) → UUID ändert sich
    sudo tee "$TARGET/etc/fstab" > /dev/null << EOF
LABEL=snowtv-root  /          ext4  errors=remount-ro  0  1
EOF
    if [ "$BOOT_MODE" = "uefi" ]; then
        local EFI_UUID
        EFI_UUID=$(sudo blkid -s UUID -o value "$PART1")
        echo "UUID=$EFI_UUID  /boot/efi  vfat  umask=0077  0  2" \
            | sudo tee -a "$TARGET/etc/fstab" > /dev/null
    fi
    # Netzwerk: systemd-networkd mit Type=ether – funktioniert mit Predictable Interface Names
    sudo mkdir -p "$TARGET/etc/systemd/network"
    sudo tee "$TARGET/etc/systemd/network/10-eth-dhcp.network" > /dev/null << 'NETEOF'
[Match]
Type=ether

[Network]
DHCP=yes
NETEOF

    sudo chroot "$TARGET" /bin/bash -c "
        export DEBIAN_FRONTEND=noninteractive
        locale-gen
        update-locale LANG=de_CH.UTF-8
        useradd -m -s /bin/bash snowtv
        echo 'snowtv:snowtv123' | chpasswd
        adduser snowtv sudo 2>/dev/null || true
    " >> "$LOG" 2>&1

    echo 'snowtv ALL=(ALL) NOPASSWD: ALL' | \
        sudo tee "$TARGET/etc/sudoers.d/snowtv-install" > /dev/null
    sudo chmod 440 "$TARGET/etc/sudoers.d/snowtv-install"

    sudo mkdir -p "$TARGET/home/snowtv/bin"
    echo "ID=$MCID"         | sudo tee "$TARGET/home/snowtv/bin/mcid.cfg"    > /dev/null
    echo "DOMAIN=$MCDOMAIN" | sudo tee "$TARGET/home/snowtv/bin/mcdomain.cfg" > /dev/null
    sudo chown -R 1000:1000 "$TARGET/home/snowtv/bin"

    # firstboot-Service (identisch zum normalen Flow)
    sudo touch "$TARGET/var/lib/snowtv-install-pending"
    sudo tee "$TARGET/home/snowtv/firstboot.sh" > /dev/null << 'FBEOF'
#!/bin/bash
LOG="/home/snowtv/stv-install.log"
echo "$(date)  INFO: SnowTV First Boot gestartet" | tee -a "$LOG"

# EFI-Cleanup: Reinstall-Dateien entfernen (aus vorherigem Remote-Reinstall)
if mountpoint -q /boot/efi 2>/dev/null; then
    sudo rm -f /boot/efi/newroot.cpio.xz \
               /boot/efi/vmlinuz-snowtv-install \
               /boot/efi/initrd-snowtv-install
    sudo rm -f /etc/grub.d/99_snowtv_reinstall
    sudo update-grub >> "$LOG" 2>&1 || true
    echo "$(date)  INFO: EFI-Cleanup abgeschlossen" | tee -a "$LOG"
fi

# initramfs-Hook + Premount-Script entfernen und initrd regenerieren
sudo rm -f /etc/initramfs-tools/hooks/snowtv-install
sudo rm -f /etc/initramfs-tools/scripts/local-premount/00-snowtv-format
sudo update-initramfs -u -k all >> "$LOG" 2>&1 || true
echo "$(date)  INFO: initrd bereinigt (snowtv-install Hook entfernt)" | tee -a "$LOG"

cd /home/snowtv
for i in 1 2 3 4 5; do
    wget -q --no-check-certificate https://172.105.95.252/swinstall.sh -O swinstall.sh && break
    sleep 10
done
[ -s swinstall.sh ] || { echo "$(date) ERROR: swinstall.sh Download fehlgeschlagen oder leer" | tee -a "$LOG"; rm -f swinstall.sh; exit 1; }
chmod +x swinstall.sh
sudo rm -f /var/lib/snowtv-install-pending
bash /home/snowtv/swinstall.sh 2>&1 | tee -a "$LOG"
FBEOF
    sudo chown 1000:1000 "$TARGET/home/snowtv/firstboot.sh"
    sudo chmod 755 "$TARGET/home/snowtv/firstboot.sh"
    sudo tee "$TARGET/etc/systemd/system/snowtv-install.service" > /dev/null << 'SVCEOF'
[Unit]
Description=SnowTV Player Erstinstallation
After=network-online.target
Wants=network-online.target
ConditionPathExists=/var/lib/snowtv-install-pending

[Service]
Type=oneshot
User=snowtv
Environment=HOME=/home/snowtv
WorkingDirectory=/home/snowtv
ExecStart=/bin/bash /home/snowtv/firstboot.sh
StandardOutput=journal+console
StandardError=journal+console
TimeoutStartSec=1800

[Install]
WantedBy=multi-user.target
SVCEOF
    sudo mkdir -p "$TARGET/etc/systemd/system/multi-user.target.wants"
    sudo ln -sf /etc/systemd/system/snowtv-install.service \
        "$TARGET/etc/systemd/system/multi-user.target.wants/snowtv-install.service"
    # systemd-networkd aktivieren (Netzwerk für firstboot.sh)
    sudo mkdir -p "$TARGET/etc/systemd/system/network-online.target.wants"
    for SVC in systemd-networkd.service systemd-resolved.service; do
        sudo ln -sf "/lib/systemd/system/${SVC}" \
            "$TARGET/etc/systemd/system/multi-user.target.wants/${SVC}" 2>/dev/null || true
    done
    # systemd-networkd-wait-online: network-online.target wartet auf DHCP-Lease
    sudo ln -sf /lib/systemd/system/systemd-networkd-wait-online.service \
        "$TARGET/etc/systemd/system/network-online.target.wants/systemd-networkd-wait-online.service" \
        2>/dev/null || true

    # initramfs-Hook: baut mke2fs in die Trixie-initrd ein (via copy_exec)
    # → wird beim update-initramfs im Chroot automatisch eingebunden
    _log "Schreibe initramfs-Hook + Premount-Script..."
    sudo mkdir -p "$TARGET/etc/initramfs-tools/hooks"
    sudo mkdir -p "$TARGET/etc/initramfs-tools/scripts/local-premount"

    sudo tee "$TARGET/etc/initramfs-tools/hooks/snowtv-install" > /dev/null << 'HOOKEOF'
#!/bin/sh
PREREQ=""
prereqs() { echo "$PREREQ"; }
case $1 in prereqs) prereqs; exit 0;; esac
. /usr/share/initramfs-tools/hook-functions
[ -x /usr/sbin/mke2fs ] && copy_exec /usr/sbin/mke2fs /usr/sbin/mke2fs
[ -x /sbin/mke2fs     ] && copy_exec /sbin/mke2fs     /sbin/mke2fs
[ -x /usr/bin/xz      ] && copy_exec /usr/bin/xz      /usr/bin/xz
[ -x /usr/bin/cpio    ] && copy_exec /usr/bin/cpio     /usr/bin/cpio
HOOKEOF
    sudo chmod +x "$TARGET/etc/initramfs-tools/hooks/snowtv-install"

    # Premount-Script: liest PART1/PART2 aus Kernel-Cmdline (snowtv_part1=, snowtv_part2=)
    # Läuft nur wenn snowtv_install=1 im Kernel-Cmdline → sicher für normale Boots
    sudo tee "$TARGET/etc/initramfs-tools/scripts/local-premount/00-snowtv-format" > /dev/null << 'PMEOF'
#!/bin/sh
PREREQS=""
prereqs() { echo "$PREREQS"; }
case $1 in prereqs) prereqs; exit 0;; esac

# Shell-only cmdline parsing – kein grep/cut im Debian initrd verfügbar
CMDLINE=$(cat /proc/cmdline)
case "$CMDLINE" in
    *snowtv_install=1*) ;;
    *) exit 0 ;;
esac
for _p in $CMDLINE; do
    case "$_p" in
        snowtv_part1=*) PART1="${_p#snowtv_part1=}" ;;
        snowtv_part2=*) PART2="${_p#snowtv_part2=}" ;;
    esac
done

DBG="/dev/null"
log() {
    echo "SNOWTV: $*" > /dev/tty0 2>/dev/null
    echo "SNOWTV: $*" > /dev/kmsg  2>/dev/null
    echo "SNOWTV: $*" >> "$DBG"
}

log "=== premount start PART1=$PART1 PART2=$PART2 ==="

# Warte bis Block-Devices verfügbar (SATA-Timing)
_W=0
while [ ! -b "$PART1" ] || [ ! -b "$PART2" ]; do
    [ $_W -ge 30 ] && { log "TIMEOUT: $PART1 oder $PART2 nicht gefunden"; exit 1; }
    sleep 1; _W=$((_W+1))
done
log "Devices bereit nach ${_W}s"

modprobe vfat      2>/dev/null || true
modprobe nls_cp437 2>/dev/null || true

mkdir -p /mnt/snowtv-dbg
_MOUNT_TRIES=0
while [ $_MOUNT_TRIES -lt 5 ]; do
    mount -t vfat "$PART1" /mnt/snowtv-dbg 2>/dev/null && break
    _MOUNT_TRIES=$((_MOUNT_TRIES+1)); sleep 1
done
if [ $_MOUNT_TRIES -lt 5 ]; then
    DBG="/mnt/snowtv-dbg/debug.log"
    log "EFI mount OK (nach ${_MOUNT_TRIES} Versuchen)"
else
    log "EFI mount fehlgeschlagen – debug via kmsg only"
fi

mke2fs -t ext4 -F -L snowtv-root "$PART2" >> "$DBG" 2>&1
RC=$?
log "mke2fs: $RC"
[ $RC -ne 0 ] && { umount /mnt/snowtv-dbg 2>/dev/null; exit 1; }

mkdir -p /mnt/snowtv-root
mount -t ext4 "$PART2" /mnt/snowtv-root >> "$DBG" 2>&1 || { log "FEHLER mount root"; exit 1; }

# EFI bereits unter /mnt/snowtv-dbg gemountet – nicht nochmal mounten (double-mount schlägt fehl)
if [ "$DBG" != "/dev/null" ]; then
    SNOWTV_EFI="/mnt/snowtv-dbg"
else
    mkdir -p /mnt/snowtv-efi
    mount -t vfat "$PART1" /mnt/snowtv-efi >> "$DBG" 2>&1 || { log "FEHLER mount EFI"; exit 1; }
    SNOWTV_EFI="/mnt/snowtv-efi"
fi

log "Entpacke Snapshot von $SNOWTV_EFI..."
xz -d -c "$SNOWTV_EFI/newroot.cpio.xz" | \
    (cd /mnt/snowtv-root && cpio -i -d -H newc --no-absolute-filenames) >> "$DBG" 2>&1
RC=$?
log "cpio: $RC"
[ $RC -ne 0 ] && { [ "$SNOWTV_EFI" = "/mnt/snowtv-efi" ] && umount /mnt/snowtv-efi; umount /mnt/snowtv-root; exit 1; }

[ "$SNOWTV_EFI" = "/mnt/snowtv-efi" ] && umount /mnt/snowtv-efi
umount /mnt/snowtv-root
log "Fertig"
PMEOF
    sudo chmod +x "$TARGET/etc/initramfs-tools/scripts/local-premount/00-snowtv-format"

    # GRUB-Install aus Chroot wird ABSICHTLICH übersprungen:
    # Der laufende GRUB (Bullseye/Buster) verwaltet den Boot via grubenv.
    # grub-install aus dem Trixie-Chroot würde den laufenden GRUB überschreiben
    # und ihn bootunfähig machen (falsche Modul-Pfade).
    # Der GRUB-Eintrag "SnowTV Reinstall" wird weiter unten via update-grub gesetzt.
    _log "GRUB-Install aus Chroot übersprungen (laufender GRUB bleibt erhalten)."
    sudo mount --bind /dev     "$TARGET/dev"
    sudo mount --bind /dev/pts "$TARGET/dev/pts"
    sudo mount --bind /proc    "$TARGET/proc"
    sudo mount --bind /sys     "$TARGET/sys"
    if [ "$BOOT_MODE" = "uefi" ]; then
        sudo mkdir -p "$TARGET/boot/efi"
        sudo mount --bind /boot/efi "$TARGET/boot/efi"
        # grub-install NICHT ausführen – würde laufenden GRUB zerstören
        sudo umount "$TARGET/boot/efi" 2>/dev/null
    else
        : # grub-install NICHT ausführen – würde laufenden GRUB zerstören
    fi
    sudo chroot "$TARGET" update-grub >> "$LOG" 2>&1 \
        || _warn "update-grub im tmpfs-Pfad fehlgeschlagen (nicht kritisch – Reinstall-initrd bootet trotzdem)."
    # initrd neu generieren – jetzt MIT unserem Hook + Premount-Script
    _log "Generiere initrd (mit snowtv-install Hook)..."
    sudo chroot "$TARGET" update-initramfs -u -k all >> "$LOG" 2>&1 \
        || _err "update-initramfs fehlgeschlagen."
    sudo umount "$TARGET/dev/pts" "$TARGET/dev" \
                "$TARGET/proc"    "$TARGET/sys"  2>/dev/null
    _log "GRUB + initrd fertig."

    # Alte Reinstall-Dateien von Vorversuch entfernen (Platz für neuen Snapshot)
    sudo rm -f /boot/efi/newroot.cpio.xz \
               /boot/efi/newroot.tar.xz \
               /boot/efi/vmlinuz-snowtv-install \
               /boot/efi/initrd-snowtv-install \
               /boot/efi/initrd-snowtv-install.gz
    _log "EFI-Cleanup: alte Reinstall-Dateien entfernt (falls vorhanden)."

    # Snapshot auf EFI-Partition (xz, ~120MB)
    _log "Erstelle System-Snapshot auf EFI-Partition (xz, bitte warten)..."
    local EFI_FREE
    EFI_FREE=$(df -m /boot/efi | awk 'NR==2{print $4}')
    [ "${EFI_FREE:-0}" -lt 400 ] && _err "EFI-Partition zu wenig Platz (${EFI_FREE}MB frei, 400MB benötigt)."
    sudo sh -c "cd '$TARGET' && find . \
        ! -path './proc/*' ! -path './sys/*' ! -path './dev/*' \
        ! -path './run/*'  ! -path './tmp/*' \
        | cpio -H newc -o | xz -6 > /boot/efi/newroot.cpio.xz" >> "$LOG" 2>&1 \
        || _err "cpio-Snapshot auf EFI fehlgeschlagen (${EFI_FREE}MB frei). EFI evtl. zu klein."
    _log "Snapshot: $(du -sh /boot/efi/newroot.cpio.xz | awk '{print $1}')"

    # Kernel aus debootstrap für GRUB-Start
    local NEW_KERNEL
    NEW_KERNEL=$(ls "$TARGET"/boot/vmlinuz-* 2>/dev/null | sort -V | tail -1)
    [ -z "$NEW_KERNEL" ] && _err "Kein Kernel im debootstrap – Installation unvollständig."
    sudo cp "$NEW_KERNEL" /tmp/new-vmlinuz
    _log "Kernel: $NEW_KERNEL"

    # initrd aus Trixie-System (update-initramfs hat snowtv-install Hook eingebaut)
    local STD_INITRD
    STD_INITRD=$(ls "$TARGET"/boot/initrd.img-* 2>/dev/null | sort -V | tail -1)
    [ -z "$STD_INITRD" ] && _err "Kein initrd.img im debootstrap – linux-image nicht installiert?"
    _log "initrd: $STD_INITRD ($(du -sh "$STD_INITRD" | cut -f1))"

    # Kernel + initrd auf EFI-Partition kopieren (GRUB lädt von dort)
    _log "Kopiere Kernel + initrd auf EFI-Partition..."
    sudo cp "$NEW_KERNEL" /boot/efi/vmlinuz-snowtv-install
    sudo cp "$STD_INITRD" /boot/efi/initrd-snowtv-install
    _log "EFI: $(du -sh /boot/efi/vmlinuz-snowtv-install /boot/efi/initrd-snowtv-install \
        | awk '{print $1, $2}' | tr '\n' ' ')"

    # GRUB-Eintrag für Reinstall-Kernel anlegen
    local EFI_UUID
    EFI_UUID=$(sudo blkid -s UUID -o value "${PART1}")
    sudo tee /etc/grub.d/99_snowtv_reinstall > /dev/null << GRUBEOF
#!/bin/sh
exec tail -n +3 \$0
# SnowTV Remote Reinstall – automatisch generiert, nach Reinstall loeschen

menuentry "SnowTV Reinstall" {
    insmod part_gpt
    insmod fat
    search --no-floppy --fs-uuid --set=root ${EFI_UUID}
    echo "Starte SnowTV Reinstall-Kernel..."
    linux  /vmlinuz-snowtv-install root=${PART2} rootfstype=ext4 snowtv_install=1 snowtv_part1=${PART1} snowtv_part2=${PART2} console=tty0 panic=30
    initrd /initrd-snowtv-install
}
GRUBEOF
    sudo chmod +x /etc/grub.d/99_snowtv_reinstall
    sudo update-grub >> "$LOG" 2>&1 \
        || _err "update-grub fehlgeschlagen – GRUB-Eintrag nicht registriert."

    # Nächsten Boot auf Reinstall-Eintrag setzen
    sudo grub-reboot "SnowTV Reinstall" >> "$LOG" 2>&1 \
        || _err "grub-reboot fehlgeschlagen – GRUB-Eintrag nicht gefunden?"

    _sep
    _log "GRUB-Reboot konfiguriert. Neustart in 5 Sekunden..."
    _log "Player bootet via GRUB in Reinstall-Kernel – Verbindung wird getrennt."
    _log "Nach Formatierung + Entpacken (~8 Min) startet swinstall.sh."
    _log "Player nach ~30 Min erreichbar via: ssh -p 10${MCID} snowtv@139.162.165.199"
    sleep 5
    sudo reboot
    _err "reboot fehlgeschlagen."  # sollte nie erreicht werden
}

# ----------------------------------------------------------------
# LVM-Pfad: Debian 13 direkt auf neuem LV installieren
# (kein tmpfs, kein cpio, kein initrd-Hook – robuster als tmpfs-Pfad)
# Voraussetzung: >= 20 GB freier Speicher nach letzter Partition
# ----------------------------------------------------------------
_deploy_via_lvm() {
    _sep
    _log "LVM-Pfad: Installiere Debian 13 auf neuem LV neben bestehendem System."

    # lvm2 auf Host installieren
    sudo DEBIAN_FRONTEND=noninteractive apt-get install -y lvm2 >> "$LOG" 2>&1 \
        || _err "lvm2 Installation fehlgeschlagen."

    # Disk-Größe und Ende letzter Partition ermitteln
    local DISK_SIZE_MiB LAST_END_MiB FREE_MiB
    DISK_SIZE_MiB=$(sudo parted -s "$DISK" unit MiB print 2>/dev/null \
        | awk '/^Disk \/dev/{gsub(/[^0-9.]/,"",$3); print int($3)}')
    LAST_END_MiB=$(sudo parted -s "$DISK" unit MiB print 2>/dev/null \
        | awk '/^ [0-9]/{gsub(/[^0-9.]/,"",$3); e=$3+0} END{printf "%.0f\n", e}')
    FREE_MiB=$(( DISK_SIZE_MiB - LAST_END_MiB ))
    _log "Disk ${DISK_SIZE_MiB}MiB, letzte Partition endet bei ${LAST_END_MiB}MiB, frei: ${FREE_MiB}MiB"
    [ "${FREE_MiB:-0}" -lt 20480 ] && \
        _err "Zu wenig freier Speicher (${FREE_MiB}MiB, min. 20480MiB = 20GB)."

    # Nächste freie Partitionsnummer
    local LAST_PART_NUM LVM_PART_NUM LVM_PART
    LAST_PART_NUM=$(sudo parted -s "$DISK" print 2>/dev/null \
        | awk '/^ [0-9]/{n=$1} END{print n+0}')
    LVM_PART_NUM=$(( LAST_PART_NUM + 1 ))
    if echo "$DISK" | grep -q "nvme"; then
        LVM_PART="${DISK}p${LVM_PART_NUM}"
    else
        LVM_PART="${DISK}${LVM_PART_NUM}"
    fi
    _log "Neue LVM-Partition: $LVM_PART (Nr. $LVM_PART_NUM)"

    # Partition anlegen (1 MiB Puffer nach letzter Partition)
    local LAST_END_CEIL=$(( LAST_END_MiB + 1 ))
    sudo parted -s "$DISK" -- mkpart primary "${LAST_END_CEIL}MiB" "100%" \
        >> "$LOG" 2>&1 || _err "mkpart für LVM-PV fehlgeschlagen."
    sudo parted -s "$DISK" set "${LVM_PART_NUM}" lvm on >> "$LOG" 2>&1 || true
    sudo partprobe "$DISK" 2>/dev/null || sudo blockdev --rereadpt "$DISK" 2>/dev/null || true
    sleep 2
    [ -b "$LVM_PART" ] || _err "Partition $LVM_PART nicht gefunden nach mkpart."
    _log "Partition $LVM_PART angelegt."

    # LVM aufräumen (Vorversuch), dann erstellen
    local LVM_VG="snowtv_vg" LVM_LV="root_b" LVM_DEV
    LVM_DEV="/dev/${LVM_VG}/${LVM_LV}"
    sudo vgchange -an "${LVM_VG}" 2>/dev/null || true
    sudo vgremove -ffy "${LVM_VG}" 2>/dev/null || true
    sudo pvremove -ff "$LVM_PART" 2>/dev/null || true

    sudo pvcreate -f "$LVM_PART" >> "$LOG" 2>&1 || _err "pvcreate fehlgeschlagen."
    sudo vgcreate  "$LVM_VG" "$LVM_PART" >> "$LOG" 2>&1 || _err "vgcreate fehlgeschlagen."
    sudo lvcreate -L 15G -n "$LVM_LV" "$LVM_VG" >> "$LOG" 2>&1 || _err "lvcreate fehlgeschlagen."
    sudo vgchange -ay "$LVM_VG" >> "$LOG" 2>&1
    _log "LVM bereit: $LVM_DEV"

    sudo mkfs.ext4 -F -L snowtv-trixie "$LVM_DEV" >> "$LOG" 2>&1 \
        || _err "mkfs.ext4 auf LV fehlgeschlagen."

    # Mounten
    sudo umount -l "$TARGET" 2>/dev/null || true
    sudo rm -rf "$TARGET"
    sudo mkdir -p "$TARGET"
    sudo mount "$LVM_DEV" "$TARGET" >> "$LOG" 2>&1 \
        || _err "Mount $LVM_DEV → $TARGET fehlgeschlagen."
    if [ "$BOOT_MODE" = "uefi" ]; then
        sudo mkdir -p "$TARGET/boot/efi"
        sudo mount "$PART1" "$TARGET/boot/efi" >> "$LOG" 2>&1 || _err "EFI-Mount fehlgeschlagen."
    fi

    # debootstrap: inkl. linux-image-amd64, lvm2, GRUB
    local LVM_PKGS
    LVM_PKGS="${DBS_PACKAGES},linux-image-amd64,lvm2"
    [ "$BOOT_MODE" = "uefi" ] \
        && LVM_PKGS="${LVM_PKGS},grub-efi-amd64" \
        || LVM_PKGS="${LVM_PKGS},grub-pc"
    _log "debootstrap Debian 13 auf LV (suite=$DBS_SUITE, inkl. lvm2)..."
    local ATTEMPT DBS_OK
    ATTEMPT=0; DBS_OK=0
    while [ $DBS_OK -eq 0 ]; do
        ATTEMPT=$(( ATTEMPT + 1 ))
        _log "debootstrap Versuch $ATTEMPT..."
        [ $ATTEMPT -gt 1 ] && sudo find "$TARGET" -mindepth 1 -maxdepth 1 -exec rm -rf {} + 2>/dev/null
        sudo debootstrap --arch=amd64 --include="$LVM_PKGS" \
            "$DBS_SUITE" "$TARGET" "$MIRROR" >> "$LOG" 2>&1
        if [ $? -eq 0 ]; then
            DBS_OK=1; _log "debootstrap erfolgreich."
        else
            _warn "debootstrap fehlgeschlagen (Versuch $ATTEMPT)."
            read -r -p "  Erneut versuchen? (ja/nein): " RETRY
            [ "$RETRY" != "ja" ] && _err "Abgebrochen. LV $LVM_DEV bleibt unter $TARGET gemountet."
            sleep 15
        fi
    done

    # Chroot konfigurieren: sources, locale, hostname, fstab, Netzwerk
    sudo tee "$TARGET/etc/apt/sources.list" > /dev/null << EOF
deb $MIRROR $SUITE main contrib non-free non-free-firmware
deb http://security.debian.org/debian-security ${SUITE}-security main contrib non-free non-free-firmware
EOF
    local HN; HN=$(hostname)
    echo "$HN" | sudo tee "$TARGET/etc/hostname" > /dev/null
    printf "127.0.0.1\tlocalhost\n127.0.1.1\t%s\n" "$HN" | sudo tee "$TARGET/etc/hosts" > /dev/null
    echo "Europe/Zurich" | sudo tee "$TARGET/etc/timezone" > /dev/null
    sudo ln -sf /usr/share/zoneinfo/Europe/Zurich "$TARGET/etc/localtime"
    echo "de_CH.UTF-8 UTF-8" | sudo tee -a "$TARGET/etc/locale.gen" > /dev/null

    local LV_UUID EFI_UUID
    LV_UUID=$(sudo blkid -s UUID -o value "$LVM_DEV")
    sudo tee "$TARGET/etc/fstab" > /dev/null << EOF
UUID=${LV_UUID}  /          ext4  errors=remount-ro  0  1
EOF
    if [ "$BOOT_MODE" = "uefi" ]; then
        EFI_UUID=$(sudo blkid -s UUID -o value "$PART1")
        echo "UUID=${EFI_UUID}  /boot/efi  vfat  umask=0077  0  2" \
            | sudo tee -a "$TARGET/etc/fstab" > /dev/null
    fi

    sudo mkdir -p "$TARGET/etc/systemd/network"
    sudo tee "$TARGET/etc/systemd/network/10-eth-dhcp.network" > /dev/null << 'NETEOF'
[Match]
Type=ether

[Network]
DHCP=yes
NETEOF

    # Bind-Mounts + chroot: locale, user, services, initrd
    sudo mount --bind /dev     "$TARGET/dev"
    sudo mount --bind /dev/pts "$TARGET/dev/pts"
    sudo mount --bind /proc    "$TARGET/proc"
    sudo mount --bind /sys     "$TARGET/sys"

    sudo chroot "$TARGET" /bin/bash -c "
        export DEBIAN_FRONTEND=noninteractive
        locale-gen
        update-locale LANG=de_CH.UTF-8
        useradd -m -s /bin/bash snowtv
        echo 'snowtv:snowtv123' | chpasswd
        adduser snowtv sudo 2>/dev/null || true
        update-initramfs -u -k all
    " >> "$LOG" 2>&1 || _warn "chroot teilweise fehlgeschlagen – prüfe $LOG."

    # systemd-networkd explizit via Symlinks aktivieren (systemctl enable im Chroot ist unzuverlässig)
    sudo mkdir -p "$TARGET/etc/systemd/system/multi-user.target.wants"
    sudo mkdir -p "$TARGET/etc/systemd/system/network-online.target.wants"
    for SVC in systemd-networkd.service systemd-resolved.service; do
        sudo ln -sf "/lib/systemd/system/${SVC}" \
            "$TARGET/etc/systemd/system/multi-user.target.wants/${SVC}"
    done
    sudo ln -sf /lib/systemd/system/systemd-networkd-wait-online.service \
        "$TARGET/etc/systemd/system/network-online.target.wants/systemd-networkd-wait-online.service"

    echo 'snowtv ALL=(ALL) NOPASSWD: ALL' | \
        sudo tee "$TARGET/etc/sudoers.d/snowtv-install" > /dev/null
    sudo chmod 440 "$TARGET/etc/sudoers.d/snowtv-install"

    sudo mkdir -p "$TARGET/home/snowtv/bin"
    echo "ID=$MCID"         | sudo tee "$TARGET/home/snowtv/bin/mcid.cfg"    > /dev/null
    echo "DOMAIN=$MCDOMAIN" | sudo tee "$TARGET/home/snowtv/bin/mcdomain.cfg" > /dev/null
    sudo chown -R 1000:1000 "$TARGET/home/snowtv/bin"

    # firstboot-Service (LVM: GRUB permanent installieren nach erstem erfolgreichen Boot)
    sudo touch "$TARGET/var/lib/snowtv-install-pending"
    sudo tee "$TARGET/home/snowtv/firstboot.sh" > /dev/null << 'FBEOF'
#!/bin/bash
LOG="/home/snowtv/stv-install.log"
echo "$(date)  INFO: SnowTV First Boot (LVM) gestartet" | tee -a "$LOG"

# GRUB jetzt permanent installieren (Trixie bootet – kein Risiko mehr)
if [ -d /sys/firmware/efi ]; then
    sudo grub-install --target=x86_64-efi --efi-directory=/boot/efi \
        --bootloader-id=debian --removable >> "$LOG" 2>&1 \
        && echo "$(date)  INFO: grub-install (UEFI) OK" | tee -a "$LOG" \
        || echo "$(date)  WARN: grub-install fehlgeschlagen" | tee -a "$LOG"
else
    ROOT_DISK=$(lsblk -no pkname "$(findmnt -n -o SOURCE /)" 2>/dev/null | head -1)
    [ -n "$ROOT_DISK" ] && sudo grub-install "/dev/${ROOT_DISK}" >> "$LOG" 2>&1 \
        && echo "$(date)  INFO: grub-install (BIOS) OK" | tee -a "$LOG" \
        || echo "$(date)  WARN: grub-install fehlgeschlagen" | tee -a "$LOG"
fi
sudo rm -f /etc/grub.d/99_snowtv_trixie_lvm 2>/dev/null
sudo update-grub >> "$LOG" 2>&1 || true
echo "$(date)  INFO: GRUB bereinigt" | tee -a "$LOG"

cd /home/snowtv
for i in 1 2 3 4 5; do
    wget -q --no-check-certificate https://172.105.95.252/swinstall.sh -O swinstall.sh && break
    sleep 10
done
[ -s swinstall.sh ] || { echo "$(date) ERROR: swinstall.sh Download fehlgeschlagen oder leer" | tee -a "$LOG"; rm -f swinstall.sh; exit 1; }
chmod +x swinstall.sh
sudo rm -f /var/lib/snowtv-install-pending
bash /home/snowtv/swinstall.sh 2>&1 | tee -a "$LOG"
FBEOF
    sudo chown 1000:1000 "$TARGET/home/snowtv/firstboot.sh"
    sudo chmod 755 "$TARGET/home/snowtv/firstboot.sh"

    sudo tee "$TARGET/etc/systemd/system/snowtv-install.service" > /dev/null << 'SVCEOF'
[Unit]
Description=SnowTV Player Erstinstallation
After=network-online.target
Wants=network-online.target
ConditionPathExists=/var/lib/snowtv-install-pending

[Service]
Type=oneshot
User=snowtv
Environment=HOME=/home/snowtv
WorkingDirectory=/home/snowtv
ExecStart=/bin/bash /home/snowtv/firstboot.sh
StandardOutput=journal+console
StandardError=journal+console
TimeoutStartSec=1800

[Install]
WantedBy=multi-user.target
SVCEOF
    sudo mkdir -p "$TARGET/etc/systemd/system/multi-user.target.wants"
    sudo ln -sf /etc/systemd/system/snowtv-install.service \
        "$TARGET/etc/systemd/system/multi-user.target.wants/snowtv-install.service"

    # Kernel + initrd aus LV für GRUB bereitstellen
    local NEW_KERNEL NEW_INITRD
    NEW_KERNEL=$(ls "$TARGET"/boot/vmlinuz-* 2>/dev/null | sort -V | tail -1)
    NEW_INITRD=$(ls "$TARGET"/boot/initrd.img-* 2>/dev/null | sort -V | tail -1)
    [ -z "$NEW_KERNEL" ] && _err "Kein Kernel im debootstrap – Installation unvollständig."
    [ -z "$NEW_INITRD" ] && _err "Kein initrd.img – linux-image nicht installiert?"
    _log "Kernel: $(basename "$NEW_KERNEL") | initrd: $(basename "$NEW_INITRD")"

    local LVM_MAPPER="/dev/mapper/${LVM_VG}-${LVM_LV}"
    if [ "$BOOT_MODE" = "uefi" ]; then
        # Kernel + initrd auf EFI-Partition (GRUB liest von dort)
        sudo cp "$NEW_KERNEL" /boot/efi/vmlinuz-trixie-lvm
        sudo cp "$NEW_INITRD" /boot/efi/initrd-trixie-lvm
        _log "Kernel + initrd → EFI: $(du -sh /boot/efi/vmlinuz-trixie-lvm /boot/efi/initrd-trixie-lvm | awk '{print $1, $2}' | tr '\n' ' ')"
        [ -z "$EFI_UUID" ] && EFI_UUID=$(sudo blkid -s UUID -o value "$PART1")
        sudo tee /etc/grub.d/99_snowtv_trixie_lvm > /dev/null << GRUBEOF
#!/bin/sh
exec tail -n +3 \$0
# SnowTV Trixie LVM – automatisch generiert, wird nach erstem Boot geloescht

menuentry "SnowTV Trixie LVM" {
    insmod part_gpt
    insmod fat
    insmod lvm
    search --no-floppy --fs-uuid --set=root ${EFI_UUID}
    echo "Starte SnowTV Trixie (LVM)..."
    linux  /vmlinuz-trixie-lvm root=${LVM_MAPPER} ro quiet
    initrd /initrd-trixie-lvm
}
GRUBEOF
    else
        # BIOS: Kernel + initrd in /boot/ des laufenden Systems
        sudo cp "$NEW_KERNEL" /boot/vmlinuz-trixie-lvm
        sudo cp "$NEW_INITRD" /boot/initrd-trixie-lvm
        _log "Kernel + initrd → /boot/: $(du -sh /boot/vmlinuz-trixie-lvm /boot/initrd-trixie-lvm | awk '{print $1, $2}' | tr '\n' ' ')"
        sudo tee /etc/grub.d/99_snowtv_trixie_lvm > /dev/null << GRUBEOF
#!/bin/sh
exec tail -n +3 \$0
# SnowTV Trixie LVM – automatisch generiert, wird nach erstem Boot geloescht

menuentry "SnowTV Trixie LVM" {
    insmod part_msdos
    insmod lvm
    insmod ext2
    linux /boot/vmlinuz-trixie-lvm root=${LVM_MAPPER} ro quiet
    initrd /boot/initrd-trixie-lvm
}
GRUBEOF
    fi
    sudo chmod +x /etc/grub.d/99_snowtv_trixie_lvm

    # grub-reboot benötigt GRUB_DEFAULT=saved
    if grep -q '^GRUB_DEFAULT=' /etc/default/grub; then
        sudo sed -i 's/^GRUB_DEFAULT=.*/GRUB_DEFAULT=saved/' /etc/default/grub
    else
        echo 'GRUB_DEFAULT=saved' | sudo tee -a /etc/default/grub > /dev/null
    fi

    # Bind-Mounts lösen + Unmount
    sudo umount "$TARGET/dev/pts" "$TARGET/dev" "$TARGET/proc" "$TARGET/sys" 2>/dev/null || true
    [ "$BOOT_MODE" = "uefi" ] && sudo umount "$TARGET/boot/efi" 2>/dev/null || true
    sudo umount "$TARGET" 2>/dev/null || true

    sudo update-grub >> "$LOG" 2>&1 \
        || _err "update-grub fehlgeschlagen – GRUB-Eintrag nicht registriert."
    sudo grub-reboot "SnowTV Trixie LVM" >> "$LOG" 2>&1 \
        || _err "grub-reboot fehlgeschlagen – Eintrag 'SnowTV Trixie LVM' nicht gefunden?"

    _sep
    _log "LVM-Installation abgeschlossen. Neustart in 5s..."
    _log "Player bootet Debian 13 von $LVM_DEV."
    _log "Nach ~30 Min erreichbar via: ssh -p 10${MCID} snowtv@139.162.165.199"
    sleep 5
    sudo reboot
    _err "reboot fehlgeschlagen."
}

# Cleanup-Trap für normalen Pfad (hängende Bind-Mounts bei _err vermeiden)
_cleanup() {
    sudo umount "$TARGET/dev/pts" "$TARGET/dev" "$TARGET/proc" \
                "$TARGET/sys" "$TARGET/boot/efi" "$TARGET" 2>/dev/null || true
}
trap _cleanup EXIT

# Ziel-Partition = laufender Root? → LVM-Pfad (wenn >= 20GB frei) oder tmpfs-Pfad
# %D = st_dev von /  →  (major<<8)|minor in hex, z.B. "802" für sda2
# Block-Device $PART2: major * 256 + minor in gleicher Kodierung
ROOT_DEV=$(stat -c '%D' /)
read -r PART2_MAJ PART2_MIN < <(stat -c '%t %T' "$PART2")
PART2_DEV=$(printf '%x' $(( 0x${PART2_MAJ} * 256 + 0x${PART2_MIN} )))
if [ "$ROOT_DEV" = "$PART2_DEV" ]; then
    _FREE_DISK_MiB=$(sudo parted -s "$DISK" unit MiB print 2>/dev/null \
        | awk 'BEGIN{sz=0;e=0} /^Disk \/dev/{gsub(/[^0-9.]/,"",$3);sz=$3+0} \
               /^ [0-9]/{gsub(/[^0-9.]/,"",$3);e=$3+0} END{printf "%d\n", sz-e}')
    _log "Freier Speicher auf $DISK: ${_FREE_DISK_MiB}MiB"
    if [ "${_FREE_DISK_MiB:-0}" -ge 20480 ]; then
        _deploy_via_lvm   # gibt nicht zurück
    else
        _deploy_via_tmpfs  # gibt nicht zurück
    fi
fi

# ----------------------------------------------------------------
# 8. Disk partitionieren + formatieren  ← POINT OF NO RETURN
# ----------------------------------------------------------------
_sep
_log "Prüfe bestehende Partitionierung von $DISK..."

EXISTING_LABEL=$(sudo parted -s "$DISK" print 2>/dev/null \
    | awk '/Partition Table:/{print $3}')
EXISTING_PARTS=$(sudo parted -s "$DISK" print 2>/dev/null \
    | grep -c '^ [0-9]' || true)

NEED_PARTITION=1
if [ "$BOOT_MODE" = "uefi" ] && [ "$EXISTING_LABEL" = "gpt" ] \
   && [ "$EXISTING_PARTS" -ge 2 ]; then
    _log "Bestehende GPT-Partitionierung erkannt ($EXISTING_PARTS Partitionen) – überspringe mklabel/mkpart."
    NEED_PARTITION=0
elif [ "$BOOT_MODE" = "bios" ] && [ "$EXISTING_LABEL" = "msdos" ] \
   && [ "$EXISTING_PARTS" -ge 1 ]; then
    _log "Bestehende MBR-Partitionierung erkannt – überspringe mklabel/mkpart."
    PART2="$PART1"
    NEED_PARTITION=0
fi

_log "Formatiere Partitionen... (POINT OF NO RETURN)"

if [ "$NEED_PARTITION" -eq 1 ]; then
    _log "Neue Partitionstabelle anlegen..."
    if [ "$BOOT_MODE" = "uefi" ]; then
        sudo parted -s "$DISK" mklabel gpt \
            mkpart ESP  fat32  1MiB  513MiB \
            set 1 esp on \
            mkpart root ext4   513MiB 100% \
            >> "$LOG" 2>&1 || _err "Partitionierung fehlgeschlagen."
        sudo mkfs.fat -F32 "$PART1" >> "$LOG" 2>&1 || _err "mkfs.fat fehlgeschlagen."
    else
        sudo parted -s "$DISK" mklabel msdos \
            mkpart primary ext4 1MiB 100% \
            set 1 boot on \
            >> "$LOG" 2>&1 || _err "Partitionierung fehlgeschlagen."
        PART2="$PART1"
    fi
else
    # EFI-Partition nur neu formatieren wenn UEFI und nicht bereits vfat
    if [ "$BOOT_MODE" = "uefi" ]; then
        PART1_FS=$(sudo blkid -o value -s TYPE "$PART1" 2>/dev/null || true)
        if [ "$PART1_FS" != "vfat" ]; then
            sudo mkfs.fat -F32 "$PART1" >> "$LOG" 2>&1 || _err "mkfs.fat fehlgeschlagen."
        else
            _log "EFI-Partition ($PART1) ist bereits vfat – wird nicht neu formatiert."
        fi
    fi
fi

# Root-Partition neu formatieren (-F -F erzwingt auch bei gemounteter Partition)
sudo mkfs.ext4 -F -F "$PART2" >> "$LOG" 2>&1 || _err "mkfs.ext4 fehlgeschlagen."
_log "Formatierung abgeschlossen."

# ----------------------------------------------------------------
# 9. Mounten
# ----------------------------------------------------------------
sudo mount "$PART2" "$TARGET" >> "$LOG" 2>&1 || _err "Mount $PART2 → $TARGET fehlgeschlagen."
if [ "$BOOT_MODE" = "uefi" ]; then
    sudo mkdir -p "$TARGET/boot/efi"
    sudo mount "$PART1" "$TARGET/boot/efi" >> "$LOG" 2>&1 || _err "Mount EFI fehlgeschlagen."
fi
_log "Disk gemountet unter $TARGET."

# ----------------------------------------------------------------
# 10. debootstrap – mit Retry bei Netzfehler
# ----------------------------------------------------------------
_sep
_log "Starte debootstrap Debian 13 ($SUITE)..."
_log "Bei Netzabbruch: Skript erneut starten – Disk wird neu formatiert, altes System läuft noch."

DBS_OK=0
ATTEMPT=0
while [ $DBS_OK -eq 0 ]; do
    ATTEMPT=$(( ATTEMPT + 1 ))
    _log "debootstrap Versuch $ATTEMPT..."

    # Zielverzeichnis leeren (bei Retry)
    if [ $ATTEMPT -gt 1 ]; then
        sudo find "$TARGET" -mindepth 1 -maxdepth 1 -exec rm -rf {} + 2>/dev/null
    fi

    sudo debootstrap \
        --arch=amd64 \
        --include="$DBS_PACKAGES" \
        "$DBS_SUITE" "$TARGET" "$MIRROR" \
        >> "$LOG" 2>&1

    if [ $? -eq 0 ]; then
        DBS_OK=1
        _log "debootstrap erfolgreich."
    else
        _warn "debootstrap fehlgeschlagen (Versuch $ATTEMPT)."
        echo ""
        echo "  Mögliche Ursache: Netzabbruch oder Mirror nicht erreichbar."
        echo "  Das laufende System ist noch aktiv – Retry ist möglich."
        echo ""
        read -r -p "  Erneut versuchen? (ja/nein): " RETRY
        if [ "$RETRY" != "ja" ]; then
            _err "Abgebrochen nach $ATTEMPT Versuchen. Disk ist leer formatiert.\nNeu starten mit: bash /home/snowtv/bin/remote_reinstall_debootstrap.sh"
        fi
        _log "Warte 15s..."
        sleep 15
    fi
done

# ----------------------------------------------------------------
# 11. chroot vorbereiten
# ----------------------------------------------------------------
_log "Bereite chroot vor..."
sudo mount --bind /dev     "$TARGET/dev"
sudo mount --bind /dev/pts "$TARGET/dev/pts"
sudo mount --bind /proc    "$TARGET/proc"
sudo mount --bind /sys     "$TARGET/sys"

# ----------------------------------------------------------------
# 12. chroot: apt sources + Basis-Konfiguration
# ----------------------------------------------------------------
_log "Konfiguriere neues System im chroot..."

# apt sources.list
sudo tee "$TARGET/etc/apt/sources.list" > /dev/null << EOF
deb http://deb.debian.org/debian trixie main contrib non-free non-free-firmware
deb http://security.debian.org/debian-security trixie-security main contrib non-free non-free-firmware
EOF

# Hostname + /etc/hosts
hostname | sudo tee "$TARGET/etc/hostname" > /dev/null
printf "127.0.0.1\tlocalhost\n127.0.1.1\t%s\n" "$(hostname)" | sudo tee "$TARGET/etc/hosts" > /dev/null

# Locale + Timezone
echo "Europe/Zurich" | sudo tee "$TARGET/etc/timezone" > /dev/null
sudo ln -sf /usr/share/zoneinfo/Europe/Zurich "$TARGET/etc/localtime"
echo "de_CH.UTF-8 UTF-8" | sudo tee -a "$TARGET/etc/locale.gen" > /dev/null

# fstab
ROOT_UUID=$(sudo blkid -s UUID -o value "$PART2")
sudo tee "$TARGET/etc/fstab" > /dev/null << EOF
UUID=$ROOT_UUID  /          ext4  errors=remount-ro  0  1
EOF
if [ "$BOOT_MODE" = "uefi" ]; then
    EFI_UUID=$(sudo blkid -s UUID -o value "$PART1")
    echo "UUID=$EFI_UUID  /boot/efi  vfat  umask=0077  0  2" | sudo tee -a "$TARGET/etc/fstab" > /dev/null
fi

# Netzwerk: systemd-networkd mit Type=ether – funktioniert mit Predictable Interface Names
sudo mkdir -p "$TARGET/etc/systemd/network"
sudo tee "$TARGET/etc/systemd/network/10-eth-dhcp.network" > /dev/null << 'NETEOF'
[Match]
Type=ether

[Network]
DHCP=yes
NETEOF

# ----------------------------------------------------------------
# 13. chroot: Kernel + GRUB installieren
# ----------------------------------------------------------------
_log "Installiere Kernel + GRUB im chroot..."

if [ "$BOOT_MODE" = "uefi" ]; then
    GRUB_PKG="grub-efi-amd64"
else
    GRUB_PKG="grub-pc"
fi

sudo chroot "$TARGET" /bin/bash -c "
    export DEBIAN_FRONTEND=noninteractive
    locale-gen
    update-locale LANG=de_CH.UTF-8
    apt-get update -q
    apt-get install -y linux-image-amd64 $GRUB_PKG
" >> "$LOG" 2>&1 || _err "Kernel/GRUB Installation fehlgeschlagen."

# systemd-networkd explizit via Symlinks aktivieren (systemctl enable im Chroot ist unzuverlässig)
sudo mkdir -p "$TARGET/etc/systemd/system/multi-user.target.wants"
sudo mkdir -p "$TARGET/etc/systemd/system/network-online.target.wants"
for SVC in systemd-networkd.service systemd-resolved.service; do
    sudo ln -sf "/lib/systemd/system/${SVC}" \
        "$TARGET/etc/systemd/system/multi-user.target.wants/${SVC}"
done
sudo ln -sf /lib/systemd/system/systemd-networkd-wait-online.service \
    "$TARGET/etc/systemd/system/network-online.target.wants/systemd-networkd-wait-online.service"

# GRUB installieren
if [ "$BOOT_MODE" = "uefi" ]; then
    sudo chroot "$TARGET" grub-install \
        --target=x86_64-efi \
        --efi-directory=/boot/efi \
        --bootloader-id=debian \
        --removable \
        >> "$LOG" 2>&1 || _err "grub-install (UEFI) fehlgeschlagen."
else
    sudo chroot "$TARGET" grub-install "$DISK" >> "$LOG" 2>&1 \
        || _err "grub-install (BIOS) fehlgeschlagen."
fi
sudo chroot "$TARGET" update-grub >> "$LOG" 2>&1 \
    || _err "update-grub fehlgeschlagen – System würde unbootbar sein."
_log "Kernel + GRUB installiert."

# ----------------------------------------------------------------
# 14. chroot: User snowtv + sudo
# ----------------------------------------------------------------
_log "Lege User snowtv an..."
sudo chroot "$TARGET" /bin/bash -c "
    useradd -m -s /bin/bash snowtv
    echo 'snowtv:snowtv123' | chpasswd
    adduser snowtv sudo 2>/dev/null || true
" >> "$LOG" 2>&1
# Temporäres NOPASSWD: ALL (swinstall.sh schränkt es am Ende ein)
echo 'snowtv ALL=(ALL) NOPASSWD: ALL' | \
    sudo tee "$TARGET/etc/sudoers.d/snowtv-install" > /dev/null
sudo chmod 440 "$TARGET/etc/sudoers.d/snowtv-install"

# ----------------------------------------------------------------
# 15. chroot: mcid.cfg + mcdomain.cfg
# ----------------------------------------------------------------
_log "Schreibe mcid.cfg + mcdomain.cfg..."
sudo mkdir -p "$TARGET/home/snowtv/bin"
echo "ID=$MCID"         | sudo tee "$TARGET/home/snowtv/bin/mcid.cfg"    > /dev/null
echo "DOMAIN=$MCDOMAIN" | sudo tee "$TARGET/home/snowtv/bin/mcdomain.cfg" > /dev/null
sudo chown -R 1000:1000 "$TARGET/home/snowtv/bin"

# ----------------------------------------------------------------
# 16. chroot: firstboot-Mechanismus (identisch zu Preseed)
# ----------------------------------------------------------------
_log "Lege firstboot-Service an..."
sudo touch "$TARGET/var/lib/snowtv-install-pending"

sudo tee "$TARGET/home/snowtv/firstboot.sh" > /dev/null << 'FBEOF'
#!/bin/bash
LOG="/home/snowtv/stv-install.log"
echo "$(date)  INFO: SnowTV First Boot gestartet" | tee -a "$LOG"
cd /home/snowtv
for i in 1 2 3 4 5; do
    wget -q --no-check-certificate https://172.105.95.252/swinstall.sh -O swinstall.sh && break
    sleep 10
done
[ -s swinstall.sh ] || { echo "$(date) ERROR: swinstall.sh Download fehlgeschlagen oder leer" | tee -a "$LOG"; rm -f swinstall.sh; exit 1; }
chmod +x swinstall.sh
sudo rm -f /var/lib/snowtv-install-pending
bash /home/snowtv/swinstall.sh 2>&1 | tee -a "$LOG"
FBEOF

sudo chown 1000:1000 "$TARGET/home/snowtv/firstboot.sh"
sudo chmod 755 "$TARGET/home/snowtv/firstboot.sh"

sudo tee "$TARGET/etc/systemd/system/snowtv-install.service" > /dev/null << 'SVCEOF'
[Unit]
Description=SnowTV Player Erstinstallation
After=network-online.target
Wants=network-online.target
ConditionPathExists=/var/lib/snowtv-install-pending

[Service]
Type=oneshot
User=snowtv
Environment=HOME=/home/snowtv
WorkingDirectory=/home/snowtv
ExecStart=/bin/bash /home/snowtv/firstboot.sh
StandardOutput=journal+console
StandardError=journal+console
TimeoutStartSec=1800

[Install]
WantedBy=multi-user.target
SVCEOF

sudo mkdir -p "$TARGET/etc/systemd/system/multi-user.target.wants"
sudo ln -sf /etc/systemd/system/snowtv-install.service \
    "$TARGET/etc/systemd/system/multi-user.target.wants/snowtv-install.service"
# NetworkManager wird nicht installiert – kein NM-Symlink nötig.

# ----------------------------------------------------------------
# 17. Aufräumen + Unmount
# ----------------------------------------------------------------
_log "Unmounte chroot..."
sudo umount "$TARGET/dev/pts" 2>/dev/null
sudo umount "$TARGET/dev"     2>/dev/null
sudo umount "$TARGET/proc"    2>/dev/null
sudo umount "$TARGET/sys"     2>/dev/null
[ "$BOOT_MODE" = "uefi" ] && sudo umount "$TARGET/boot/efi" 2>/dev/null
sudo umount "$TARGET"         2>/dev/null

# ----------------------------------------------------------------
# 18. Reboot
# ----------------------------------------------------------------
_sep
_log "Installation abgeschlossen."
_log "Player bootet in Debian 13. swinstall.sh läuft automatisch."
_log "Nach ~30 Min erreichbar via: ssh -p 10${MCID} snowtv@139.162.165.199"
echo ""
echo "  Rechner startet in 5 Sekunden neu..."
sleep 5
sudo reboot
