{ pkgs, lib, modulesPath, inputs, ... }:
let
  installScript = pkgs.writeShellScriptBin "nixos-install-host" ''
    set -euo pipefail

    BOLD='\033[1m'
    RED='\033[0;31m'
    GREEN='\033[0;32m'
    YELLOW='\033[1;33m'
    NC='\033[0m'

    header() { echo -e "\n''${BOLD}==> $1''${NC}"; }
    ok()     { echo -e "''${GREEN}[ok]''${NC} $1"; }
    warn()   { echo -e "''${YELLOW}[warn]''${NC} $1"; }
    die()    { echo -e "''${RED}[error]''${NC} $1"; exit 1; }

    # ------------------------------------------------------------------ #
    # Network                                                              #
    # ------------------------------------------------------------------ #

    header "Network"
    echo "An internet connection is required to download packages during installation."
    echo "If you need Wi-Fi, connect now with: nmtui"
    echo ""
    read -p "Press Enter when the network is ready (or Ctrl-C to abort)..."

    # ------------------------------------------------------------------ #
    # Host selection                                                       #
    # ------------------------------------------------------------------ #

    header "NixOS Installer"
    echo "Evaluating flake..."
    HOSTS_JSON=$(nix eval "path:/etc/nixos-config#nixosConfigurations" \
                   --apply builtins.attrNames --json) \
      || die "Failed to evaluate the flake at /etc/nixos-config."

    echo "Available hosts:"
    echo "$HOSTS_JSON" | ${pkgs.jq}/bin/jq -r '.[]' | grep -v installer | sed 's/^/  /'
    echo ""

    read -p "Host to install: " HOST
    [ -z "$HOST" ] && die "No host specified."

    # Verify the selected host has disko configured before touching anything.
    # local.notebook.disk is only defined for hosts that include notebook-disko.nix.
    echo "Checking that '$HOST' supports automated installation..."
    nix eval "path:/etc/nixos-config#nixosConfigurations.$HOST.config.local.notebook.disk" \
        --raw > /dev/null 2>&1 \
      || die "Host '$HOST' does not have a disko configuration. Only 'notebook' is supported."
    ok "Host '$HOST' is supported."

    # ------------------------------------------------------------------ #
    # Hardware detection                                                   #
    # ------------------------------------------------------------------ #

    header "Detecting hardware"
    echo "Running nixos-generate-config..."
    DETECTED_HW=$(nixos-generate-config --no-filesystems --show-hardware-config 2>/dev/null) \
      || die "Failed to detect hardware. Is nixos-generate-config available?"
    ok "Hardware detected."

    # Build a writable copy of the embedded flake and inject the detected
    # hardware config so both disko and nixos-install use the right modules.
    echo "Preparing installation flake..."
    rm -rf /tmp/nixos-flake
    cp -rL /etc/nixos-config /tmp/nixos-flake
    echo "$DETECTED_HW" > /tmp/nixos-flake/modules/_hardware/notebook-hardware.nix
    ok "Hardware config written to flake."

    FLAKE="path:/tmp/nixos-flake"

    # ------------------------------------------------------------------ #
    # Disk selection                                                       #
    # ------------------------------------------------------------------ #

    header "Available disks"
    lsblk -d -o NAME,SIZE,MODEL --noheadings | grep -v loop
    echo ""

    CONFIGURED_DISK=$(nix eval "$FLAKE#nixosConfigurations.$HOST.config.local.notebook.disk" \
                        --raw 2>/dev/null || echo "/dev/nvme0n1")
    echo -e "Disk configured for this host: ''${BOLD}$CONFIGURED_DISK''${NC}"
    read -p "Target disk [$CONFIGURED_DISK]: " DISK_INPUT
    DISK="''${DISK_INPUT:-$CONFIGURED_DISK}"

    [ ! -b "$DISK" ] && die "$DISK is not a valid block device."

    if [ "$DISK" != "$CONFIGURED_DISK" ]; then
      warn "Disk $DISK differs from configured $CONFIGURED_DISK."
      warn "The disko config will use $DISK regardless, but update local.notebook.disk in"
      warn "modules/_hardware/notebook-disko.nix and commit it after installation."
    fi

    # ------------------------------------------------------------------ #
    # Age key                                                              #
    # ------------------------------------------------------------------ #

    header "Age key (secrets decryption)"
    KEYS_PATH=""

    # Search already-mounted media (standard auto-mount paths)
    for candidate in \
        /run/media/nixos/*/keys.txt \
        /run/media/*/keys.txt \
        /run/media/*/*/keys.txt \
        /tmp/keys.txt; do
      if [ -f "$candidate" ]; then
        KEYS_PATH="$candidate"
        ok "Found at $KEYS_PATH"
        break
      fi
    done

    # When booting via Ventoy the USB data partition (label "Ventoy") is not
    # auto-mounted in the live environment — only the ISO loop device is set up.
    # Detect it by label, mount read-only, copy keys.txt to /tmp, then unmount.
    if [ -z "$KEYS_PATH" ]; then
      VENTOY_DEV=$(${pkgs.util-linux}/bin/blkid -t LABEL="Ventoy" -o device 2>/dev/null | head -1 || true)
      if [ -n "$VENTOY_DEV" ]; then
        warn "keys.txt not found in mounted media. Trying Ventoy partition ($VENTOY_DEV)..."
        VENTOY_MNT=$(mktemp -d)
        if mount -o ro "$VENTOY_DEV" "$VENTOY_MNT" 2>/dev/null; then
          if [ -f "$VENTOY_MNT/keys.txt" ]; then
            cp "$VENTOY_MNT/keys.txt" /tmp/keys.txt
            chmod 600 /tmp/keys.txt
            KEYS_PATH="/tmp/keys.txt"
            ok "Found on Ventoy USB — copied to /tmp/keys.txt"
          else
            warn "Ventoy partition mounted but no keys.txt found at its root."
            echo "Contents of Ventoy root:"
            ls "$VENTOY_MNT" | sed 's/^/  /'
          fi
          umount "$VENTOY_MNT" 2>/dev/null || true
          rm -rf "$VENTOY_MNT"
        else
          warn "Could not mount Ventoy partition $VENTOY_DEV."
        fi
      fi
    fi

    if [ -z "$KEYS_PATH" ]; then
      warn "Age key not found automatically."
      echo "Options:"
      echo "  1. Place keys.txt at the root of the Ventoy USB (alongside the .iso)"
      echo "  2. Mount another USB and it will be found at /run/media/*"
      echo "  3. Enter the path manually below"
      read -p "Path to keys.txt: " KEYS_PATH
    fi

    [ ! -f "$KEYS_PATH" ] && die "Age key not found at $KEYS_PATH"

    # ------------------------------------------------------------------ #
    # Confirmation                                                         #
    # ------------------------------------------------------------------ #

    header "Confirmation"
    echo -e "  Host   : ''${BOLD}$HOST''${NC}"
    echo -e "  Disk   : ''${BOLD}$DISK''${NC} (ALL DATA WILL BE ERASED)"
    echo -e "  Keys   : ''${BOLD}$KEYS_PATH''${NC}"
    echo ""
    read -p "Type 'yes' to continue: " CONFIRM
    [ "$CONFIRM" != "yes" ] && { echo "Aborted."; exit 1; }

    # ------------------------------------------------------------------ #
    # Installation                                                         #
    # ------------------------------------------------------------------ #

    header "Partitioning and formatting"
    echo "(You will be prompted to set the LUKS passphrase.)"
    disko --mode destroy,format,mount --flake "$FLAKE#$HOST"

    header "Copying age key"
    mkdir -p /mnt/etc/sops/age
    install -m 600 "$KEYS_PATH" /mnt/etc/sops/age/keys.txt
    ok "Age key installed."

    header "Installing NixOS"
    nixos-install --root /mnt --flake "$FLAKE#$HOST" --no-root-passwd

    # ------------------------------------------------------------------ #
    # Post-install: save config to the new system                         #
    # ------------------------------------------------------------------ #

    header "Saving configuration"
    # Copy the flake (including the detected hardware config) to the user's
    # working directory on the installed system so they can commit it.
    mkdir -p /mnt/home/zoty/repos
    cp -r /tmp/nixos-flake /mnt/home/zoty/repos/nixos
    # UID 1000 is the first normal user, matching the zoty account.
    chown -R 1000:1000 /mnt/home/zoty/repos/nixos
    ok "Configuration saved to ~/repos/nixos on the installed system."

    echo ""
    ok "Installation complete! Remove the USB drive and reboot."
    echo ""
    echo "After the first boot, commit the detected hardware config:"
    echo "  cd ~/repos/nixos"
    echo "  git add modules/_hardware/notebook-hardware.nix"
    echo "  git commit -m 'add notebook hardware config'"
    echo "  git push"
  '';
in {
  imports = [
    "${modulesPath}/installer/cd-dvd/installation-cd-minimal.nix"
  ];

  # Ventoy presents the ISO as a virtual CDROM without the filesystem label
  # that NixOS stage-1 expects (nixos-minimal-*). Stage-1 cannot find the
  # loop device for nix-store.squashfs, causing "unable to read id index table".
  # copytoram loads the entire ISO into RAM before the squashfs mount, removing
  # the dependency on the Ventoy device remaining accessible during boot.
  # See: https://github.com/NixOS/nixpkgs/issues/245101
  boot.kernelParams = [ "copytoram" ];
  boot.zfs.forceImportRoot = false;

  services.getty.autologinUser = lib.mkForce "root";

  nix.settings = {
    experimental-features = [ "nix-command" "flakes" ];
    tarball-ttl            = 0;
  };

  # NetworkManager instead of wpa_supplicant for nmtui support
  networking.networkmanager.enable   = true;
  networking.wireless.enable         = lib.mkForce false;

  environment.systemPackages = [
    installScript
    inputs.disko.packages.${pkgs.stdenv.hostPlatform.system}.default
    pkgs.git
    pkgs.age
    pkgs.sops
    pkgs.jq
    pkgs.neovim
  ];

  # Embed the flake source so the install script can copy it at install time.
  # The script copies it to /tmp/nixos-flake (writable) and injects the
  # detected hardware config before running disko and nixos-install.
  environment.etc."nixos-config".source = ../.;

  documentation.enable       = lib.mkForce false;
  documentation.nixos.enable = lib.mkForce false;

  system.stateVersion = "25.11";
}
