#!/bin/bash
# DoFollow — the brain, as something you double-click.
#
# The download stays small by NOT carrying a 113 MB runtime: if this Mac already has a
# usable Node it uses that, and if it does not it fetches the official one once, into
# Application Support. Everything else — the token, the data, the Claude login — is the
# same either way, and none of it needs a terminal.
set -u
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"          # …/Contents
RES="$HERE/Resources"
DATA="$HOME/Library/Application Support/DoFollow"
LOG="$DATA/dofollow.log"
NODE_VERSION="v22.11.0"
mkdir -p "$DATA"

# Every message wears the DoFollow icon. A notification sent from a script always shows
# Script Editor's icon instead — macOS files it under osascript, not under this app — so
# DoFollow speaks in small dialogs, which take the icon we give them, and says little.
ICON="with icon note"
[ -f "$RES/DoFollow.icns" ] && ICON="with icon (POSIX file \"$RES/DoFollow.icns\")"
note() { /usr/bin/osascript -e "display dialog \"$1\" with title \"DoFollow\" buttons {\"OK\"} default button 1 giving up after 6 $ICON" >/dev/null 2>&1 & }
ask()  { /usr/bin/osascript -e "display dialog \"$1\" with title \"DoFollow\" buttons {\"$3\", \"$2\"} default button \"$2\" $ICON" 2>/dev/null | grep -q "button returned:$2"; }
fail() { /usr/bin/osascript -e "display dialog \"$1\" with title \"DoFollow\" buttons {\"OK\"} default button 1 $ICON" >/dev/null 2>&1; exit 1; }

export PATH="$HOME/.local/bin:/opt/homebrew/bin:/usr/local/bin:$PATH"

# 1. A runtime. Whatever is already here, if it is new enough.
usable() { [ -x "$1" ] && [ "$("$1" -e 'process.stdout.write(String(process.versions.node.split(".")[0]))' 2>/dev/null || echo 0)" -ge 20 ]; }
NODE=""
for candidate in "$DATA/runtime/bin/node" "$(command -v node || true)"; do
  if usable "$candidate"; then NODE="$candidate"; break; fi
done

if [ -z "$NODE" ]; then
  note "Getting the runtime — about 40 MB, once."
  ARCH="$(uname -m)"; [ "$ARCH" = "x86_64" ] && ARCH="x64"
  TARBALL="node-$NODE_VERSION-darwin-$ARCH"
  if /usr/bin/curl -fsSL "https://nodejs.org/dist/$NODE_VERSION/$TARBALL.tar.gz" -o "$DATA/node.tar.gz" 2>>"$LOG" &&
     /usr/bin/tar -xzf "$DATA/node.tar.gz" -C "$DATA" "$TARBALL/bin/node" 2>>"$LOG"; then
    mkdir -p "$DATA/runtime/bin"
    mv "$DATA/$TARBALL/bin/node" "$DATA/runtime/bin/node"
    rm -rf "$DATA/$TARBALL" "$DATA/node.tar.gz"
    NODE="$DATA/runtime/bin/node"
  else
    fail "DoFollow could not download its runtime. Check your connection and open it again."
  fi
fi

# 2. Claude Code, which is where the Claude login lives. Offered, never silent.
if ! command -v claude >/dev/null 2>&1; then
  if ask "DoFollow needs Claude Code — that is what holds your Claude login.\n\nInstall it now from claude.ai? It takes about a minute." "Install" "Not now"; then
    note "Installing Claude Code…"
    if /bin/bash -c "curl -fsSL https://claude.ai/install.sh | bash" >> "$LOG" 2>&1; then
      export PATH="$HOME/.local/bin:$PATH"
      note "Claude Code installed."
    else
      /usr/bin/osascript -e "display dialog \"Could not install Claude Code automatically.\n\nInstall it from claude.com/code, then open DoFollow again.\" with title \"DoFollow\" buttons {\"Open claude.com/code\",\"OK\"} default button 1 $ICON" \
        -e 'if button returned of result is "Open claude.com/code" then open location "https://claude.com/code"' >/dev/null 2>&1
    fi
  fi
fi

# 3. A token nobody has to see, handed to the extension only when it proves it is one.
if [ ! -s "$DATA/token" ]; then
  "$NODE" -e 'process.stdout.write(require("crypto").randomBytes(24).toString("hex"))' > "$DATA/token"
fi
export FORMFILLER_TOKEN="$(cat "$DATA/token")"
export FORMFILLER_DATA_DIR="$DATA"
# Its own port range, found by the server: 8787 is often taken by other dev tools.
export PORT=auto

# Already running THIS version: nothing to do. An older one (a friend who dragged the new
# app over the old): carry on — the server stops the old copy and takes over its port.
MINE="$(/usr/bin/grep -o '"version": *"[^"]*"' "$RES/server/package.json" | /usr/bin/grep -o '[0-9][0-9.]*')"
for port in 38787 38788 38789 38790 38791; do
  PING="$(/usr/bin/curl -s -m 1 "http://127.0.0.1:$port/ping" 2>/dev/null)"
  if echo "$PING" | grep -q '"service":"dofollow"'; then
    if echo "$PING" | grep -q "\"version\":\"$MINE\"" && echo "$PING" | grep -q '"updates":true'; then
      note "Already running — open the extension."
      exit 0
    fi
    break
  fi
done

# Said once, the first time. After that DoFollow starts quietly: it is a background
# helper, and "open the extension and log in" is wrong advice to someone already set up.
if [ ! -f "$DATA/.welcomed" ]; then
  note "DoFollow is running in the background.\n\nOpen the DoFollow extension in Chrome — Setup connects your Claude account in one click."
  touch "$DATA/.welcomed"
fi
cd "$RES/server"
exec "$NODE" src/index.js >> "$LOG" 2>&1
