#!/usr/bin/env bash
#
# BitPub installer.
#
# This script installs the open-source `@bitpub/cli` Node package globally
# and provisions a local + cloud identity. Source for both this script and
# the CLI is at https://github.com/tollbit/bitpub.
#
# === Want to verify before running? ===
#   1. Read it first:   curl -fsSL https://bitpub.io/install.sh | less
#   2. Or skip the script entirely — these two commands do the same thing:
#         npm install -g @bitpub/cli
#         bitpub setup
#
# === Usage ===
#   curl -fsSL https://bitpub.io/install.sh | bash
#   curl -fsSL https://bitpub.io/install.sh | bash -s -- --local-only
#   curl -fsSL https://bitpub.io/install.sh | bash -s -- --url http://localhost:8080
#
# === What this script does (exhaustively) ===
#   1. Verifies that `node` and `npm` are available on PATH.
#   2. Downloads the CLI tarball from $BITPUB_TARBALL_URL (default:
#      https://bitpub.io/cli/latest.tgz — same content as `@bitpub/cli` on npm).
#   3. Runs `npm install -g <tarball>`. If global install lacks permissions,
#      writes an `npx` wrapper to ~/.local/bin instead (no sudo).
#   4. Runs `bitpub setup` to create ~/.bitpub/config.json, provision a
#      private cloud namespace against $BITPUB_CLOUD_URL, install the agent
#      skill, save a Welcome slice, and (in interactive shells) open
#      http://localhost:4141 so you can confirm it worked.
#
# === Network access ===
#   This script only contacts $BITPUB_TARBALL_URL (to download the CLI) and
#   $BITPUB_CLOUD_URL (to provision your identity). It does not phone home
#   anywhere else, modify shell rc files beyond appending ~/.local/bin to
#   PATH if needed, or write anything inside the current working directory.
#
# === Environment overrides (useful for development / staging) ===
#   BITPUB_CLOUD_URL    cloud tenant for identity provisioning
#                        (default: https://bitpub.io)
#   BITPUB_TARBALL_URL  URL of the .tgz to install
#                        (default: $BITPUB_CLOUD_URL/cli/latest.tgz)
#   BITPUB_SKIP_WELCOME 1 to skip the post-install browser open
#
# === Forwarded flags (everything after `bash -s --`) ===
#   --local-only         skip cloud provisioning (local store only)
#   --force              overwrite an existing identity
#   --url <URL>          override the cloud tenant for this run

set -euo pipefail

BITPUB_CLOUD_URL="${BITPUB_CLOUD_URL:-https://bitpub.io}"
BITPUB_TARBALL_URL="${BITPUB_TARBALL_URL:-${BITPUB_CLOUD_URL}/cli/latest.tgz}"

INIT_FLAGS=()
HAS_LOCAL_ONLY=0
while [ $# -gt 0 ]; do
  case "$1" in
    --local-only)         HAS_LOCAL_ONLY=1; INIT_FLAGS+=("$1"); shift ;;
    --force)              INIT_FLAGS+=("$1"); shift ;;
    --url)                INIT_FLAGS+=("$1" "$2"); shift 2 ;;
    --url=*)              INIT_FLAGS+=("$1"); shift ;;
    *)
      echo "Unknown flag: $1" >&2
      echo "Supported flags: --local-only, --force, --url <URL>" >&2
      exit 2
      ;;
  esac
done

step() { printf '\n\033[1m▸ %s\033[0m\n' "$1"; }
ok()   { printf '  \033[32m✓\033[0m %s\n' "$1"; }
fail() { printf '  \033[31m✗\033[0m %s\n' "$1" >&2; exit 1; }

# Self-identifying banner so the script is recognisable in logs and screen
# recordings (and obvious if someone tries to ship a tampered installer).
printf '\033[1mBitPub installer\033[0m  ·  source: https://github.com/tollbit/bitpub\n'
printf '  Will install @bitpub/cli from %s\n' "$BITPUB_TARBALL_URL"
printf '  Will provision a private identity against %s\n' "$BITPUB_CLOUD_URL"
printf '  (Equivalent to: npm install -g @bitpub/cli && bitpub setup)\n'

# ── 1. Pre-flight ────────────────────────────────────────────────────────────
step "Checking prerequisites"

command -v node >/dev/null 2>&1 || fail "node is required (https://nodejs.org). Install it and re-run."
command -v npm  >/dev/null 2>&1 || fail "npm is required (ships with node). Install it and re-run."
ok "node $(node --version) / npm $(npm --version)"

# ── 2. Download + install the CLI ────────────────────────────────────────────
step "Installing BitPub CLI"

TMPDIR_OUT="$(mktemp -d)"
trap 'rm -rf "$TMPDIR_OUT"' EXIT
TARBALL_PATH="$TMPDIR_OUT/bitpub-cli.tgz"

if command -v curl >/dev/null 2>&1; then
  curl -fsSL "$BITPUB_TARBALL_URL" -o "$TARBALL_PATH" || fail "failed to download $BITPUB_TARBALL_URL"
elif command -v wget >/dev/null 2>&1; then
  wget -q "$BITPUB_TARBALL_URL" -O "$TARBALL_PATH" || fail "failed to download $BITPUB_TARBALL_URL"
else
  fail "neither curl nor wget is available"
fi
ok "downloaded $BITPUB_TARBALL_URL"

if INSTALL_ERR="$(npm install -g "$TARBALL_PATH" 2>&1)"; then
  ok "installed globally"
elif echo "$INSTALL_ERR" | grep -qiE "EACCES|permission denied"; then
  # Global install needs elevated permissions — write an npx wrapper to
  # ~/.local/bin instead. npx caches the package after the first run so
  # subsequent calls are fast. No sudo required.
  printf '  \033[33m!\033[0m global npm install needs write access — using ~/.local/bin wrapper instead\n'
  WRAPPER_DIR="$HOME/.local/bin"
  mkdir -p "$WRAPPER_DIR"
  printf '#!/usr/bin/env sh\nexec npx --yes "%s" "$@"\n' "$BITPUB_TARBALL_URL" > "$WRAPPER_DIR/bitpub"
  chmod +x "$WRAPPER_DIR/bitpub"
  export PATH="$WRAPPER_DIR:$PATH"
  # Persist to the first shell profile found.
  for _rc in "$HOME/.zshrc" "$HOME/.bashrc" "$HOME/.profile"; do
    if [ -f "$_rc" ] && ! grep -qF '.local/bin' "$_rc" 2>/dev/null; then
      printf '\nexport PATH="$HOME/.local/bin:$PATH"  # added by bitpub installer\n' >> "$_rc"
      ok "added ~/.local/bin to PATH in $(basename "$_rc") — new terminals will pick this up"
      break
    fi
  done
  ok "installed → $WRAPPER_DIR/bitpub (runs via npx)"
else
  fail "npm install -g failed: $INSTALL_ERR"
fi

command -v bitpub >/dev/null 2>&1 || fail "bitpub not found on PATH — open a new terminal and re-run, or add ~/.local/bin to your PATH"
ok "bitpub binary on PATH"

# ── 3. Identity + skill + welcome via `bitpub setup` ────────────────────────
# `bitpub setup` does identity provision + project anchor + skill install,
# then (on a fresh install in an interactive shell) saves a Welcome slice
# and spawns the browser UI detached so the install script exits cleanly.
# The browser-open is gated inside setup on:
#   - --local-only          (no cloud identity to write to)
#   - --no-welcome          (explicit opt-out)
#   - BITPUB_SKIP_WELCOME=1
#   - non-TTY stdout        (CI, headless agents w/o a pty)
# We just pass our flags through and let setup decide. Same logic, one place.
step "Setting up local store + cloud namespace"

# If the user didn't pass --url, default to BITPUB_CLOUD_URL.
HAS_URL_FLAG=0
for arg in "${INIT_FLAGS[@]:-}"; do
  case "$arg" in --url|--url=*) HAS_URL_FLAG=1 ;; esac
done
if [ "$HAS_URL_FLAG" -eq 0 ]; then
  INIT_FLAGS=(--url "$BITPUB_CLOUD_URL" "${INIT_FLAGS[@]:-}")
fi

bitpub setup "${INIT_FLAGS[@]}" || fail "bitpub setup failed"

printf '\n\033[1mBitPub ready.\033[0m  Try: bitpub list\n'
