#!/bin/bash
# alfred-install-hook -- Alfred Linux Calamares helper (v7 installer layer)
# Called by the shellprocess@alfred_* jobs in /etc/calamares/settings.conf (dontChroot: true).
#   src            mount a read-only overlay of ALL live squashfs layers at /run/alfred-installsrc
#                  (unpackfs copies from there, so v1/v2/v3/v6/v7 fixes + whiteouts reach the target)
#   prep  ROOT     post-unpack cleanup of live-only state in the target
#   home  ROOT USER  give the new user the live desktop dotfiles (minus secrets) + provision
#                    per-user Kyber-1024 (ML-KEM-1024) keypair & quantum-sealed Solana/GSM wallet
#   models ROOT    copy optional AI models from the live medium
#   final ROOT     verify kernel/initrd/grub, provision /etc/alfred/quantum-fde Kyber-1024 layer,
#                  lock image root password, cleanup
set -u
SRC=/run/alfred-installsrc
log() { echo "[alfred-install-hook] $*"; }

resolve_root() {
    local r="${1:-}"
    if [ -z "$r" ] || [ ! -d "$r/etc" ]; then
        r=$(findmnt -rno TARGET | grep -m1 '^/tmp/calamares-root-' || true)
    fi
    [ -n "$r" ] && [ -d "$r/etc" ] || { log "cannot find target root (got '${1:-}')"; exit 1; }
    echo "$r"
}

src() {
    if mountpoint -q "$SRC"; then umount -l "$SRC"; fi
    mkdir -p "$SRC"
    local lower="" rootopts
    lower=$(ls -d /run/live/rootfs/*/ 2>/dev/null | sed 's#/$##' | LC_ALL=C sort -r | paste -sd:)
    rootopts=$(findmnt -no OPTIONS / | tr ',' '\n' | sed -n 's/^lowerdir=//p' | head -1)
    if [ -z "$lower" ]; then
        lower="$rootopts"
        [ -n "$lower" ] || lower=$(findmnt -no OPTIONS / | tr ',' '\n' | sed -n 's/^lowerdir+=//p' | paste -sd:)
    fi
    log "root overlay lowerdir: ${rootopts:-?}"
    [ -n "$lower" ] || { log "no live layers found"; exit 1; }
    log "layers (top first): $lower"
    mount -t overlay alfred-installsrc -o ro,lowerdir="$lower" "$SRC" || { log "overlay mount failed"; exit 1; }
    [ -e "$SRC/usr/bin/bash" ] || { log "source overlay looks empty"; exit 1; }
    log "source ready at $SRC"
}

prep() {
    local R; R=$(resolve_root "${1:-}")
    if mountpoint -q "$SRC"; then umount -l "$SRC"; rmdir "$SRC" 2>/dev/null; fi

    # 1. merged /usr
    if [ -d "$R/lib" ] && [ ! -L "$R/lib" ]; then
        log "merging /lib into /usr/lib"
        cp -a "$R/lib/." "$R/usr/lib/" && rm -rf "$R/lib" && ln -s usr/lib "$R/lib"
    fi

    # 2. live-only conveniences that must not survive on an installed system
    rm -f "$R/usr/share/applications/alfred-install.desktop" \
          "$R/usr/share/applications/calamares-install-debian.desktop" \
          "$R/etc/xdg/autostart/calamares-desktop-icon.desktop"

    # Enforce sovereign passwordless sudo for the installed system owner
    log "configuring sovereign passwordless sudo"
    mkdir -p "$R/etc/sudoers.d"
    cat > "$R/etc/sudoers.d/010-alfred" << 'EOF'
# Alfred Linux Sovereign Sudo: Zero friction for administrative owners
alfred ALL=(ALL:ALL) NOPASSWD: ALL
%sudo ALL=(ALL:ALL) NOPASSWD: ALL
EOF
    chmod 440 "$R/etc/sudoers.d/010-alfred"

    # 3. per-machine secrets are never cloned (regenerated on install / first boot)
    rm -f "$R"/etc/ssh/ssh_host_*
    rm -rf "$R/etc/alfred/quantum-fde"

    # 4. target initramfs: drop live-only hot-patches
    rm -f "$R/etc/initramfs-tools/scripts/init-bottom/99-ima-apparmor-cleanup" \
          "$R/etc/initramfs-tools/scripts/init-bottom/apparmor-hotfix" \
          "$R/etc/initramfs-tools/scripts/init-bottom/usrmerge-fix"

    # 5. initramfs-tools state
    mkdir -p "$R/var/lib/initramfs-tools"
    local k v
    for k in "$R"/boot/vmlinuz-*; do
        [ -e "$k" ] || continue
        v=${k##*/vmlinuz-}
        if [ -d "$R/usr/lib/modules/$v/kernel" ]; then
            touch "$R/var/lib/initramfs-tools/$v"; log "kernel $v registered for initramfs"
        fi
    done

    # 6. installed kernel cmdline
    mkdir -p "$R/etc/default/grub.d"
    cat > "$R/etc/default/grub.d/zz-alfred-installed.cfg" <<'EOF'
# Written by the Alfred Linux installer: same LSM/IMA policy as the live ISO.
GRUB_CMDLINE_LINUX="$GRUB_CMDLINE_LINUX apparmor=0 ima_appraise=off lsm=landlock,lockdown,yama,bpf"
EOF

    # 7. keep the live desktop dotfiles for the new user, strictly excluding all live keys/wallets;
    #    removeuser deletes /home/alfred right after this job.
    if [ -d "$R/home/alfred" ]; then
        mkdir -p "$R/var/lib/alfred-installer/skel"
        rsync -a --exclude=/.ssh --exclude=/.gnupg --exclude=/.vault --exclude='/.*_history' \
              --exclude=/.cache --exclude=/.config/autostart/alfred-live-welcome.desktop \
              --exclude=/.config/solana --exclude=/.config/alfred-wallet \
              --exclude=/.config/alfred-solana --exclude=/.local/share/alfred-wallet \
              --exclude=/.local/state/alfred-solana --exclude=/.alfred/quantum-keys \
              "$R/home/alfred/" "$R/var/lib/alfred-installer/skel/"
    fi
    log "prep done"
}

home() {
    local R U H S
    R=$(resolve_root "${1:-}"); U="${2:-}"
    if [ -z "$U" ] || ! chroot "$R" getent passwd "$U" >/dev/null; then
        U=$(chroot "$R" getent passwd 1000 | cut -d: -f1)
    fi
    H=$(chroot "$R" getent passwd "$U" | cut -d: -f6)
    S="$R/var/lib/alfred-installer/skel"
    if [ -n "$U" ] && [ -n "$H" ] && [ -d "$S" ]; then
        log "seeding $H for $U"
        mkdir -p "$R$H"
        cp -an "$S/." "$R$H/"
        if [ "$H" != /home/alfred ]; then
            grep -rlI --null /home/alfred "$R$H" 2>/dev/null | xargs -0r sed -i "s#/home/alfred#$H#g"
        fi

        # Ensure explicit passwordless sudo for the newly registered user account
        mkdir -p "$R/etc/sudoers.d"
        cat > "$R/etc/sudoers.d/010-alfred" << EOF
# Alfred Linux Sovereign Sudo: Zero friction for administrative owners
$U ALL=(ALL:ALL) NOPASSWD: ALL
alfred ALL=(ALL:ALL) NOPASSWD: ALL
%sudo ALL=(ALL:ALL) NOPASSWD: ALL
EOF
        chmod 440 "$R/etc/sudoers.d/010-alfred"

        # Provision per-user Post-Quantum Kyber-1024 (ML-KEM-1024) keypair & fresh Solana/GSM wallet
        log "provisioning Kyber-1024 (ML-KEM-1024) keypair and fresh Solana/GSM wallet for $U"
        chroot "$R" /bin/bash -c "
            umask 077
            KEM_ALG='ML-KEM-1024'
            openssl list -kem-algorithms 2>/dev/null | grep -qi 'kyber1024' && KEM_ALG='kyber1024'
            QDIR='$H/.alfred/quantum-keys'
            mkdir -p \"\$QDIR\"
            if openssl genpkey -algorithm \"\$KEM_ALG\" -out \"\$QDIR/kyber1024.key\" 2>/dev/null; then
                openssl pkey -in \"\$QDIR/kyber1024.key\" -pubout -out \"\$QDIR/kyber1024.pub\" 2>/dev/null || true
                chmod 600 \"\$QDIR/kyber1024.key\"
                chmod 644 \"\$QDIR/kyber1024.pub\" 2>/dev/null || true
            fi

            SOLDIR='$H/.config/solana'
            mkdir -p \"\$SOLDIR\"
            export PATH=\"/usr/local/bin:/opt/solana/current/solana-release/bin:/opt/solana/current/bin:\$PATH\"
            if [ ! -f \"\$SOLDIR/id.json\" ] && command -v solana-keygen >/dev/null 2>&1; then
                solana-keygen new --no-bip39-passphrase --silent --outfile \"\$SOLDIR/id.json\" >/dev/null 2>&1 || true
                chmod 600 \"\$SOLDIR/id.json\" 2>/dev/null || true
                PUB=\$(solana-keygen pubkey \"\$SOLDIR/id.json\" 2>/dev/null || true)
                if [ -n \"\$PUB\" ]; then
                    printf '%s\n' \"\$PUB\" > \"\$SOLDIR/id.json.pub\"
                    chmod 644 \"\$SOLDIR/id.json.pub\"
                fi
                # Wrap the new Solana keypair in a Kyber-1024 (ML-KEM-1024) + AES-256-CBC KEM backup
                if [ -f \"\$QDIR/kyber1024.pub\" ] && [ -f \"\$SOLDIR/id.json\" ]; then
                    if openssl pkeyutl -encap -inkey \"\$QDIR/kyber1024.pub\" -pubin \
                        -secret \"\$SOLDIR/.kem-secret.tmp\" -out \"\$SOLDIR/id.kyber1024.kem\" 2>/dev/null; then
                        openssl enc -aes-256-cbc -pbkdf2 -iter 210000 -salt \
                            -pass file:\"\$SOLDIR/.kem-secret.tmp\" \
                            -in \"\$SOLDIR/id.json\" -out \"\$SOLDIR/id.kyber1024.vault\" 2>/dev/null || true
                        rm -f \"\$SOLDIR/.kem-secret.tmp\"
                        chmod 600 \"\$SOLDIR/id.kyber1024.vault\" \"\$SOLDIR/id.kyber1024.kem\" 2>/dev/null || true
                    fi
                fi
            fi
        " || true

        chroot "$R" chown -R "$U:" "$H"
    fi
    rm -rf "$R/var/lib/alfred-installer"
}

models() {
    local R; R=$(resolve_root "${1:-}")
    if [ -d /run/live/medium/live/alfred-models ]; then
        rm -f "$R/opt/alfred-models" 2>/dev/null
        mkdir -p "$R/opt/alfred-models"
        cp -a /run/live/medium/live/alfred-models/. "$R/opt/alfred-models/"
        chown -R root:root "$R/opt/alfred-models"
    else
        log "no model files on the live medium"
    fi
}

final() {
    local R K v; R=$(resolve_root "${1:-}")
    K=$(ls "$R"/boot/vmlinuz-* 2>/dev/null | sort -V | tail -1)
    [ -n "$K" ] || { log "NO KERNEL in target /boot"; exit 1; }
    v=${K##*/vmlinuz-}
    if [ ! -s "$R/boot/initrd.img-$v" ]; then
        log "initrd for $v missing, generating"; chroot "$R" update-initramfs -c -k "$v" || exit 1
    fi
    if ! grep -q "vmlinuz-$v" "$R/boot/grub/grub.cfg" 2>/dev/null; then
        log "grub.cfg lacks $v, regenerating"; chroot "$R" update-grub || exit 1
    fi

    # Provision system-level Kyber-1024 (ML-KEM-1024) Quantum FDE layer in /etc/alfred/quantum-fde
    log "provisioning /etc/alfred/quantum-fde Kyber-1024 (ML-KEM-1024) layer"
    chroot "$R" /bin/bash -c '
        umask 077
        KYBER_DIR="/etc/alfred/quantum-fde"
        mkdir -p "$KYBER_DIR"
        chmod 700 "$KYBER_DIR"
        KEM_ALG="ML-KEM-1024"
        openssl list -kem-algorithms 2>/dev/null | grep -qi "kyber1024" && KEM_ALG="kyber1024"
        if openssl genpkey -algorithm "$KEM_ALG" -out "$KYBER_DIR/fde-kyber.key" 2>/dev/null; then
            openssl pkey -in "$KYBER_DIR/fde-kyber.key" -pubout -out "$KYBER_DIR/fde-kyber.pub" 2>/dev/null || true
            openssl pkeyutl -encap -inkey "$KYBER_DIR/fde-kyber.pub" -pubin \
                -secret "$KYBER_DIR/quantum-keyfile.bin" \
                -out "$KYBER_DIR/kem-ciphertext.bin" 2>/dev/null || true
            chmod 600 "$KYBER_DIR"/* 2>/dev/null || true
        fi
    ' || true

    # Lock shared root password
    chroot "$R" passwd -l root >/dev/null 2>&1 || true

    # Purge lingering default live password 'alfred' from target /etc/shadow
    # If the user did not set a custom password, remove the default password so no backdoor exists
    log "purging lingering default live password 'alfred' from target /etc/shadow"
    python3 -c "
import os, sys, ctypes
try:
    libcrypt = ctypes.CDLL('libcrypt.so.1')
    libcrypt.crypt.restype = ctypes.c_char_p
    libcrypt.crypt.argtypes = [ctypes.c_char_p, ctypes.c_char_p]
    root = sys.argv[1]
    shadow_path = os.path.join(root, 'etc/shadow')
    if os.path.exists(shadow_path):
        lines = []
        with open(shadow_path) as f:
            for l in f:
                p = l.strip().split(':')
                if len(p) > 1 and p[1].startswith('$'):
                    res = libcrypt.crypt(b'alfred', p[1].encode('utf-8'))
                    if res and res.decode('utf-8') == p[1]:
                        p[1] = ''
                lines.append(':'.join(p) + '\n')
        with open(shadow_path, 'w') as f:
            f.writelines(lines)
except Exception:
    pass
" "$R" || true

    # Enable Alfred Server Root Onboarding Daemon for headless / server access
    chroot "$R" systemctl enable alfred-server-onboard.service >/dev/null 2>&1 || true

    rm -rf "$R/var/lib/alfred-installer"
    ls -la "$R/boot" | sed 's/^/[alfred-install-hook] boot: /'
    log "final done"
}

cmd="${1:-}"; shift || true
case "$cmd" in
    src|prep|home|models|final) "$cmd" "$@" ;;
    *) echo "usage: $0 src|prep ROOT|home ROOT USER|models ROOT|final ROOT"; exit 2 ;;
esac
