#!/bin/sh
set -e

# hacklab installer — https://hacklab.so
err() { printf '%s\n' "$1" >&2; }

if ! command -v node >/dev/null 2>&1; then
  err "hacklab needs Node 20+ and it isn't on your PATH."
  err "Using nvm / fnm / volta? Run this in your shell instead:"
  err "  npm install -g hacklab@latest"
  exit 1
fi

NODE_MAJOR=$(node -p 'process.versions.node.split(".")[0]' 2>/dev/null || echo 0)
if [ "$NODE_MAJOR" -lt 20 ] 2>/dev/null; then
  err "hacklab needs Node 20+ (you have $(node -v))."
  err "Upgrade Node, then run: npm install -g hacklab@latest"
  exit 1
fi

if ! command -v npm >/dev/null 2>&1; then
  err "npm not found (it ships with Node). Install Node 20+, then: npm install -g hacklab@latest"
  exit 1
fi

# Is there a completed account on this machine? We read the same session file
# the CLI reads and mirror its loadSession: valid token/email/appUrl, a *handle*
# (a finished profile -- a token without one is a half-done signup that should
# still be able to finish), and not expired (explicit expiresAt, else savedAt +
# 7-day legacy TTL; an unparseable expiresAt falls back to savedAt, matching the
# CLI). node is guaranteed by the checks above.
SESSION_FILE="${HACKLAB_SESSION_PATH:-$HOME/.hacklab/session.json}"
WHO=""
if [ -f "$SESSION_FILE" ]; then
  WHO=$(node -e 'try{const fs=require("fs");const s=JSON.parse(fs.readFileSync(process.argv[process.argv.length-1],"utf8"));if(!s.token||!s.email||!s.appUrl||!s.handle)process.exit(1);const e=Date.parse(s.expiresAt);const t=Number.isNaN(e)?(s.savedAt?Date.parse(s.savedAt)+604800000:NaN):e;if(!Number.isNaN(t)&&t<=Date.now())process.exit(1);process.stdout.write("@"+s.handle)}catch{process.exit(1)}' "$SESSION_FILE" 2>/dev/null) || WHO=""
fi

# Fully set up = logged in AND the binary is actually on PATH. Only then is
# there truly nothing to do. A valid session with no binary still needs the
# install (fnm/nvm keep global npm packages per node version, so switching node
# wipes the CLI while ~/.hacklab survives; same for a home dir carried to a new
# machine) -- it just doesn't need the login. Exit 0 = success so the curl|sh
# pipe doesn't look like a failure.
if [ -n "$WHO" ] && command -v hacklab >/dev/null 2>&1; then
  err "You're already logged in as $WHO."
  err "hacklab is already set up on this machine -- nothing to install or register."
  err "To use a different account: hacklab logout && hacklab login"
  exit 0
fi

# --- Permission-safe global install (option H1) -----------------------------
# `npm i -g` writes into npm's global folder; where that's a root-owned
# /usr/local (Node's default on many systems) a normal user's install dies with
# EACCES. Rather than dump npm's raw stack trace or escalate with sudo, probe
# writability up front and, if the folder is read-only, point npm at a user-owned
# prefix — npm's own documented EACCES remedy. That change is persistent, so
# every future `npm i -g` (including `hacklab update`) just works too.
USER_PREFIX="$HOME/.npm-global"
PREFIX_RECONFIGURED=""

# Can the current user create/write inside $1? npm's target dir usually doesn't
# exist yet, so walk up to the nearest existing ancestor — mkdir succeeds iff
# that ancestor is writable.
can_write() {
  d=$1
  while [ -n "$d" ] && [ "$d" != "/" ] && [ ! -e "$d" ]; do d=$(dirname "$d"); done
  [ -w "$d" ]
}

GLOBAL_ROOT=$(npm root -g 2>/dev/null || echo "")
if [ -n "$GLOBAL_ROOT" ] && ! can_write "$GLOBAL_ROOT"; then
  err "npm's global folder isn't writable by your user ($GLOBAL_ROOT)."
  err "Pointing npm at $USER_PREFIX so no sudo is needed..."
  if npm config set prefix "$USER_PREFIX" >/dev/null 2>&1; then
    PREFIX_RECONFIGURED=1
    # Use the new bin dir for the rest of THIS run so the on-PATH check below
    # sees the fresh install; the profile edit below is only for future shells.
    PATH="$USER_PREFIX/bin:$PATH"
    export PATH
  else
    err "Couldn't set an npm prefix automatically."
    err "Install into the system location with sudo instead:"
    err "  sudo npm install -g hacklab@latest"
    exit 1
  fi
fi

# Install (or upgrade) the CLI globally so `hacklab` is a persistent command.
echo "Installing hacklab (npm i -g hacklab@latest)..."
npm install -g hacklab@latest

# If we reconfigured the prefix, make the change loud (not silent) and tell the
# user the one line to add to their profile so `hacklab` is on PATH next time.
if [ -n "$PREFIX_RECONFIGURED" ]; then
  err "Configured npm to install global packages under $USER_PREFIX."
  err "Add its bin dir to your PATH for future shells (append to ~/.profile or ~/.zshrc):"
  err "  export PATH=\"$USER_PREFIX/bin:\$PATH\""
fi

# Already logged in? Then the missing binary was the only problem -- don't
# re-run the login/registration flow against a live account.
if [ -n "$WHO" ]; then
  if command -v hacklab >/dev/null 2>&1; then
    err "Installed the hacklab CLI. You're still logged in as $WHO -- you're all set."
  else
    err "Installed the hacklab CLI, but it isn't on your PATH yet."
    err "Add npm's global bin dir to PATH (see: npm bin -g)."
    err "You're still logged in as $WHO -- once PATH is fixed you're all set."
  fi
  exit 0
fi

# Installed — now run setup, so one pasted line finishes the whole thing.
# npm's global bin dir isn't always on PATH (custom prefix, some Homebrew/nvm
# layouts) — the same `command -v` check that verifies the install also gives
# us the binary to run. Under `curl | sh` stdin is the pipe, so setup's prompts
# need the terminal handed to them explicitly; without a usable /dev/tty there
# is nobody to prompt, so print the one command to run instead.
#
# The probe OPENS /dev/tty (in a subshell, both directions) rather than testing
# its permission bits: the device node is world-read/writable and passes `test
# -r`/`-w` even where there is no controlling terminal to open (a CI runner, a
# container build, anything daemonized), and there the real redirect would die
# with ENXIO and take the whole install down with it.
if command -v hacklab >/dev/null 2>&1; then
  if (exec </dev/tty >/dev/tty) 2>/dev/null; then
    err "Installed the hacklab CLI. Starting setup..."
    hacklab setup < /dev/tty
    exit 0
  fi
  err "Installed the hacklab CLI. Verify it: type \`hacklab\` in your terminal."
  err "Next step: hacklab setup"
else
  err "Installed hacklab, but it isn't on your PATH yet."
  err "Add npm's global bin dir to PATH (see: npm bin -g), then run: hacklab setup"
fi
exit 0
