#!/usr/bin/env bash
# Installer for edge-1 (bare-metal edge host, replaces the k8s-edge VM).
# Runs from the edge-host ISO live environment. WIPES the target disk.
# Usage: edge-install [disk]
# Default: the internal disk — first NVMe, else eMMC (Wyse 3040), else
# the first non-USB, non-optical disk. The live USB stick itself is
# excluded via the ISO9660 label mount.
set -euo pipefail

HOST=edge-1

detect_disk() {
  # eMMC needs mmc_block before any /dev/mmcblk* exists (see
  # modules-load.d/edge-mmc.conf; belt-and-braces here for older sticks).
  modprobe -q mmc_block sdhci_acpi 2>/dev/null || true
  udevadm settle 2>/dev/null || true
  [ -b /dev/nvme0n1 ] && { echo /dev/nvme0n1; return; }
  for d in /dev/mmcblk0 /dev/mmcblk1 /dev/mmcblk2; do
    [ -b "$d" ] && { echo "$d"; return; }
  done
  # NAME,TYPE first — TRAN is often empty (eMMC, virtio) and would shift
  # whitespace-split fields if it sat in the middle.
  lsblk -dno NAME,TYPE,TRAN | awk '$2=="disk" && $3!="usb" {print "/dev/"$1; exit}'
}

DISK="${1:-$(detect_disk)}"
[ -n "$DISK" ] || { echo "no internal disk found; pass one explicitly"; exit 1; }
[ -b "$DISK" ] || { echo "no such block device: $DISK"; exit 1; }

echo "Target disk: $DISK"
lsblk "$DISK"
echo
read -rp "This WIPES ${DISK} and installs ${HOST}. Type '${HOST}' to continue: " ans
[ "$ans" = "$HOST" ] || { echo "aborted"; exit 1; }

part() {
  case "$DISK" in
    *nvme*|*mmcblk*) echo "${DISK}p$1" ;;
    *) echo "${DISK}$1" ;;
  esac
}

sgdisk --zap-all "$DISK"
sgdisk -n1:0:+512M -t1:ef00 -c1:ESP -N2 -t2:8304 -c2:root "$DISK"
partprobe "$DISK"
mkfs.fat -F32 "$(part 1)"
mkfs.ext4 -F "$(part 2)"

mount "$(part 2)" /mnt
mount --mkdir "$(part 1)" /mnt/boot

# Everything the edge-host ansible role expects to find; the role itself
# is applied over SSH after first boot (see ansible/docs/edge-host.md).
pacstrap -K /mnt base linux linux-firmware intel-ucode openssh python git \
  docker docker-compose

genfstab -U /mnt >> /mnt/etc/fstab

# eMMC boot: autodetect does not reliably include the mmc stack, and a
# root on /dev/mmcblk0p2 without mmc_block in the initramfs is unbootable
# (observed on the Wyse 3040). Pin the modules and regenerate.
sed -i 's/^MODULES=.*/MODULES=(sdhci_acpi sdhci_pci mmc_block)/' /mnt/etc/mkinitcpio.conf
arch-chroot /mnt mkinitcpio -P
echo "$HOST" > /mnt/etc/hostname
ln -sf /usr/share/zoneinfo/Europe/Berlin /mnt/etc/localtime
echo 'en_US.UTF-8 UTF-8' > /mnt/etc/locale.gen
echo 'LANG=en_US.UTF-8' > /mnt/etc/locale.conf
arch-chroot /mnt locale-gen

cat > /mnt/etc/systemd/network/20-wired.network <<'EOF'
[Match]
Type=ether

[Network]
DHCP=yes
EOF
ln -sf /run/systemd/resolve/stub-resolv.conf /mnt/etc/resolv.conf

# Key-only root SSH (no root password is set — console login stays locked,
# which is fine for a headless box; recovery goes through this ISO).
install -d -m700 /mnt/root/.ssh
install -m600 /root/edge-authorized_keys /mnt/root/.ssh/authorized_keys

arch-chroot /mnt systemctl enable \
  systemd-networkd systemd-resolved systemd-timesyncd sshd docker

arch-chroot /mnt bootctl install
cat > /mnt/boot/loader/loader.conf <<'EOF'
default edge.conf
timeout 3
EOF
cat > /mnt/boot/loader/entries/edge.conf <<EOF
title Arch Linux (${HOST})
linux /vmlinuz-linux
initrd /intel-ucode.img
initrd /initramfs-linux.img
options root=UUID=$(blkid -s UUID -o value "$(part 2)") rw
EOF

umount -R /mnt
echo
echo "${HOST} installed. Remove the USB stick and reboot."
echo
echo "Then, from the workstation:"
echo "  1. confirm 'ssh root@${HOST}' works (it must be reachable by name)"
echo "  2. add ${HOST} to [edge_host] in ansible/inventory/pve_hosts.yml"
echo "  3. cd ansible && ansible-playbook -i inventory/pve_hosts.yml \\"
echo "       plays/install-edge-host.yml"
echo
echo "One run, whole group, no --limit: the play carries certificates and"
echo "common itself, so there is no separate common.yml step."
