#!/bin/sh
# Adbucks installer. On a Mac it installs the Adbucks app; in VS Code, Cursor
# and Windsurf it adds the Adbucks extension; then it signs you in once and
# connects Claude Code, Codex and Cursor. It changes only their settings files,
# after backing them up, and never patches the apps themselves.
set -eu

ADBUCKS_ORIGIN=${ADBUCKS_URL:-"https://adbucks.co"}

fail() {
  printf 'Adbucks: %s\n' "$1" >&2
  exit 1
}

command -v curl >/dev/null 2>&1 || fail "curl is required to install Adbucks."

# Adbucks runs on Node.js. Most people who are not developers do not have it,
# so when this computer has no recent Node.js, fetch the official build from
# nodejs.org, check it against the checksum nodejs.org publishes, and keep a
# private copy in ~/.adbucks/node. Nothing else on the computer is changed.
ADBUCKS_NODE_HOME=${ADBUCKS_NODE_HOME:-"$HOME/.adbucks/node"}
ADBUCKS_NODE_DIST=${ADBUCKS_NODE_DIST:-https://nodejs.org/dist/latest-v22.x}
NODE_HELP="Install Node.js 20 or newer from https://nodejs.org, then run this command again."

node_ok() {
  "$1" -e 'process.exit(Number(process.versions.node.split(".")[0]) >= 20 ? 0 : 1)' >/dev/null 2>&1
}

if command -v node >/dev/null 2>&1 && node_ok node; then
  :
elif node_ok "$ADBUCKS_NODE_HOME/bin/node"; then
  PATH="$ADBUCKS_NODE_HOME/bin:$PATH"
  export PATH
else
  case "$(uname -s)" in
    Darwin) node_os=darwin ;;
    Linux) node_os=linux ;;
    *) fail "Adbucks could not set up Node.js on this system. $NODE_HELP" ;;
  esac
  case "$(uname -m)" in
    arm64 | aarch64) node_arch=arm64 ;;
    x86_64 | amd64) node_arch=x64 ;;
    *) fail "Adbucks could not set up Node.js on this processor. $NODE_HELP" ;;
  esac
  printf 'Setting up Node.js for Adbucks (one time, about 50 MB)...\n'
  node_tmp=$(mktemp -d)
  curl -fsSL "$ADBUCKS_NODE_DIST/SHASUMS256.txt" -o "$node_tmp/SHASUMS256.txt" || fail "Could not reach nodejs.org. $NODE_HELP"
  node_entry=$(grep -- "-$node_os-$node_arch.tar.gz" "$node_tmp/SHASUMS256.txt" | sed -n 1p)
  node_sum=${node_entry%% *}
  node_file=${node_entry##* }
  [ -n "$node_entry" ] && [ -n "$node_sum" ] && [ -n "$node_file" ] || fail "Could not find Node.js for this computer. $NODE_HELP"
  curl -fsSL "$ADBUCKS_NODE_DIST/$node_file" -o "$node_tmp/$node_file" || fail "Could not download Node.js. $NODE_HELP"
  node_actual=$( (shasum -a 256 "$node_tmp/$node_file" 2>/dev/null || sha256sum "$node_tmp/$node_file") | cut -d ' ' -f 1)
  if [ "$node_actual" != "$node_sum" ]; then
    rm -rf "$node_tmp"
    fail "The Node.js download did not match the checksum nodejs.org publishes, so it was not used. $NODE_HELP"
  fi
  tar -xzf "$node_tmp/$node_file" -C "$node_tmp" || fail "Could not unpack Node.js. $NODE_HELP"
  rm -rf "$ADBUCKS_NODE_HOME"
  mkdir -p "$(dirname "$ADBUCKS_NODE_HOME")"
  mv "$node_tmp/${node_file%.tar.gz}" "$ADBUCKS_NODE_HOME"
  rm -rf "$node_tmp"
  # Adbucks needs only Node.js itself, not npm, headers or manuals.
  rm -rf "$ADBUCKS_NODE_HOME/include" "$ADBUCKS_NODE_HOME/share" "$ADBUCKS_NODE_HOME/lib/node_modules" \
    "$ADBUCKS_NODE_HOME/bin/npm" "$ADBUCKS_NODE_HOME/bin/npx" "$ADBUCKS_NODE_HOME/bin/corepack"
  node_ok "$ADBUCKS_NODE_HOME/bin/node" || fail "Node.js was downloaded but does not run here. $NODE_HELP"
  PATH="$ADBUCKS_NODE_HOME/bin:$PATH"
  export PATH
  printf '✓ Node.js ready\n'
fi

ADBUCKS_INSTALL_ROOT=${ADBUCKS_INSTALL_ROOT:-"$HOME/.adbucks/installer"}
mkdir -p "$ADBUCKS_INSTALL_ROOT/bin" "$ADBUCKS_INSTALL_ROOT/lib"

download() {
  curl -fsSL "$ADBUCKS_ORIGIN/api/adbucks/install?asset=$1" -o "$2"
}

printf 'Downloading Adbucks...\n'
download cli "$ADBUCKS_INSTALL_ROOT/bin/adbucks.mjs" || fail "Could not download Adbucks from $ADBUCKS_ORIGIN. Check your internet connection and try again."
ADBUCKS_MODULES=$(curl -fsSL "$ADBUCKS_ORIGIN/api/adbucks/install?asset=lib-list") || fail "Could not download Adbucks from $ADBUCKS_ORIGIN. Check your internet connection and try again."
for module in $ADBUCKS_MODULES; do
  case "$module" in
    *[!a-z0-9.-]*|"") fail "The server sent an unexpected file name." ;;
  esac
  download "lib&name=$module" "$ADBUCKS_INSTALL_ROOT/lib/$module" || fail "Could not download Adbucks from $ADBUCKS_ORIGIN. Check your internet connection and try again."
done
chmod 700 "$ADBUCKS_INSTALL_ROOT/bin/adbucks.mjs"

ADBUCKS_AGENT="$ADBUCKS_INSTALL_ROOT/bin/adbucks.mjs"
ADBUCKS_APP=""
ADBUCKS_OVERLAY_BINARY=""
if [ "$(uname -s)" = "Darwin" ]; then
  printf 'Installing the Adbucks Mac app...\n'
  ADBUCKS_APPS_DIR=${ADBUCKS_APPS_DIR:-/Applications}
  if [ ! -w "$ADBUCKS_APPS_DIR" ]; then
    ADBUCKS_APPS_DIR="$HOME/Applications"
    mkdir -p "$ADBUCKS_APPS_DIR"
  fi
  ADBUCKS_TMP=$(mktemp -d)
  if download app "$ADBUCKS_TMP/Adbucks.zip" && ditto -x -k "$ADBUCKS_TMP/Adbucks.zip" "$ADBUCKS_TMP/unpacked" && [ -d "$ADBUCKS_TMP/unpacked/Adbucks.app" ]; then
    # Replace a running copy cleanly: the app, its agent and its overlay.
    pkill -x Adbucks 2>/dev/null || true
    pkill -f "Adbucks.app/Contents/Resources/bin/adbucks.mjs" 2>/dev/null || true
    pkill -f "Adbucks.app/Contents/MacOS/AdbucksOverlay" 2>/dev/null || true
    rm -rf "$ADBUCKS_APPS_DIR/Adbucks.app"
    mv "$ADBUCKS_TMP/unpacked/Adbucks.app" "$ADBUCKS_APPS_DIR/Adbucks.app"
    ADBUCKS_APP="$ADBUCKS_APPS_DIR/Adbucks.app"
    ADBUCKS_AGENT="$ADBUCKS_APP/Contents/Resources/bin/adbucks.mjs"
    # The app runs Adbucks itself. A background service from an older terminal
    # install would race it for the same placements, so it goes.
    launchctl bootout "gui/$(id -u)" "$HOME/Library/LaunchAgents/com.adbucks.companion.plist" 2>/dev/null || true
    rm -f "$HOME/Library/LaunchAgents/com.adbucks.companion.plist"
    export ADBUCKS_SKIP_COMPANION=true
    printf '✓ Adbucks app installed in %s\n' "$ADBUCKS_APPS_DIR"
  else
    printf '! The Mac app could not be installed. Using the terminal version instead.\n'
    if download overlay "$ADBUCKS_INSTALL_ROOT/AdbucksOverlay"; then
      chmod 700 "$ADBUCKS_INSTALL_ROOT/AdbucksOverlay"
      ADBUCKS_OVERLAY_BINARY="$ADBUCKS_INSTALL_ROOT/AdbucksOverlay"
    else
      rm -f "$ADBUCKS_INSTALL_ROOT/AdbucksOverlay"
    fi
  fi
  rm -rf "$ADBUCKS_TMP"
fi

# VS Code based editors: their own command line tool, on the PATH or inside the app.
editor_cli() {
  if command -v "$1" >/dev/null 2>&1; then
    command -v "$1"
    return 0
  fi
  for dir in /Applications "$HOME/Applications"; do
    if [ -x "$dir/$2.app/Contents/Resources/app/bin/$1" ]; then
      printf '%s\n' "$dir/$2.app/Contents/Resources/app/bin/$1"
      return 0
    fi
  done
  return 1
}
ADBUCKS_VSIX=""
for editor in "code:Visual Studio Code" "cursor:Cursor" "windsurf:Windsurf" "codium:VSCodium"; do
  name=${editor%%:*}
  label=${editor#*:}
  cli=$(editor_cli "$name" "$label") || continue
  if [ -z "$ADBUCKS_VSIX" ]; then
    ADBUCKS_VSIX="$ADBUCKS_INSTALL_ROOT/adbucks-vscode.vsix"
    if ! download vscode "$ADBUCKS_VSIX"; then
      printf '! The editor extension could not be downloaded.\n'
      break
    fi
  fi
  if "$cli" --install-extension "$ADBUCKS_VSIX" --force >/dev/null 2>&1; then
    printf '✓ Adbucks added to %s\n' "$label"
  else
    printf '! Could not add Adbucks to %s\n' "$label"
  fi
done

export ADBUCKS_URL="$ADBUCKS_ORIGIN" ADBUCKS_OVERLAY_BINARY
# curl | sh uses stdin for this script, so give setup the real terminal when one
# exists.
if (: </dev/tty) 2>/dev/null; then
  node "$ADBUCKS_AGENT" connect all </dev/tty
else
  node "$ADBUCKS_AGENT" connect all
fi

if [ -n "$ADBUCKS_APP" ]; then
  open "$ADBUCKS_APP"
  printf '\n✓ Adbucks is in your menu bar. When macOS asks, allow Accessibility so the card can sit above your chat box.\n'
fi
if [ -n "$ADBUCKS_VSIX" ]; then
  printf '✓ Restart your editor once and it uses this same sign-in. Nothing else to click.\n'
fi
