#!/usr/bin/env bash
# minimal-ai installer
#
# Install:
#   curl -fsSL https://raw.githubusercontent.com/eeshansrivastava89/minimal-ai/main/install.sh | bash
#
# Or review first:
#   curl -fsSL https://raw.githubusercontent.com/eeshansrivastava89/minimal-ai/main/install.sh | less
#
# What this does:
#   1. Checks for Node.js
#   2. If not found, installs it via nvm (no sudo needed)
#   3. Installs minimal-ai globally via npm
#   4. Ensures everything is on PATH (nvm + ~/.local/bin in .zprofile)
#   5. Launches minimal-ai (chained: onboarding → model picker in one flow)
#
# Flags:
#   --dry-run    Show what would happen without making changes
#   --help       Show this help
#
# This script never uses sudo. Everything installs to user-writable directories.

set -euo pipefail

NVM_INSTALLED=false

# ── Flags ───────────────────────────────────────────────────────────────────

DRY_RUN=false

for arg in "$@"; do
  case "$arg" in
    --dry-run)  DRY_RUN=true; echo "[dry-run] No changes will be made." ;;
    --help|-h)   echo "Usage: curl -fsSL <url> | bash -s -- [--dry-run]"; exit 0 ;;
  esac
done

dry() { if $DRY_RUN; then printf "[dry-run] %s\n" "$*"; return 0; else "$@"; fi; }

# ── Visual style (Fang-inspired) ────────────────────────────────────────────

BOLD='\033[1m' RESET='\033[0m'
CYAN='\033[36m' MAGENTA='\033[35m' GREEN='\033[32m'
YELLOW='\033[33m' RED='\033[31m' DIM='\033[2m'

_term_width() {
  tput cols 2>/dev/null || echo 72
}

_section_line() {
  local width
  width=$(_term_width)
  [ "$width" -gt 80 ] && width=80
  local fill=$((width - ${#1} - 1))
  [ "$fill" -lt 0 ] && fill=0
  printf '%*s' "$fill" '' | tr ' ' '─'
}

section() {
  printf "\n${BOLD}${MAGENTA}%s${RESET} ${DIM}%s${RESET}\n" "$1" "$(_section_line "$1")"
}

codeblock() {
  printf "  ${DIM}│${RESET} %s\n" "$1"
}

info()  { printf "${CYAN}→${RESET} %s\n" "$*"; }
ok()     { printf "${GREEN}✓${RESET} %s\n" "$*"; }
warn()   { printf "${YELLOW}!${RESET} %s\n" "$*"; }
fail()   { printf "${RED}✗${RESET} %s\n" "$*"; exit 1; }

# ── Header ───────────────────────────────────────────────────────────────────

printf "\n${BOLD}${CYAN}minimal-ai${RESET} ${DIM}— A privacy-first local AI runner${RESET}\n\n"

printf "  ${DIM}Install:${RESET}\n"
codeblock "curl -fsSL https://raw.githubusercontent.com/eeshansrivastava89/minimal-ai/main/install.sh | bash"
printf "\n"

# ── Detect OS ───────────────────────────────────────────────────────────────

section "DETECTED SYSTEM"

OS="$(uname -s)"
ARCH="$(uname -m)"
case "$OS" in
  Darwin) OS="macos" ;;
  Linux)  OS="linux" ;;
  *)      fail "Unsupported OS: $OS. minimal-ai requires macOS or Linux." ;;
esac
case "$ARCH" in
  x86_64|amd64) ARCH="x64" ;;
  arm64|aarch64) ARCH="arm64" ;;
  *)             fail "Unsupported architecture: $ARCH" ;;
esac
ok "Detected: ${OS}-${ARCH}"

# ── Check for Node.js ───────────────────────────────────────────────────────

section "NODE.JS"

if command -v node &>/dev/null; then
  NODE_VERSION="$(node --version 2>/dev/null || echo "unknown")"
  NODE_MAJOR="$(echo "$NODE_VERSION" | sed 's/^v//' | cut -d. -f1)"
  if [ "$NODE_MAJOR" -ge 20 ] 2>/dev/null; then
    ok "Node.js ${NODE_VERSION} found at $(command -v node)"
  else
    warn "Node.js ${NODE_VERSION} found, but minimal-ai requires Node >=20."
    echo "  Install Node.js 20+ via nvm: nvm install --lts"
    echo "  Or download from https://nodejs.org/"
    exit 1
  fi
else
  echo ""
  printf "${BOLD}minimal-ai needs Node.js.${RESET}\n"
  printf "It will be installed now via nvm (Node Version Manager).\n"
  printf "This installs to your home directory — no sudo needed.\n"
  echo ""

  # Install nvm
  export NVM_DIR="${NVM_DIR:-$HOME/.nvm}"
  info "Installing nvm..."
  dry curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh -o /tmp/nvm-install.sh
  dry bash /tmp/nvm-install.sh

  # Source nvm in this script
  if ! $DRY_RUN; then
    [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
  fi

  # Install Node.js LTS
  info "Installing Node.js LTS..."
  dry nvm install --lts

  # Verify
  if $DRY_RUN || command -v node &>/dev/null; then
    ok "Node.js $(node --version 2>/dev/null || echo 'installed') installed via nvm."
    NVM_INSTALLED=true
  else
    ok "Node.js installed via nvm."
    echo ""
    warn "Node.js was installed but your shell doesn't see it yet."
    echo "  Restart your terminal, or run: source ~/.nvm/nvm.sh"
    echo "  Then re-run this installer."
    exit 0
  fi
fi

# ── Ensure ~/.local/bin is on PATH (for HuggingFace CLI) ───────────────────

section "PATH SETUP"

LOCAL_BIN="$HOME/.local/bin"
if ! $DRY_RUN; then
  # Add to current process PATH
  [[ -d "$LOCAL_BIN" ]] && export PATH="$LOCAL_BIN:$PATH"

  # Persist to shell profile (same file nvm uses)
  PROFILE_FILE="$HOME/.zprofile"
  [[ "$OSTYPE" != darwin* ]] && PROFILE_FILE="$HOME/.bashrc"
  if ! grep -qF '.local/bin' "$PROFILE_FILE" 2>/dev/null; then
    echo '' >> "$PROFILE_FILE"
    echo '# Added by minimal-ai installer (HuggingFace CLI)' >> "$PROFILE_FILE"
    echo 'export PATH="$HOME/.local/bin:$PATH"' >> "$PROFILE_FILE"
  fi
fi
ok "~/.local/bin is on PATH"

# ── Install minimal-ai ──────────────────────────────────────────────────────

section "INSTALL"

info "Installing minimal-ai via npm..."
dry npm install -g minimal-ai@latest --prefer-online

# ── Dry-run early exit ──────────────────────────────────────────────────────

if $DRY_RUN; then
  ok "minimal-ai installed (dry-run)"
  echo ""
  printf "${BOLD}${GREEN}────────────────────────────────────────────────${RESET}\n"
  printf "${BOLD}${GREEN}  minimal-ai is ready! (dry-run)${RESET}\n"
  printf "${BOLD}${GREEN}────────────────────────────────────────────────${RESET}\n"
  echo ""
  echo "  Run: minimal-ai"
  echo ""
  exit 0
fi

# ── Get installed version ───────────────────────────────────────────────────

INSTALLED_VERSION=""
NPM_PREFIX="$(npm prefix -g 2>/dev/null || true)"
NPM_BIN="${NPM_PREFIX%/}/bin"
if [[ -x "$NPM_BIN/minimal-ai" ]]; then
  INSTALLED_VERSION="$(MINIMAL_NO_UPDATE_CHECK=1 "$NPM_BIN/minimal-ai" version 2>/dev/null | sed -E 's/^minimal-ai v//' || echo "")"
  ok "minimal-ai ${INSTALLED_VERSION:+v${INSTALLED_VERSION} }installed"
else
  warn "minimal-ai was installed but could not be found at $NPM_BIN"
  echo "  Restart your terminal and run: minimal-ai"
  echo "  Or run: npx minimal-ai"
fi

# ── Done ────────────────────────────────────────────────────────────────────

section "READY"

printf "${BOLD}${GREEN}────────────────────────────────────────────────${RESET}\n"
printf "${BOLD}${GREEN}  minimal-ai ${INSTALLED_VERSION:+v${INSTALLED_VERSION} }is ready!${RESET}\n"
printf "${BOLD}${GREEN}────────────────────────────────────────────────${RESET}\n"

cat << 'EOF'

  First run will walk you through setting up everything you need
  (managed llama.cpp runtime for GGUF models, model backends, Pi).

EOF

# ── Launch minimal-ai ──────────────────────────────────────────────────────
#
# Chain the flow: install.sh → minimal-ai onboarding → model picker.
# When nvm was used, node/npm/minimal-ai are in nvm's bin directory, only on
# PATH when nvm is sourced (.zprofile). We start a new login shell that
# sources .zprofile and immediately runs minimal-ai — one continuous flow.
# When nvm wasn't needed (Node already present), minimal-ai is already on
# PATH, so just run it directly.

if [[ -c /dev/tty ]]; then
  printf "${BOLD}Launching minimal-ai...${RESET}\n\n"
  if $NVM_INSTALLED; then
    SHELL="${SHELL:-/bin/zsh}"
    # Login shell sources .zprofile (nvm → PATH), runs minimal-ai,
    # then execs into an interactive login shell so the user stays in
    # a shell with everything on PATH after minimal-ai exits.
    # trap ":" INT keeps the shell alive if the user presses Ctrl+C
    # inside minimal-ai (e.g. cancelling a download) — without it, SIGINT
    # kills the shell too, skipping exec "$SHELL" -il and dropping PATH.
    exec "$SHELL" -l -c 'trap ":" INT; minimal-ai; exec "$SHELL" -il' < /dev/tty
  else
    exec minimal-ai < /dev/tty
  fi
fi
