#!/bin/bash
# ╔══════════════════════════════════════════════════════════════════════════════╗
# ║  setup/modules/package-managers.sh — Package manager bootstrap            ║
# ║                                                                              ║
# ║  PURPOSE:                                                                    ║
# ║    Installs and configures the additional package managers and language     ║
# ║    runtimes that the rest of the setup depends on. This must be the        ║
# ║    FIRST module run because others rely on yay, nvm, and rustup.           ║
# ║                                                                              ║
# ║  INSTALLS:                                                                   ║
# ║    - Flatpak (via pacman) — universal app sandbox, Flathub remote          ║
# ║    - yay — AUR helper (builds packages from the Arch User Repository)      ║
# ║    - rustup — Rust toolchain manager; sets stable as default               ║
# ║    - nvm + Node.js 22 — JavaScript runtime for CLI tools                  ║
# ║                                                                              ║
# ║  ALL INSTALLS ARE IDEMPOTENT — safe to run multiple times.                ║
# ╚══════════════════════════════════════════════════════════════════════════════╝

set -euo pipefail
# -e: abort immediately if any command fails (package manager errors are fatal here)
# -u: error on unset variables
# -o pipefail: pipe failures are caught

# Load shared logging helpers (log, skip, warn, err functions)
source "$(dirname "${BASH_SOURCE[0]}")/lib/logging.sh"

# ── Flatpak + system update ────────────────────────────────────────────────────
# WHY: Run a full system upgrade first (-yu) to avoid partial-upgrade issues
#      where pacman has a newer database but old packages. This is critical on
#      Arch which is a rolling release.
# Flatpak is installed here (not in core-packages.sh) because it's needed before
# the Flathub remote can be added, and some modules call ensure_flatpak() early.
log "Updating system and installing Flatpak..."
sudo pacman -Syu --noconfirm --needed flatpak

# ── yay (AUR helper) ──────────────────────────────────────────────────────────
# WHY: The AUR (Arch User Repository) contains thousands of community packages
#      not in the official repos. yay is the most popular AUR helper — it wraps
#      pacman and handles PKGBUILD downloading, building, and installing.
# HOW: Clone the yay PKGBUILD from AUR, then build and install it with makepkg.
#      makepkg -si: build the package (-s=sync dependencies) and install (-i).
# IDEMPOTENCY: Check for the yay binary first to avoid rebuilding if already present.
if ! command -v yay &>/dev/null; then
    log "Installing yay..."
    # Use ~/install-tmp rather than /tmp to survive across sudo sessions and avoid
    # tmpfs size limits on systems with small RAM
    mkdir -p ~/install-tmp
    git clone https://aur.archlinux.org/yay.git ~/install-tmp/yay
    cd ~/install-tmp/yay
    # --noconfirm: don't prompt during the build/install process
    makepkg -si --noconfirm
    cd ~
else
    skip "yay already installed."
fi

# ── rustup / Rust toolchain ────────────────────────────────────────────────────
# WHY: Rust is used by many modern CLI tools (yazi, starship, zellij, etc.) and
#      some AUR packages require cargo to build from source.
#      rustup is preferred over the `rust` package because it allows switching
#      between stable/nightly channels and managing multiple targets.
# HOW: Install rustup via pacman (it's in the official repos), then set
#      `stable` as the active toolchain so `cargo` and `rustc` are available.
if ! command -v rustup &>/dev/null; then
    log "Installing rustup..."
    sudo pacman -S --noconfirm --needed rustup
fi
# Always run 'rustup default stable' even if rustup exists — this is idempotent
# and ensures the correct toolchain is active (guards against nightly being default)
rustup default stable

# ── nvm + Node.js ─────────────────────────────────────────────────────────────
# WHY: Node.js is required for npm-based tools including Claude Code CLI,
#      LocalTunnel, and other developer utilities. We use nvm (Node Version Manager)
#      rather than the system `node` package because:
#        1. nvm allows per-project Node version pinning via .nvmrc
#        2. Global npm packages install to ~/.nvm without needing sudo
#        3. Switching to LTS or newer versions is a one-liner
# HOW: Download and run the official nvm install script, then source nvm.sh to
#      activate it in this shell session, then install Node.js LTS v22.
# NOTE: nvm installs to ~/.nvm/ and injects itself via .bashrc/.zshrc hooks
if ! command -v node &>/dev/null; then
    log "Installing nvm and Node.js 22..."
    # Only clone nvm if its directory doesn't exist (guards against partial installs)
    if [ ! -d "$HOME/.nvm" ]; then
        # Pin to a specific nvm version for reproducibility
        curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.2/install.sh | bash
    fi
    # Source nvm into the current shell session (normally loaded by .bashrc/.zshrc)
    . "$HOME/.nvm/nvm.sh"
    # Install Node.js 22 (current LTS) and set it as the active version
    nvm install 22
else
    # Report the currently-installed version so the log shows what's active
    skip "Node.js already installed: $(node -v)"
fi

log "Package managers ready."
