#!/bin/bash
# AimClear BigQuery MCP — Mac setup script
# Run this once on a marketer's Mac. Installs Homebrew (if needed), gcloud CLI,
# the toolbox binary, registers the MCP additively in Claude Code and Claude
# Desktop user-scope config files, and authenticates to Google.
#
# Run as your normal user — do NOT use sudo. Homebrew handles its own password
# prompts when needed.
#
# Usage:
#   ./marketer-pipeline-setup-mac.sh                    # run all phases
#   ./marketer-pipeline-setup-mac.sh --skip-to install  # resume after a failed install
#   ./marketer-pipeline-setup-mac.sh --skip-to auth     # only (re)run gcloud auth
#
# Phases: download → install → configure → auth
# Exit codes: 0=ok, 10=download failed, 20=install failed, 30=configure failed, 40=auth failed.
# A phase marker line "[PHASE: <name>]" is printed at the start of each phase so
# an orchestrator (e.g. a Claude Code plugin) can track progress and resume.

set -euo pipefail

TOOLBOX_VERSION="v0.32.0"
TOOLBOX_DIR="$HOME/bin"
BIGQUERY_PROJECT="marty-search-console-ga4-api"   # pinned billing project for the pilot — see design doc
export HOMEBREW_NO_AUTO_UPDATE=1                  # prevent brew from auto-updating mid-script

# ── Argument parsing ─────────────────────────────────────────────────────────
SKIP_TO=""
while [[ $# -gt 0 ]]; do
  case "$1" in
    --skip-to)
      SKIP_TO="${2:-}"
      shift 2
      ;;
    --skip-to=*)
      SKIP_TO="${1#--skip-to=}"
      shift
      ;;
    -h|--help)
      sed -n '2,18p' "$0"
      exit 0
      ;;
    *)
      echo "ERROR: Unknown argument: $1" >&2
      echo "Usage: $0 [--skip-to download|install|configure|auth]" >&2
      exit 1
      ;;
  esac
done

# ── Phase framework ──────────────────────────────────────────────────────────
# bash 3.2 compatible (macOS default) — no associative arrays.
phase_order() {
  case "$1" in
    download)  echo 1 ;;
    install)   echo 2 ;;
    configure) echo 3 ;;
    auth)      echo 4 ;;
    *)         echo 0 ;;
  esac
}

phase_exit_code() {
  case "$1" in
    download)  echo 10 ;;
    install)   echo 20 ;;
    configure) echo 30 ;;
    auth)      echo 40 ;;
    *)         echo 1 ;;
  esac
}

START_PHASE="${SKIP_TO:-download}"
START_ORDER=$(phase_order "$START_PHASE")
if [[ "$START_ORDER" == "0" ]]; then
  echo "ERROR: Invalid --skip-to value: '$START_PHASE'" >&2
  echo "Valid phases: download, install, configure, auth" >&2
  exit 1
fi

should_run_phase() {
  local order
  order=$(phase_order "$1")
  [[ "$order" -ge "$START_ORDER" ]]
}

CURRENT_PHASE=""
on_exit() {
  local rc=$?
  if [[ $rc -ne 0 && -n "$CURRENT_PHASE" ]]; then
    echo "[PHASE_FAILED: $CURRENT_PHASE]" >&2
    exit "$(phase_exit_code "$CURRENT_PHASE")"
  fi
}
trap on_exit EXIT

# ── Preflight (always runs, regardless of --skip-to) ─────────────────────────
echo "=== AimClear BigQuery MCP Setup ==="
if [[ -n "$SKIP_TO" ]]; then
  echo "Resuming from phase: $SKIP_TO"
fi
echo ""

# Refuse to run as root — Homebrew won't install with EUID 0, and the script
# handles its own admin prompts when needed.
if [[ $EUID -eq 0 ]]; then
  echo "ERROR: Do NOT run this script with sudo." >&2
  echo "Run it as your normal user — Homebrew handles its own password prompts." >&2
  exit 1
fi

# Warn if neither Claude Code nor Claude Desktop is installed
CLAUDE_CODE_FOUND=false
CLAUDE_DESKTOP_FOUND=false
if command -v claude &>/dev/null; then CLAUDE_CODE_FOUND=true; fi
if [[ -d "/Applications/Claude.app" ]] || [[ -d "$HOME/Applications/Claude.app" ]]; then CLAUDE_DESKTOP_FOUND=true; fi

if ! $CLAUDE_CODE_FOUND && ! $CLAUDE_DESKTOP_FOUND; then
  echo "WARNING: Neither Claude Code nor Claude Desktop was found on this machine."
  echo "Download and install Claude before completing setup: https://claude.ai/download"
  echo "This script will continue and configure everything — Claude will pick it up once installed."
  echo ""
  read -rp "Press Enter to continue, or Ctrl+C to exit and install Claude first: "
  echo ""
fi

# ── Phase: download ──────────────────────────────────────────────────────────
# Pre-stage the toolbox binary before doing anything that could fail. On Mac
# there's nothing else to download up front — Homebrew handles gcloud's
# download+install as one atomic step in the install phase.
if should_run_phase download; then
  CURRENT_PHASE=download
  echo "[PHASE: download]"

  ARCH=$(uname -m)
  # Detect Rosetta — sysctl.proc_translated returns 1 if running translated.
  # In that case, prefer the native arm64 binary.
  if [[ $(sysctl -n sysctl.proc_translated 2>/dev/null) == "1" ]]; then
    ARCH="arm64"
  fi

  if [[ "$ARCH" == "arm64" ]]; then
    PLATFORM="darwin/arm64"
  else
    PLATFORM="darwin/amd64"
  fi

  TOOLBOX_URL="https://storage.googleapis.com/genai-toolbox/$TOOLBOX_VERSION/$PLATFORM/toolbox"

  mkdir -p "$TOOLBOX_DIR"
  if [[ -f "$TOOLBOX_DIR/toolbox" ]]; then
    echo "✓ toolbox already installed: $("$TOOLBOX_DIR/toolbox" --version 2>/dev/null || echo 'unknown')"
  else
    echo "Downloading toolbox ($PLATFORM)..."
    curl -fsSL -o "$TOOLBOX_DIR/toolbox" "$TOOLBOX_URL"
    chmod +x "$TOOLBOX_DIR/toolbox"
    xattr -d com.apple.quarantine "$TOOLBOX_DIR/toolbox" 2>/dev/null || true

    # Trigger any Gatekeeper notarization dialog now while the marketer is at
    # the keyboard, rather than later from inside Claude (where the dialog
    # would be invisible).
    "$TOOLBOX_DIR/toolbox" --version &>/dev/null || true

    echo "✓ toolbox installed: $("$TOOLBOX_DIR/toolbox" --version 2>/dev/null || echo 'unknown')"
  fi
fi

export PATH="$TOOLBOX_DIR:$PATH"

# ── Phase: install ───────────────────────────────────────────────────────────
# Homebrew (if needed) and gcloud CLI via Homebrew. This is the phase most
# likely to fail interactively — sudo password, license prompts, network.
if should_run_phase install; then
  CURRENT_PHASE=install
  echo ""
  echo "[PHASE: install]"

  # Homebrew
  if command -v brew &>/dev/null; then
    echo "✓ Homebrew already installed: $(brew --version 2>/dev/null | head -1 || echo 'unknown')"
  else
    echo "Installing Homebrew..."
    echo "(Homebrew will ask you to press Enter to confirm, then prompt for your Mac password — both are normal)"
    /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

    # Make brew available for the rest of this script.
    if [[ -f /opt/homebrew/bin/brew ]]; then
      eval "$(/opt/homebrew/bin/brew shellenv)"   # Apple Silicon (M-series)
    elif [[ -f /usr/local/bin/brew ]]; then
      eval "$(/usr/local/bin/brew shellenv)"       # Intel Mac
    fi

    echo "✓ Homebrew installed"
  fi

  if ! command -v brew &>/dev/null; then
    echo "ERROR: Homebrew was installed but 'brew' is still not on PATH." >&2
    echo "Try opening a new Terminal window and re-running this script." >&2
    exit 1   # trap maps this to 20
  fi

  # Claude Code CLI (Anthropic native installer — no Node dependency, auto-updates).
  if command -v claude &>/dev/null; then
    echo "✓ Claude Code already installed: $(claude --version 2>/dev/null | head -1 || echo 'unknown')"
  else
    echo "Installing Claude Code via the official Anthropic installer..."
    curl -fsSL https://claude.ai/install.sh | bash
    # Installer drops the binary at ~/.local/bin/claude — make sure it's on PATH for this script
    export PATH="$HOME/.local/bin:$PATH"
    hash -r 2>/dev/null || true
    if command -v claude &>/dev/null; then
      echo "✓ Claude Code installed: $(claude --version 2>/dev/null | head -1 || echo 'unknown')"
    else
      echo "WARNING: Claude Code installer ran but 'claude' is not on PATH within this script." >&2
      echo "  Open a new Terminal window after setup completes to use the 'claude' command." >&2
    fi
  fi

  # gcloud CLI
  if command -v gcloud &>/dev/null; then
    # `|| echo unknown` guards against pyenv-shim conflicts that crash gcloud --version
    echo "✓ gcloud already installed: $(gcloud --version 2>/dev/null | head -1 || echo 'unknown')"
  else
    # Pre-check: brew can be installed at a prefix owned by a different user
    # (common when Macs are pre-imaged or handed down between users). If so,
    # `brew install` produces a wall of "not writable" errors that scroll the
    # actionable remediation off-screen. Fail early with a clean message.
    BREW_PREFIX=$(brew --prefix)
    if [[ ! -w "$BREW_PREFIX/Cellar" ]] || [[ ! -w "$BREW_PREFIX/bin" ]]; then
      echo "" >&2
      echo "ERROR: Homebrew is installed at $BREW_PREFIX, but its directories are not" >&2
      echo "       owned by your user account. This usually means the Mac was previously" >&2
      echo "       set up under a different user." >&2
      echo "" >&2
      echo "To fix:" >&2
      echo "  1. Open the Self Service app → Admin on Demand (give yourself temporary admin)" >&2
      echo "  2. In Terminal, run:" >&2
      echo "       sudo chown -R \$(whoami) $BREW_PREFIX" >&2
      echo "  3. Re-run this script with:" >&2
      echo "       $0 --skip-to install" >&2
      echo "" >&2
      exit 1   # trap maps this to 20
    fi

    echo "Installing Google Cloud CLI via Homebrew..."
    echo "(brew may prompt for your Mac password — this is normal)"
    brew install --cask google-cloud-sdk

    # Refresh PATH aggressively — brew cask installs can land in spots
    # neither `brew shellenv` nor `path.bash.inc` alone reliably surfaces,
    # and bash caches negative command lookups in its hash table.
    if [[ -f /opt/homebrew/bin/brew ]]; then
      eval "$(/opt/homebrew/bin/brew shellenv)"
    elif [[ -f /usr/local/bin/brew ]]; then
      eval "$(/usr/local/bin/brew shellenv)"
    fi
    source "$(brew --prefix)/share/google-cloud-sdk/path.bash.inc" 2>/dev/null || true
    source "$(brew --prefix)/share/google-cloud-sdk/path.zsh.inc"  2>/dev/null || true
    hash -r 2>/dev/null || true

    # Last-resort: hunt for gcloud under Caskroom paths and prepend to PATH
    if ! command -v gcloud &>/dev/null; then
      for d in \
          "$(brew --prefix)/Caskroom/google-cloud-sdk/latest/google-cloud-sdk/bin" \
          "/opt/homebrew/Caskroom/google-cloud-sdk/latest/google-cloud-sdk/bin" \
          "/usr/local/Caskroom/google-cloud-sdk/latest/google-cloud-sdk/bin"; do
        if [[ -x "$d/gcloud" ]]; then
          export PATH="$d:$PATH"
          break
        fi
      done
    fi

    if ! command -v gcloud &>/dev/null; then
      echo "ERROR: gcloud was installed but cannot be found on PATH within this script." >&2
      echo "Quit Terminal, open a new window, and re-run with: --skip-to install" >&2
      exit 1   # trap maps this to 20
    fi

    echo "✓ gcloud installed: $(gcloud --version 2>/dev/null | head -1 || echo 'unknown')"
  fi
fi

# ── Phase: configure ─────────────────────────────────────────────────────────
# Write MCP entries into both Claude Code and Claude Desktop user-scope configs.
# Additive — preserves any existing MCP servers the marketer has.
if should_run_phase configure; then
  CURRENT_PHASE=configure
  echo ""
  echo "[PHASE: configure]"

  TOOLBOX_PATH="$TOOLBOX_DIR/toolbox"
  if [[ ! -x "$TOOLBOX_PATH" ]]; then
    echo "ERROR: toolbox binary not found at $TOOLBOX_PATH — run download phase first." >&2
    exit 1   # trap maps this to 30
  fi

  # Claude Code (~/.claude.json)
  CLAUDE_CODE_CONFIG="$HOME/.claude.json"
  echo "Registering BigQuery MCP in Claude Code..."

  TOOLBOX_PATH="$TOOLBOX_PATH" \
  CONFIG_PATH="$CLAUDE_CODE_CONFIG" \
  BQ_PROJECT="$BIGQUERY_PROJECT" \
  python3 - <<'PY'
import json, os
path = os.environ["CONFIG_PATH"]
config = {}
if os.path.exists(path):
    try:
        with open(path) as f:
            config = json.load(f)
    except json.JSONDecodeError:
        pass
config.setdefault("mcpServers", {})
config["mcpServers"]["bigquery"] = {
    "type": "stdio",
    "command": os.environ["TOOLBOX_PATH"],
    "args": ["--prebuilt", "bigquery", "--stdio"],
    "env": {"BIGQUERY_PROJECT": os.environ["BQ_PROJECT"]}
}
with open(path, "w") as f:
    json.dump(config, f, indent=2)
PY
  echo "✓ Claude Code config updated at $CLAUDE_CODE_CONFIG"

  # Claude Desktop (if installed)
  CLAUDE_DESKTOP_CONFIG="$HOME/Library/Application Support/Claude/claude_desktop_config.json"
  if [[ -d "/Applications/Claude.app" ]] || [[ -d "$HOME/Applications/Claude.app" ]]; then
    mkdir -p "$(dirname "$CLAUDE_DESKTOP_CONFIG")"
    echo "Registering BigQuery MCP in Claude Desktop..."

    TOOLBOX_PATH="$TOOLBOX_PATH" \
    CONFIG_PATH="$CLAUDE_DESKTOP_CONFIG" \
    BQ_PROJECT="$BIGQUERY_PROJECT" \
    python3 - <<'PY'
import json, os
path = os.environ["CONFIG_PATH"]
config = {}
if os.path.exists(path):
    try:
        with open(path) as f:
            config = json.load(f)
    except json.JSONDecodeError:
        pass
config.setdefault("mcpServers", {})
config["mcpServers"]["bigquery"] = {
    "command": os.environ["TOOLBOX_PATH"],
    "args": ["--prebuilt", "bigquery", "--stdio"],
    "env": {"BIGQUERY_PROJECT": os.environ["BQ_PROJECT"]}
}
with open(path, "w") as f:
    json.dump(config, f, indent=2)
PY
    echo "✓ Claude Desktop config updated at $CLAUDE_DESKTOP_CONFIG"
  else
    echo "— Claude Desktop not found, skipping Desktop config"
  fi
fi

# ── Phase: auth ──────────────────────────────────────────────────────────────
# gcloud Application Default Credentials. Idempotent — skips the browser flow
# if a valid token already exists, so --skip-to auth on a re-run is a no-op
# when auth was already successful.
if should_run_phase auth; then
  CURRENT_PHASE=auth
  echo ""
  echo "[PHASE: auth]"

  if gcloud auth application-default print-access-token &>/dev/null; then
    echo "✓ Already authenticated to Google Cloud"
  else
    echo "A browser window will open. Sign in with your @aimclear.com Google account."
    echo ""
    gcloud auth application-default login
  fi

  # Verify auth actually worked
  if ! gcloud auth application-default print-access-token &>/dev/null; then
    echo "" >&2
    echo "ERROR: Google authentication did not complete successfully." >&2
    echo "Re-run with --skip-to auth and complete the browser sign-in when prompted." >&2
    exit 1   # trap maps this to 40
  fi

  # Smoke test: can we see any GCP projects? This is DIAGNOSTIC only — if gcloud
  # itself fails (Cloud Resource Manager API not enabled, no quota project set,
  # etc.) we must NOT fail the phase, because the marketer's auth was already
  # verified working two lines above. Isolate the call so set -e / pipefail
  # can't trip on it.
  echo ""
  echo "Checking your BigQuery access..."
  set +e
  PROJECT_LIST_OUTPUT=$(gcloud projects list --format="value(projectId)" 2>&1)
  PROJECT_LIST_RC=$?
  set -e

  if [[ $PROJECT_LIST_RC -ne 0 ]]; then
    echo ""
    echo "NOTE: 'gcloud projects list' returned an error (exit $PROJECT_LIST_RC), but your"
    echo "      authentication itself succeeded. Common cause: the Cloud Resource Manager API"
    echo "      isn't enabled on a quota project you have access to. You can still test the MCP"
    echo "      in Claude. If projects don't show up there, send Timothy the message below:"
    echo ""
    printf '%s\n' "$PROJECT_LIST_OUTPUT" | sed 's/^/      /'
    echo ""
  else
    PROJECT_COUNT=$(printf '%s\n' "$PROJECT_LIST_OUTPUT" | grep -c '[^[:space:]]' || true)
    if [[ "$PROJECT_COUNT" == "0" ]]; then
      echo ""
      echo "NOTE: Google sign-in worked, but you don't have access to any BigQuery projects yet."
      echo "Send your Google account email to Alyssa and ask her to add you to client projects."
      echo "Once she's done, you don't need to re-run this script — just test in Claude."
      echo ""
    fi
  fi
fi

# Clear CURRENT_PHASE so a successful exit doesn't trigger the trap remap.
CURRENT_PHASE=""

echo ""
echo "=== Setup complete ==="
echo ""
echo "IMPORTANT: If Claude Code or Claude Desktop is currently running, fully QUIT and"
echo "reopen them now (Cmd+Q, not just close the window). MCP entries only load at startup."
echo ""
echo "Then start a new Claude conversation and ask:"
echo "  'What BigQuery projects do I have access to?'"
