#!/bin/bash
set -euo pipefail
export LC_ALL=C.UTF-8

ADAT=/usr/lib/raveos-center/adat
AKCIOK="$ADAT/actions"
KONFIGOK="$ADAT/configs"
MENTESI_LISTA="$ADAT/mentes/backup-paths.json"

if [ "$(id -u)" -ne 0 ]; then
    echo "a helper csak rootként futhat" >&2
    exit 2
fi
cd /

csomagnevek() {
    [ "$#" -ge 1 ] || { echo "nincs megadva csomag" >&2; exit 2; }
    local p
    for p in "$@"; do
        [[ "$p" =~ ^[a-z0-9@_+][a-z0-9@._+-]*$ ]] || { echo "érvénytelen csomagnév: $p" >&2; exit 2; }
    done
}

hivo_felhasznalo() {
    [[ "${PKEXEC_UID:-}" =~ ^[0-9]+$ ]] || { echo "ismeretlen hívó felhasználó" >&2; exit 2; }
    [ "$PKEXEC_UID" -ge 1000 ] || { echo "a művelet csak normál felhasználónak engedélyezett" >&2; exit 2; }
    IFS=: read -r FELH _ _ _ _ OTTHON _ < <(getent passwd "$PKEXEC_UID")
    [ -n "${FELH:-}" ] && [ -d "${OTTHON:-}" ] || { echo "a hívó felhasználó nem található" >&2; exit 2; }
}

rendszer_mentesi_ut() {
    python3 -I - "$MENTESI_LISTA" "$1" <<'PY'
import json, sys
lista, azon = sys.argv[1], sys.argv[2]
for csoport in json.load(open(lista))["groups"]:
    for elem in csoport["items"]:
        if elem["id"] == azon and elem.get("scope") == "system" and elem["path"].startswith("/"):
            print(elem["path"])
            sys.exit(0)
sys.exit(1)
PY
}

case "${1:-}" in
    frissites)
        [ "$#" -eq 1 ] || exit 2
        exec pacman -Syu --noconfirm --color never
        ;;
    snapshot)
        [ "$#" -eq 2 ] || exit 2
        leiras="$2"
        if ! [[ "$leiras" =~ ^[[:alnum:][:space:]._:,()-]{1,80}$ ]]; then
            echo "érvénytelen snapshot leírás" >&2
            exit 2
        fi
        command -v snapper >/dev/null || { echo "a snapper nincs telepítve" >&2; exit 3; }
        exec snapper -c root create --type single --cleanup-algorithm number --print-number --description "$leiras"
        ;;
    telepit)
        shift
        csomagnevek "$@"
        exec pacman -S --needed --noconfirm --color never "$@"
        ;;
    eltavolit)
        shift
        csomagnevek "$@"
        exec pacman -Rns --noconfirm --color never "$@"
        ;;
    szolgaltatas)
        [ "$#" -eq 2 ] || exit 2
        [[ "$2" =~ ^[a-z0-9][a-z0-9@_.-]*$ ]] || { echo "érvénytelen szolgáltatásnév" >&2; exit 2; }
        exec systemctl enable "$2"
        ;;
    akcio)
        [ "$#" -eq 3 ] || exit 2
        nev="$2"
        mod="$3"
        [[ "$nev" =~ ^[a-z0-9][a-z0-9-]*\.sh$ ]] || { echo "érvénytelen akció" >&2; exit 2; }
        [[ "$mod" == "install" || "$mod" == "remove" ]] || { echo "érvénytelen mód" >&2; exit 2; }
        [ -f "$AKCIOK/$nev" ] || { echo "nincs ilyen akció" >&2; exit 2; }
        hivo_felhasznalo
        exec env INSTALL_USER="$FELH" INSTALL_HOME="$OTTHON" TARGET_UID="$PKEXEC_UID" \
            TARGET_XDG_RUNTIME_DIR="/run/user/$PKEXEC_UID" RAVEOS_CONFIG_PACKAGE_DIR="$KONFIGOK" \
            bash "$AKCIOK/$nev" "$mod"
        ;;
    ntsync)
        [ "$#" -eq 2 ] || exit 2
        case "$2" in
            be)
                modprobe ntsync || exit 1
                echo ntsync > /etc/modules-load.d/ntsync.conf
                exit 0
                ;;
            ki)
                rm -f /etc/modules-load.d/ntsync.conf
                modprobe -r ntsync 2>/dev/null || echo "a modul a következő újraindításkor kerül ki"
                exit 0
                ;;
            *) echo "érvénytelen NTSync művelet" >&2; exit 2 ;;
        esac
        ;;
    utemezo)
        [ "$#" -eq 2 ] || exit 2
        case "$2" in
            be)
                [ -d /sys/kernel/sched_ext ] || { echo "a futó kernel nem támogatja a sched_ext ütemezőket" >&2; exit 3; }
                pacman -S --needed --noconfirm --color never scx-scheds scx-tools
                konfig='default_sched = "scx_lavd"\ndefault_mode = "Gaming"\n'
                if [ -f /etc/scx_loader.toml ] && [ "$(cat /etc/scx_loader.toml)" != "$(printf "$konfig")" ]; then
                    cp -f /etc/scx_loader.toml /etc/scx_loader.toml.raveos-mentes
                fi
                printf "$konfig" > /etc/scx_loader.toml
                systemctl enable scx_loader.service
                systemctl restart scx_loader.service
                for _ in 1 2 3 4 5 6 7 8 9 10; do
                    if [ "$(cat /sys/kernel/sched_ext/state 2>/dev/null)" = enabled ]; then
                        echo "fut: $(cat /sys/kernel/sched_ext/root/ops 2>/dev/null)"
                        exit 0
                    fi
                    sleep 1
                done
                echo "az ütemező nem indult el, részletek: journalctl -u scx_loader" >&2
                exit 1
                ;;
            ki)
                if command -v scxctl >/dev/null; then scxctl stop 2>/dev/null || true; fi
                systemctl disable --now scx_loader.service 2>/dev/null || true
                if [ -f /etc/scx_loader.toml.raveos-mentes ]; then
                    mv -f /etc/scx_loader.toml.raveos-mentes /etc/scx_loader.toml
                else
                    rm -f /etc/scx_loader.toml
                fi
                exit 0
                ;;
            *) echo "érvénytelen ütemező művelet" >&2; exit 2 ;;
        esac
        ;;
    arva)
        shift
        csomagnevek "$@"
        mapfile -t arvak < <(pacman -Qdtq || true)
        for p in "$@"; do
            printf '%s\n' "${arvak[@]}" | grep -qxF -- "$p" || { echo "nem árva csomag: $p" >&2; exit 2; }
        done
        exec pacman -Rn --noconfirm --color never "$@"
        ;;
    snapshot-torles)
        [ "$#" -eq 2 ] || exit 2
        [[ "$2" =~ ^[1-9][0-9]{0,5}$ ]] || { echo "érvénytelen snapshot szám" >&2; exit 2; }
        exec snapper -c root delete "$2"
        ;;
    snapshot-visszaallit)
        [ "$#" -eq 2 ] || exit 2
        szam="$2"
        [[ "$szam" =~ ^[1-9][0-9]{0,5}$ ]] || { echo "érvénytelen snapshot szám" >&2; exit 2; }
        [ "$(findmnt -no FSTYPE /)" = btrfs ] || { echo "a gyökér nem btrfs" >&2; exit 3; }
        findmnt -no OPTIONS / | tr ',' '\n' | grep -qx 'subvol=/@' || {
            echo "a rendszer nem a @ alvolumenről fut, innen nem állítható vissza" >&2; exit 3; }
        forras="/.snapshots/$szam/snapshot"
        btrfs subvolume show "$forras" >/dev/null 2>&1 || { echo "nincs ilyen snapshot: $szam" >&2; exit 2; }
        kernelek=()
        for pb in "$forras"/usr/lib/modules/*/pkgbase; do
            [ -f "$pb" ] || continue
            nev=$(<"$pb")
            [[ "$nev" =~ ^[a-z0-9][a-z0-9._+-]*$ ]] || continue
            regi=$(pacman --dbpath "$forras/var/lib/pacman" -Q "$nev" 2>/dev/null | awk '{print $2}')
            most=$(pacman -Q "$nev" 2>/dev/null | awk '{print $2}')
            [ -n "$regi" ] && [ "$regi" != "$most" ] || continue
            csomag=$(find /var/cache/pacman/pkg -maxdepth 1 -name "$nev-$regi-*.pkg.tar.*" ! -name '*.sig' | head -1)
            [ -n "$csomag" ] || {
                echo "a snapshot kernelcsomagja ($nev $regi) nincs a csomag-cache-ben, a visszaállított rendszer nem indulna el" >&2
                exit 4
            }
            kernelek+=("$csomag")
        done
        eszkoz=$(findmnt -no SOURCE / | sed 's/\[.*\]//')
        felso=$(mktemp -d /run/raveos-visszaallitas.XXXXXX)
        mentes="$felso.boot"
        mount -o subvolid=5 "$eszkoz" "$felso"
        uj="$felso/@uj"
        chroot_le() {
            local m
            for m in dev sys proc var/cache/pacman/pkg boot; do
                if mountpoint -q "$uj/$m"; then umount -R "$uj/$m" 2>/dev/null || umount -l "$uj/$m" 2>/dev/null || true; fi
            done
        }
        takaritas() {
            chroot_le
            if [ -d "$uj" ]; then btrfs subvolume delete "$uj" >/dev/null 2>&1 || true; fi
            umount "$felso" 2>/dev/null || true
            rmdir "$felso" 2>/dev/null || true
        }
        bukas() {
            echo "a visszaállítás megszakadt, a jelenlegi rendszer érintetlen" >&2
            if [ -d "$mentes" ]; then cp -a "$mentes/." /boot/ 2>/dev/null || true; fi
            takaritas
            rm -rf "$mentes"
            exit 1
        }
        trap bukas ERR
        [ -d "$felso/@" ] || { echo "nem található a @ alvolumen" >&2; false; }
        btrfs subvolume delete "$uj" >/dev/null 2>&1 || true
        btrfs subvolume snapshot "$forras" "$uj"
        sb=0
        if [ -f /etc/raveos/secureboot/machine.key ] && [ -x /usr/local/bin/raveos-sb-sign-local.sh ]; then
            sb=1
            install -d -m 700 "$uj/etc/raveos/secureboot"
            cp -a /etc/raveos/secureboot/. "$uj/etc/raveos/secureboot/"
            install -Dm755 /usr/local/bin/raveos-sb-sign-local.sh "$uj/usr/local/bin/raveos-sb-sign-local.sh"
            if [ -x /usr/local/bin/raveos-sign-file ]; then install -Dm755 /usr/local/bin/raveos-sign-file "$uj/usr/local/bin/raveos-sign-file"; fi
            if [ -f /etc/pacman.d/hooks/zz-raveos-sb-sign.hook ]; then
                install -Dm644 /etc/pacman.d/hooks/zz-raveos-sb-sign.hook "$uj/etc/pacman.d/hooks/zz-raveos-sb-sign.hook"
            fi
        fi
        if [ "${#kernelek[@]}" -gt 0 ] || [ "$sb" -eq 1 ]; then
            install -d "$mentes"
            cp -a /boot/vmlinuz-* /boot/initramfs-*.img "$mentes/" 2>/dev/null || true
            mount --bind /boot "$uj/boot"
            mount --bind /var/cache/pacman/pkg "$uj/var/cache/pacman/pkg"
            mount -t proc proc "$uj/proc"
            mount --rbind /sys "$uj/sys"
            mount --make-rslave "$uj/sys"
            mount --rbind /dev "$uj/dev"
            mount --make-rslave "$uj/dev"
            if [ "${#kernelek[@]}" -gt 0 ]; then
                echo "kernel visszaállítása: ${kernelek[*]##*/}"
                SNAP_PAC_SKIP=y chroot "$uj" pacman -U --noconfirm --color never "${kernelek[@]}"
                chroot "$uj" gpgconf --homedir /etc/pacman.d/gnupg --kill all 2>/dev/null || true
            fi
            if [ "$sb" -eq 1 ]; then
                chroot "$uj" /usr/local/bin/raveos-sb-sign-local.sh
            fi
            chroot_le
        fi
        trap - ERR
        for regi in "$felso"/@regi-*; do
            [ -d "$regi" ] || continue
            btrfs subvolume delete -R "$regi" >/dev/null 2>&1 || btrfs subvolume delete "$regi" >/dev/null 2>&1 || true
        done
        tartalek="$felso/@regi-$(date +%Y%m%d-%H%M%S)"
        mv "$felso/@" "$tartalek"
        if ! mv "$uj" "$felso/@"; then
            mv "$tartalek" "$felso/@"
            echo "az alvolumenek cseréje nem sikerült, a jelenlegi rendszer maradt" >&2
            takaritas
            exit 1
        fi
        umount "$felso" 2>/dev/null || umount -l "$felso" 2>/dev/null || true
        rmdir "$felso" 2>/dev/null || true
        rm -rf "$mentes"
        echo "a $szam. snapshot visszaállítva, újraindítás után lép életbe"
        exit 0
        ;;
    snapper-beallitas)
        [ "$#" -eq 1 ] || exit 2
        [ "$(findmnt -no FSTYPE /)" = btrfs ] || { echo "a gyökér nem btrfs" >&2; exit 3; }
        findmnt -no SOURCE /.snapshots >/dev/null 2>&1 || { echo "a /.snapshots nincs csatolva (@snapshots alvolumen)" >&2; exit 3; }
        [ ! -f /etc/snapper/configs/root ] || { echo "a snapper már be van állítva"; exit 0; }
        pacman -S --needed --noconfirm --color never snapper snap-pac
        install -d -m 755 /etc/snapper/configs
        sed -e 's/^SUBVOLUME=.*/SUBVOLUME="\/"/' \
            -e 's/^FSTYPE=.*/FSTYPE="btrfs"/' \
            -e 's/^ALLOW_GROUPS=.*/ALLOW_GROUPS="wheel"/' \
            -e 's/^SYNC_ACL=.*/SYNC_ACL="yes"/' \
            -e 's/^NUMBER_CLEANUP=.*/NUMBER_CLEANUP="yes"/' \
            -e 's/^NUMBER_LIMIT=.*/NUMBER_LIMIT="10"/' \
            -e 's/^NUMBER_LIMIT_IMPORTANT=.*/NUMBER_LIMIT_IMPORTANT="5"/' \
            -e 's/^TIMELINE_CREATE=.*/TIMELINE_CREATE="no"/' \
            -e 's/^TIMELINE_CLEANUP=.*/TIMELINE_CLEANUP="yes"/' \
            -e 's/^EMPTY_PRE_POST_CLEANUP=.*/EMPTY_PRE_POST_CLEANUP="yes"/' \
            /usr/share/snapper/config-templates/default > /etc/snapper/configs/root
        chmod 640 /etc/snapper/configs/root
        if [ -f /etc/conf.d/snapper ]; then
            sed -i 's/^SNAPPER_CONFIGS=.*/SNAPPER_CONFIGS="root"/' /etc/conf.d/snapper
        else
            install -d /etc/conf.d
            echo 'SNAPPER_CONFIGS="root"' > /etc/conf.d/snapper
        fi
        chmod 750 /.snapshots
        chown root:wheel /.snapshots
        systemctl restart snapperd.service 2>/dev/null || true
        systemctl enable --now snapper-cleanup.timer
        systemctl disable --now snapper-timeline.timer 2>/dev/null || true
        exec snapper -c root create --type single --cleanup-algorithm number --userdata important=yes \
            --description "Snapper beállítva (RaveOS Center)"
        ;;
    karbantartas)
        [ "$#" -eq 2 ] || exit 2
        case "$2" in
            cache)
                paccache -rk2
                exec paccache -ruk0
                ;;
            naplo)
                exec journalctl --vacuum-time=2weeks --vacuum-size=100M
                ;;
            tukrok)
                command -v reflector >/dev/null || pacman -S --needed --noconfirm --color never reflector
                uj=$(mktemp /etc/pacman.d/mirrorlist.XXXXXX)
                trap 'rm -f "$uj"' EXIT
                reflector -c HU,AT,DE,PL,CZ --protocol https --sort rate --latest 20 \
                    --download-timeout 10 --threads 5 --save "$uj"
                db=$(grep -c '^Server' "$uj" || true)
                [ "$db" -ge 3 ] || { echo "túl kevés működő tükör ($db), a régi lista marad" >&2; exit 1; }
                if [ -f /etc/pacman.d/mirrorlist ]; then cp -f /etc/pacman.d/mirrorlist /etc/pacman.d/mirrorlist.bak; fi
                chmod 644 "$uj"
                mv -f "$uj" /etc/pacman.d/mirrorlist
                trap - EXIT
                echo "$db tükör mentve, a régi lista: /etc/pacman.d/mirrorlist.bak"
                exit 0
                ;;
            kulcsok)
                pacman-key --init
                pacman-key --populate
                mapfile -t kulcsok < <(pacman -Qqo /usr/share/pacman/keyrings/*.gpg 2>/dev/null | sort -u)
                if [ "${#kulcsok[@]}" -gt 0 ]; then
                    pacman -S --needed --noconfirm --color never "${kulcsok[@]}" || echo "a kulcscsomagok frissítése most nem sikerült, a helyi kulcsok újratöltve"
                fi
                exec pacman-key --populate
                ;;
            flatpak)
                exec flatpak uninstall --system --unused -y --noninteractive
                ;;
            *) echo "érvénytelen karbantartási művelet" >&2; exit 2 ;;
        esac
        ;;
    driverek)
        [ "$#" -eq 1 ] || exit 2
        exec bash /usr/lib/raveos-center/raveos-gpu-drivers --rendszeren
        ;;
    secureboot)
        [ "$#" -eq 2 ] || exit 2
        case "$2" in
            setup|resign|verify) exec raveos-secureboot-setup "--$2" ;;
            *) echo "érvénytelen Secure Boot művelet" >&2; exit 2 ;;
        esac
        ;;
    mentes-root)
        [ "$#" -eq 2 ] || exit 2
        ut="$(rendszer_mentesi_ut "$2")" || { echo "ismeretlen rendszer-mentési elem" >&2; exit 2; }
        [ -e "$ut" ] || { echo "nem létezik: $ut" >&2; exit 3; }
        exec tar -cf - -C "$(dirname "$ut")" "$(basename "$ut")"
        ;;
    visszaallit-root)
        [ "$#" -eq 2 ] || exit 2
        ut="$(rendszer_mentesi_ut "$2")" || { echo "ismeretlen rendszer-mentési elem" >&2; exit 2; }
        install -d "$(dirname "$ut")"
        exec python3 -I -c '
import io, sys, tarfile
from pathlib import Path
ut = Path(sys.argv[1])
nev = ut.name
with tarfile.open(fileobj=io.BytesIO(sys.stdin.buffer.read()), mode="r:") as tar:
    tagok = tar.getmembers()
    for tag in tagok:
        tiszta = tag.name.removeprefix("./")
        if tiszta != nev and not tiszta.startswith(nev + "/"):
            sys.exit(f"érvénytelen archívumtag: {tag.name}")
    tar.extractall(path=ut.parent, members=tagok, filter="data")
print(f"visszaállítva: {len(tagok)} elem")
' "$ut"
        ;;
    *)
        echo "ismeretlen művelet" >&2
        exit 2
        ;;
esac
