#!/usr/bin/env sh
# Solid# CLI bootstrap — macOS + Linux
#
# Usage:
#   curl -fsSL https://solidnumber.com/install.sh | sh
#
# What it does (in order):
#   1. Verify network + permissions
#   2. Install Node 20 LTS via fnm if `node` < 20 or missing
#   3. npm install -g @solidnumber/cli@latest
#   4. Run `solid auth login` to open the browser auth flow
#   5. Run `solid install` (Claude Code SessionStart hook) if Claude Code present
#   6. Run `solid completion install` for the active shell
#   7. Print "you're done" with three suggested next commands
#
# Re-runs are safe — every step is idempotent. Set SOLID_INSTALL_SKIP_LOGIN=1
# to skip the auth step (for CI / scripted installs that login with --token).
#
# Phase 3 magic-link auth: if SOLID_INSTALL_TOKEN is set in the environment,
# the bootstrap forwards it to `solid setup --install-token <token>` and the
# CLI exchanges it for a real session in one paste — no browser needed.
#
#   curl -fsSL https://solidnumber.com/install.sh | SOLID_INSTALL_TOKEN=ist_xxx sh
#
# Tokens come from /dashboard/install-command (logged-in user mints them
# fresh on every page load). 5-minute single-use TTL.

set -eu

# ─────────────────────────────────────────────────────────────────────────────
# Pretty output (colors when stdout is a TTY, plain otherwise)
# ─────────────────────────────────────────────────────────────────────────────
if [ -t 1 ] && [ -z "${NO_COLOR:-}" ]; then
  C_RESET="$(printf '\033[0m')"
  C_BOLD="$(printf '\033[1m')"
  C_GREEN="$(printf '\033[32m')"
  C_BLUE="$(printf '\033[34m')"
  C_YELLOW="$(printf '\033[33m')"
  C_RED="$(printf '\033[31m')"
  C_DIM="$(printf '\033[2m')"
else
  C_RESET=""; C_BOLD=""; C_GREEN=""; C_BLUE=""; C_YELLOW=""; C_RED=""; C_DIM=""
fi

step()    { printf "%s▸ %s%s\n"   "$C_BLUE"  "$1" "$C_RESET" >&2; }
ok()      { printf "%s✓ %s%s\n"   "$C_GREEN" "$1" "$C_RESET" >&2; }
warn()    { printf "%s! %s%s\n"   "$C_YELLOW" "$1" "$C_RESET" >&2; }
err()     { printf "%s✗ %s%s\n"   "$C_RED"   "$1" "$C_RESET" >&2; }
divider() { printf "%s%s%s\n"     "$C_DIM"   "────────────────────────────────────────" "$C_RESET" >&2; }

banner() {
  printf "\n"
  printf "%s%s  ╔══════════════════════════════════════════════════════╗%s\n" "$C_BOLD" "$C_GREEN" "$C_RESET"
  printf "%s%s  ║          Solid# CLI — one-command install           ║%s\n" "$C_BOLD" "$C_GREEN" "$C_RESET"
  printf "%s%s  ╚══════════════════════════════════════════════════════╝%s\n" "$C_BOLD" "$C_GREEN" "$C_RESET"
  printf "\n"
}

# ─────────────────────────────────────────────────────────────────────────────
# Detect platform
# ─────────────────────────────────────────────────────────────────────────────
detect_platform() {
  case "$(uname -s)" in
    Darwin)  echo "macos" ;;
    Linux)   echo "linux" ;;
    *)       echo "unknown" ;;
  esac
}

PLATFORM="$(detect_platform)"
if [ "$PLATFORM" = "unknown" ]; then
  err "Unsupported OS: $(uname -s)"
  err "This installer supports macOS and Linux. For Windows, run:"
  err "    iwr -useb https://solidnumber.com/install.ps1 | iex"
  exit 1
fi

# ─────────────────────────────────────────────────────────────────────────────
# Step 1 — verify Node ≥ 20
# ─────────────────────────────────────────────────────────────────────────────
ensure_node() {
  step "Checking Node.js..."

  if command -v node >/dev/null 2>&1; then
    NODE_VERSION="$(node -v | sed 's/^v//' | cut -d. -f1)"
    if [ "$NODE_VERSION" -ge 20 ] 2>/dev/null; then
      ok "Node $(node -v) detected (≥ 20 required)"
      return 0
    fi
    warn "Node $(node -v) is too old — Solid# CLI needs ≥ 20"
  else
    warn "Node.js not found"
  fi

  # Install via fnm — fast, no admin required, works on macOS + Linux
  step "Installing Node 20 LTS via fnm..."
  if ! command -v fnm >/dev/null 2>&1; then
    curl -fsSL https://fnm.vercel.app/install | bash -s -- --skip-shell >&2
    # fnm installs into ~/.local/share/fnm; surface it for the rest of THIS process
    export PATH="$HOME/.local/share/fnm:$PATH"
    eval "$(fnm env --use-on-cd 2>/dev/null || true)"
  fi

  fnm install 20 >&2
  fnm use 20 >&2
  fnm default 20 >&2

  if ! command -v node >/dev/null 2>&1; then
    err "Node install via fnm failed. Install Node 20 LTS manually from https://nodejs.org and re-run."
    exit 1
  fi
  ok "Node $(node -v) installed"
  warn "After install completes, add this to your shell rc to keep fnm on PATH:"
  warn "    eval \"\$(fnm env --use-on-cd)\""
}

# ─────────────────────────────────────────────────────────────────────────────
# Step 2 — install / upgrade the CLI
# ─────────────────────────────────────────────────────────────────────────────
ensure_cli() {
  step "Installing @solidnumber/cli..."

  if npm i -g @solidnumber/cli@latest >&2; then
    ok "CLI installed: $(solid --version 2>/dev/null || echo 'unknown version')"
  else
    err "npm install failed. If you see EACCES errors, try:"
    err "    sudo npm i -g @solidnumber/cli@latest"
    err "Or configure npm to use a user-writable prefix:"
    err "    npm config set prefix ~/.npm-global"
    err "    export PATH=~/.npm-global/bin:\$PATH"
    exit 1
  fi
}

# ─────────────────────────────────────────────────────────────────────────────
# Step 3 — wire everything via `solid setup`
# ─────────────────────────────────────────────────────────────────────────────
# Phase 2 of SPRINT-CLI-ONE-COMMAND-ONBOARDING collapsed the chained
# auth/install/completion verbs into ONE `solid setup` umbrella. This
# bootstrap delegates to it instead of chaining the verbs ourselves —
# one place to evolve the wizard logic, one place to test it.
run_setup() {
  step "Running solid setup..."
  printf "%s%s    Auth + editor MCP + Claude hook + shell completion.%s\n" "$C_DIM" "" "$C_RESET" >&2

  # Build the setup args. SOLID_INSTALL_SKIP_LOGIN=1 inside the bootstrap
  # maps to --skip-auth on the setup wizard.
  setup_args=""
  if [ "${SOLID_INSTALL_SKIP_LOGIN:-0}" = "1" ]; then
    setup_args="--skip-auth"
  fi

  # Phase 3 magic-link auth: forward SOLID_INSTALL_TOKEN if set. The CLI
  # validates the prefix (must start with `ist_`) and exchanges it server-
  # side; bad/expired/replayed tokens get rejected with a useful error.
  if [ -n "${SOLID_INSTALL_TOKEN:-}" ]; then
    setup_args="$setup_args --install-token $SOLID_INSTALL_TOKEN"
    ok "Using install token from SOLID_INSTALL_TOKEN — skipping browser auth"
  fi

  # `--yes` accepts every non-destructive default. Stays interactive for
  # the auth browser flow because the underlying `solid auth login` always
  # opens a browser regardless. </dev/tty so the wizard can read prompts
  # even though we were piped in via curl|sh.
  if solid setup --yes $setup_args </dev/tty; then
    ok "Setup complete"
  else
    warn "Setup returned non-zero — run \`solid setup\` interactively to retry"
  fi
}

# ─────────────────────────────────────────────────────────────────────────────
# Final summary
# ─────────────────────────────────────────────────────────────────────────────
summary() {
  divider
  ok "Solid# CLI is installed and ready."
  printf "\n"
  printf "%sNext steps — pick one:%s\n" "$C_BOLD" "$C_RESET" >&2
  printf "  %ssolid clone plumber%s          # scaffold a business from a 52-industry template\n" "$C_GREEN" "$C_RESET" >&2
  printf "  %ssolid pull%s                   # pull an existing company's pages + KB locally\n" "$C_GREEN" "$C_RESET" >&2
  printf "  %ssolid demo create%s            # spin up a live demo company in 60 seconds\n" "$C_GREEN" "$C_RESET" >&2
  printf "  %ssolid ai%s                     # launch Claude Code / Cursor with this company's context\n" "$C_GREEN" "$C_RESET" >&2
  printf "\n"
  printf "Docs: %shttps://solidnumber.com/docs/cli%s\n" "$C_BLUE" "$C_RESET" >&2
  printf "\n"
}

# ─────────────────────────────────────────────────────────────────────────────
# Run
# ─────────────────────────────────────────────────────────────────────────────
main() {
  banner
  ensure_node
  ensure_cli
  run_setup
  summary
}

main "$@"
