#!/bin/bash
# AI Journey beginner setup (Mac)
# https://aijourney.dustinwells.com/start
#
# Run in Ghostty:
#   /bin/bash -c "$(curl -fsSL https://aijourney.dustinwells.com/setup.sh)"
#
# Installs everything from the beginner's guide, then opens Claude Code and
# starts the setup wizard, which walks you through the logins.
# Safe to run again: anything already installed is skipped.
#
# DRY_RUN=1 shows what would happen without changing anything.
# NO_LAUNCH=1 skips opening Claude at the end.

set -u

SITE="https://aijourney.dustinwells.com"
DRY_RUN="${DRY_RUN:-0}"
NO_LAUNCH="${NO_LAUNCH:-0}"
FAILED=()

bold=$'\033[1m'; dim=$'\033[2m'; green=$'\033[32m'; yellow=$'\033[33m'; red=$'\033[31m'; reset=$'\033[0m'
step()  { printf "\n${bold}==> %s${reset}\n" "$1"; }
ok()    { printf "  ${green}✓${reset} %s\n" "$1"; }
skip()  { printf "  ${dim}✓ %s (already installed)${reset}\n" "$1"; }
warn()  { printf "  ${yellow}!${reset} %s\n" "$1"; }
fail()  { printf "  ${red}✗${reset} %s\n" "$1"; FAILED+=("$1"); }

# run "label" cmd...  (prints instead of running in dry-run mode)
run() {
  local label="$1"; shift
  if [ "$DRY_RUN" = "1" ]; then
    printf "  ${dim}would run:${reset} %s\n" "$*"
    return 0
  fi
  if "$@"; then ok "$label"; else fail "$label"; return 1; fi
}
run_soft() {  # like run, but a failure is only a note (e.g. already added)
  local label="$1"; shift
  if [ "$DRY_RUN" = "1" ]; then printf "  ${dim}would run:${reset} %s\n" "$*"; return 0; fi
  if "$@"; then ok "$label"; else skip "$label"; fi
}

has() { command -v "$1" >/dev/null 2>&1; }

add_line() {  # add_line file line  (only if missing)
  local file="$1" line="$2"
  grep -qsF "$line" "$file" && return 0
  if [ "$DRY_RUN" = "1" ]; then printf "  ${dim}would add to %s:${reset} %s\n" "$file" "$line"; return 0; fi
  printf '\n%s\n' "$line" >> "$file"
}

# ---------------------------------------------------------------- preflight

if [ "$(uname -s)" != "Darwin" ]; then
  echo "This script is for Macs. For Linux or a VPS, follow $SITE/start/vps"
  exit 1
fi

if ! groups | grep -qw admin; then
  echo "Your Mac user isn't an administrator, so it can't install apps."
  echo "Log in as an admin user (System Settings → Users & Groups) and run this again."
  exit 1
fi

free_gb=$(df -g "$HOME" | awk 'NR==2 {print $4}')

cat <<EOF

${bold}AI Journey setup${reset}

This installs the tools from the beginner's guide:
  Homebrew, Node, git, GitHub CLI, Claude Code, the Claude and
  1Password apps, Granola, Vercel and Supabase CLIs, a browser your
  agents can drive, and the recommended skills and plugins.

Then it opens Claude, which walks you through the logins.

  • Takes about 15–20 minutes, mostly waiting
  • You'll type your Mac password once
  • Free disk space: ${free_gb} GB (50 GB recommended)

EOF

if [ "${free_gb:-0}" -lt 25 ]; then
  warn "Less than 25 GB free. Setup may fail. Free up space first if you can."
fi

if [ "$DRY_RUN" != "1" ]; then
  read -r -p "Press Enter to start (or Ctrl+C to cancel) " _ </dev/tty
  echo
  echo "Enter your Mac login password (nothing shows as you type):"
  sudo -v </dev/tty || { echo "Couldn't get admin access. Stopping."; exit 1; }
  # keep sudo alive until this script ends
  while true; do sudo -n true; sleep 50; kill -0 "$$" 2>/dev/null || exit; done 2>/dev/null &
fi

# ---------------------------------------------------------------- homebrew

step "Homebrew (installs everything else)"
if [ -x /opt/homebrew/bin/brew ]; then BREW=/opt/homebrew/bin/brew
elif [ -x /usr/local/bin/brew ]; then BREW=/usr/local/bin/brew
else BREW=""; fi

if [ -n "$BREW" ]; then
  skip "Homebrew"
else
  echo "  This also installs Apple's developer tools. It's the slowest step."
  run "Homebrew" env NONINTERACTIVE=1 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
  if [ -x /opt/homebrew/bin/brew ]; then BREW=/opt/homebrew/bin/brew; else BREW=/usr/local/bin/brew; fi
fi

if [ -x "$BREW" ]; then
  eval "$("$BREW" shellenv)"
  add_line "$HOME/.zprofile" "eval \"\$($BREW shellenv)\""
elif [ "$DRY_RUN" != "1" ]; then
  echo "Homebrew didn't install, so nothing else can. Scroll up for the error,"
  echo "or ask for help with a screenshot of this window."
  exit 1
fi

# ---------------------------------------------------------------- apps

step "Apps"
cask() {  # cask <cask-name> <App Name>
  if [ -d "/Applications/$2.app" ] || [ -d "$HOME/Applications/$2.app" ]; then skip "$2"
  else run "$2" brew install --cask "$1"; fi
}
cask ghostty   Ghostty
cask 1password 1Password
cask claude    Claude
cask granola   Granola

# ---------------------------------------------------------------- command-line tools

step "Command-line tools"
formula() {  # formula <formula> <command> <label>
  if has "$2"; then skip "$3"; else run "$3" brew install "$1"; fi
}
formula git git "git"
formula gh gh "GitHub CLI (gh)"
formula node node "Node.js + npm"
formula supabase/tap/supabase supabase "Supabase CLI"
if has op; then skip "1Password CLI (op)"; else run "1Password CLI (op)" brew install --cask 1password-cli; fi

mkdir -p "$HOME/projects"

# ---------------------------------------------------------------- claude code

step "Claude Code"
export PATH="$HOME/.local/bin:$PATH"
add_line "$HOME/.zshrc" 'export PATH="$HOME/.local/bin:$PATH"'
if has claude; then
  skip "Claude Code"
else
  run "Claude Code" /bin/bash -c "curl -fsSL https://claude.ai/install.sh | bash"
fi

# ---------------------------------------------------------------- npm tools

step "Deploy and browser tools"
if has vercel; then skip "Vercel CLI"; else run "Vercel CLI" npm install -g vercel; fi
if has agent-browser; then
  skip "agent-browser"
else
  run "agent-browser" npm install -g agent-browser && run "Browser for agent-browser" agent-browser install
fi

# ---------------------------------------------------------------- skills + plugins

step "Skills and plugins"
SKILLS="$HOME/.claude/skills"
skill_installed() { [ -e "$SKILLS/$1" ]; }

if skill_installed grill-me && skill_installed tdd && skill_installed improve-codebase-architecture; then
  skip "grill-me, tdd, improve-codebase-architecture"
else
  run "grill-me, tdd, improve-codebase-architecture" \
    npx -y skills@latest add mattpocock/skills -g -a claude-code -y -s grill-me tdd improve-codebase-architecture </dev/null
fi
if skill_installed create-skill && skill_installed evolve; then
  skip "Evolving Skills (create-skill, evolve)"
else
  run "Evolving Skills (create-skill, evolve)" \
    npx -y skills@latest add https://github.com/dodo-digital/evolving-skills/tree/main/plugins/evolving-skills/claude-skills -g -a claude-code -y </dev/null
fi
if skill_installed agent-browser; then
  skip "agent-browser skill"
else
  run "agent-browser skill" npx -y skills@latest add vercel-labs/agent-browser -g -a claude-code -y </dev/null
fi

# The setup wizard itself (always refreshed so you get the latest version)
if [ "$DRY_RUN" = "1" ]; then
  printf "  ${dim}would download:${reset} %s/setup-wizard/SKILL.md\n" "$SITE"
else
  mkdir -p "$SKILLS/setup-wizard"
  if curl -fsSL "$SITE/setup-wizard/SKILL.md" -o "$SKILLS/setup-wizard/SKILL.md"; then ok "setup-wizard skill"
  else fail "setup-wizard skill"; fi
fi

if has claude; then
  installed_plugins="$(claude plugin list 2>/dev/null || true)"
  quiet() { "$@" </dev/null >/dev/null 2>&1; }
  marketplace() { run_soft "plugin source: $1" quiet claude plugin marketplace add "$1"; }
  plugin() {  # plugin <name@marketplace>
    if printf '%s' "$installed_plugins" | grep -q "${1%@*}@"; then skip "plugin: ${1%@*}"
    else run "plugin: ${1%@*}" quiet claude plugin install "$1" -s user; fi
  }
  marketplace anthropics/claude-plugins-official
  marketplace EveryInc/compound-engineering-plugin
  plugin github@claude-plugins-official
  plugin vercel@claude-plugins-official
  plugin supabase@claude-plugins-official
  plugin stripe@claude-plugins-official
  plugin compound-engineering@compound-engineering-plugin
elif [ "$DRY_RUN" = "1" ]; then
  printf "  ${dim}would install plugins:${reset} github vercel supabase stripe compound-engineering\n"
fi

# ---------------------------------------------------------------- done

step "Done installing"
if [ ${#FAILED[@]} -gt 0 ]; then
  warn "These didn't install. The wizard will help you fix them:"
  for f in "${FAILED[@]}"; do echo "    - $f"; done
  mkdir -p "$HOME/.claude"
  printf '%s\n' "${FAILED[@]}" > "$HOME/.claude/setup-failed.txt"
else
  rm -f "$HOME/.claude/setup-failed.txt"
  ok "Everything installed"
fi

if [ "$DRY_RUN" = "1" ] || [ "$NO_LAUNCH" = "1" ]; then
  echo
  echo "To start the wizard: cd ~/projects && claude \"/setup-wizard\""
  exit 0
fi

if ! has claude; then
  echo
  echo "Claude Code didn't install, so the wizard can't start."
  echo "Close Ghostty, open it again, and run this same command once more."
  exit 1
fi

cat <<EOF

${bold}Next: Claude opens and walks you through the rest.${reset}
  1. Pick a color theme
  2. Choose "Claude account with subscription" and log in in your browser
  3. When it asks whether to trust the ~/projects folder, say yes
Then the setup wizard starts on its own.

EOF
read -r -p "Press Enter to open Claude " _ </dev/tty
cd "$HOME/projects" && exec claude "/setup-wizard" </dev/tty
