#!/bin/sh
# banger-first-boot — universal init wrapper for banger VMs.
#
# When passed as init= on the kernel cmdline (direct-boot images without
# an initramfs), this script runs as PID 1. It:
#   1. Mounts the essential virtual filesystems (/proc, /sys, /dev, /run)
#   2. If systemd (or any init) is already installed, execs it immediately
#   3. Otherwise: brings up the network, installs systemd + openssh-server
#      via the guest's native package manager, then execs systemd
#
# On subsequent boots (after systemd is installed), step 2 fires in <10ms.
#
# Test hooks:
#   RUN_PLAN=1              echo the install command instead of executing it
#   OS_RELEASE_FILE=<path>  override /etc/os-release for distro detection
#   BANGER_FIRST_BOOT_MARKER=<path>  override the marker file path

set -eu

log() { printf '[banger-first-boot] %s\n' "$*" >&2; }

# --- Step 1: essential mounts (only when running as PID 1) ---
if [ "$$" = "1" ]; then
  mount -t proc     proc     /proc 2>/dev/null || true
  mount -t sysfs    sysfs    /sys  2>/dev/null || true
  mount -t devtmpfs devtmpfs /dev  2>/dev/null || true
  mount -t tmpfs    tmpfs    /run  2>/dev/null || true
  mount -t tmpfs    tmpfs    /tmp  2>/dev/null || true
fi

# --- Step 2: if a real init exists, hand off immediately ---
# (RUN_PLAN mode skips this so the dispatch logic can be tested on hosts
# that have systemd installed.)
if [ "${RUN_PLAN:-0}" != "1" ]; then
  for candidate_init in /usr/lib/systemd/systemd /lib/systemd/systemd /sbin/init; do
    if [ -x "$candidate_init" ]; then
      MARKER="${BANGER_FIRST_BOOT_MARKER:-/var/lib/banger/first-boot-pending}"
      if [ -f "$MARKER" ]; then
        rm -f "$MARKER"
      fi
      log "found init at $candidate_init; handing off"
      exec "$candidate_init" "$@"
    fi
  done
fi

# --- Step 3: no init found — we're on a container image, provision it ---
log "no init system found; installing systemd + openssh-server"

# Bring up network so apt-get/apk can reach package repos.
# banger-network-bootstrap reads IP from /proc/cmdline (kernel ip= arg)
# or /etc/banger-network.conf (written by vm_disk.patchRootOverlay).
if [ -x /usr/local/libexec/banger-network-bootstrap ]; then
  log "bringing up network"
  /usr/local/libexec/banger-network-bootstrap || log "network bootstrap failed (continuing anyway)"
fi

# Detect distro
DIST=""
FAMILY=""
OS_RELEASE_FILE="${OS_RELEASE_FILE:-/etc/os-release}"
if [ -r "$OS_RELEASE_FILE" ]; then
  # shellcheck source=/dev/null
  . "$OS_RELEASE_FILE"
  DIST="${ID:-}"
  FAMILY="${ID_LIKE:-}"
fi
log "detected distro: ID=$DIST ID_LIKE=$FAMILY"

# Dispatch install command
CMD=""
case "$DIST" in
  debian|ubuntu|kali|raspbian|linuxmint|pop)
    CMD="apt-get update && apt-get install -y systemd-sysv openssh-server"
    ;;
  alpine)
    CMD="apk add --no-cache openrc openssh systemd"
    ;;
  fedora|rhel|centos|rocky|almalinux)
    CMD="dnf install -y systemd openssh-server"
    ;;
  arch|archlinux|manjaro)
    CMD="pacman -Sy --noconfirm openssh"
    ;;
  opensuse*|suse)
    CMD="zypper --non-interactive install -y systemd openssh"
    ;;
  *)
    case " $FAMILY " in
      *" debian "*)
        CMD="apt-get update && apt-get install -y systemd-sysv openssh-server"
        ;;
      *" rhel "* | *" fedora "*)
        CMD="dnf install -y systemd openssh-server"
        ;;
      *" arch "*)
        CMD="pacman -Sy --noconfirm openssh"
        ;;
      *" suse "*)
        CMD="zypper --non-interactive install -y systemd openssh"
        ;;
    esac
    ;;
esac

if [ -z "$CMD" ]; then
  log "FATAL: no known install command for distro '$DIST' (ID_LIKE='$FAMILY')"
  log "drop to emergency shell"
  exec /bin/sh
fi

if [ "${RUN_PLAN:-0}" = "1" ]; then
  printf '%s\n' "$CMD"
  exit 0
fi

log "running: $CMD"
eval "$CMD" || {
  log "package install failed; dropping to shell"
  exec /bin/sh
}

# Remove first-boot marker
MARKER="${BANGER_FIRST_BOOT_MARKER:-/var/lib/banger/first-boot-pending}"
rm -f "$MARKER"

# systemd should now be installed — find and exec it
for candidate_init in /usr/lib/systemd/systemd /lib/systemd/systemd /sbin/init; do
  if [ -x "$candidate_init" ]; then
    log "provisioning complete; starting $candidate_init"
    # Unmount our temp mounts — systemd will re-mount them properly
    umount /tmp  2>/dev/null || true
    umount /run  2>/dev/null || true
    umount /dev  2>/dev/null || true
    umount /sys  2>/dev/null || true
    umount /proc 2>/dev/null || true
    exec "$candidate_init" "$@"
  fi
done

log "FATAL: init not found after install; dropping to shell"
exec /bin/sh
