set positional-arguments

host := `hostname`
key_services := "github gradescope"

# Default: list available recipes.
default:
    @just --list

# Rebuild the system and switch immediately
rebuild:
    sudo nixos-rebuild switch --flake .#{{host}}

# Update flake.lock
update:
    nix flake update

# Clean up old generations and optimize store
gc:
    sudo nix-collect-garbage --delete-older-than 14d
    sudo nix-store --optimise
    sudo nixos-rebuild boot --flake .#{{host}}

# Generate Ed25519 SSH keys for each configured service
gen-keys:
    #!/usr/bin/env bash
    set -euo pipefail

    mkdir -p ~/.ssh
    chmod 700 ~/.ssh

    for service in {{key_services}}; do
        file="$HOME/.ssh/id_$service"
        if [ -f "$file" ]; then
            echo "skipping: $file already exists"
            continue
        fi
        echo "generating: $file"
        ssh-keygen -t ed25519 -f "$file" -N "" -C "$service@$(hostname -s)"
    done

# Build a bootable NixOS installer USB (writes ISO + optional extras partition).
# Pass arguments through to scripts/make-usb.sh, e.g.:
#     just make-usb --iso ~/Downloads/nixos.iso
# Re-executes itself under sudo if not already root. Quoting is preserved
# via `set positional-arguments` + "$@".
make-usb *args:
    #!/usr/bin/env bash
    set -euo pipefail
    if [[ ! -x scripts/make-usb.sh ]]; then
        chmod +x scripts/make-usb.sh
    fi
    if (( EUID == 0 )); then
        exec ./scripts/make-usb.sh "$@"
    else
        exec sudo --preserve-env=PATH ./scripts/make-usb.sh "$@"
    fi

# Register a new host: scaffold hosts/<name>/ and add a flake.nix entry.
# Example: just register-host blackbear
register-host name:
    @python3 scripts/register-host.py --repo-root . "{{name}}"

# Capture the current machine's hardware config into hosts/<name>/hardware.nix.
# Run this on the *new* machine. Two contexts work:
#   1. Already-installed NixOS: just runs nixos-generate-config against /.
#   2. Booted from installer with target mounted at /mnt: detected
#      automatically and --root /mnt is used.
# Example: just capture-hardware blackbear
capture-hardware name:
    #!/usr/bin/env bash
    set -euo pipefail

    name="{{name}}"
    target="hosts/$name/hardware.nix"

    if [[ ! -d "hosts/$name" ]]; then
        echo "[-] hosts/$name does not exist. Run \`just register-host $name\` first." >&2
        exit 1
    fi

    if ! command -v nixos-generate-config >/dev/null 2>&1; then
        echo "[-] nixos-generate-config not found." >&2
        echo "    Run this command on a NixOS machine (or inside the installer)." >&2
        exit 1
    fi

    # Detect whether we're in the installer with a target mounted at /mnt.
    extra_args=()
    if mountpoint -q /mnt 2>/dev/null && [[ -d /mnt/etc ]]; then
        echo "[+] Detected mounted target at /mnt — using --root /mnt"
        extra_args+=(--root /mnt)
    elif mountpoint -q /mnt 2>/dev/null; then
        echo "[!] /mnt is mounted but doesn't look like a NixOS target (no /mnt/etc)."
        echo "    Continuing as if on a running system. Pass --no-filesystems by editing"
        echo "    hardware.nix afterwards if disks aren't permanent."
    fi

    # Confirm before overwriting a non-placeholder hardware.nix.
    if [[ -f "$target" ]] && ! grep -q 'PLACEHOLDER hardware.nix' "$target"; then
        echo "[!] $target already exists and doesn't look like a placeholder." >&2
        read -r -p "Overwrite? (yes/[no]) " confirm
        [[ "$confirm" == "yes" ]] || { echo "aborted."; exit 1; }
    fi

    echo "[+] Generating hardware config..."
    # The redirect runs in the user's shell BEFORE sudo, so the file is
    # owned by you, not root.  sudo is needed because nixos-generate-config
    # reads /proc, /sys, and may probe mounted filesystems.
    sudo nixos-generate-config --show-hardware-config "${extra_args[@]}" > "$target"
    echo "[+] Wrote $target"
    if command -v git >/dev/null && git -C . rev-parse >/dev/null 2>&1; then
        echo "[+] git diff:"
        git --no-pager diff -- "$target" || true
    fi

# Show which hosts are currently registered in flake.nix (parses the file directly).
hosts:
    #!/usr/bin/env python3
    import re, sys
    src = open('flake.nix').read()
    m = re.search(r'nixosConfigurations\s*=\s*\{', src)
    if not m:
        sys.exit(0)
    # Brace-match to find the closing }.
    depth, i, close = 0, m.end() - 1, None
    while i < len(src):
        c = src[i]
        if c == '{': depth += 1
        elif c == '}':
            depth -= 1
            if depth == 0:
                close = i
                break
        i += 1
    block = src[m.end():close] if close else ''
    for name in re.findall(r'^[ \t]*([A-Za-z_][\w-]*)\s*=\s*nixpkgs\.lib\.nixosSystem', block, re.M):
        print(name)

