#!/usr/bin/env bash
# Install (or update) the Encyclopedia of Abstractions MCP server — macOS / Linux.
#
#   curl -fsSL https://abstractopedia.org/downloads/eoa-mcp-install.sh | bash
#   bash install.sh [--home DIR] [--from DIR|URL] [--python PYTHON] [--yes] [--no-model] [--no-test]
#
# What it does, in order — every step is idempotent, re-run to update:
#   1. picks an install home (default ~/.eoa-mcp; prompts unless --yes)
#   2. creates a virtualenv there and installs the eoa-mcp wheel
#   3. downloads the data bundle and verifies every file's SHA-256
#   4. downloads the embedding model from its official repository (pinned, verified)
#   5. runs `eoa-mcp doctor` and the packaged test-suite against what it installed
#   6. prints the client configuration to paste
#
# --from   where the release lives: a directory holding eoa-mcp-latest.json,
#          the wheel and the data bundle (the build uses dist/mcp), or the
#          site (default). Nothing is executed from the download; the wheel is
#          installed with pip and the bundle is unpacked by eoa-mcp itself.
#
# Windows: run the same steps by hand from PowerShell —
#   py -3 -m venv %USERPROFILE%\.eoa-mcp\venv
#   %USERPROFILE%\.eoa-mcp\venv\Scripts\pip install <wheel URL>
#   %USERPROFILE%\.eoa-mcp\venv\Scripts\eoa-mcp fetch-data && ... fetch-model && ... doctor && ... self-test
set -euo pipefail
main() {

SITE="https://abstractopedia.org/downloads"
FROM="$SITE"
HOME_DIR="${EOA_HOME:-$HOME/.eoa-mcp}"
PY="${PYTHON:-}"
YES=0; MODEL=1; TEST=1
while [[ $# -gt 0 ]]; do
  case "$1" in
    --home) HOME_DIR="$2"; shift 2 ;;
    --from) FROM="$2"; shift 2 ;;
    --python) PY="$2"; shift 2 ;;
    --yes|-y) YES=1; shift ;;
    --no-model) MODEL=0; shift ;;
    --no-test) TEST=0; shift ;;
    -h|--help) sed -n '2,/^set -euo pipefail/p' "$0" | sed 's/^# \{0,1\}//; s/^set.*$//'; exit 0 ;;
    *) echo "unknown flag: $1" >&2; exit 2 ;;
  esac
done

say() { printf '\n\033[1m%s\033[0m\n' "$*"; }
die() { echo "install: $*" >&2; exit 1; }

# --- python -----------------------------------------------------------------
if [[ -z "$PY" ]]; then
  for c in python3.13 python3.12 python3.11 python3.10 python3; do
    if command -v "$c" >/dev/null 2>&1 && "$c" -c 'import sys; sys.exit(0 if sys.version_info >= (3,10) else 1)' 2>/dev/null; then PY="$c"; break; fi
  done
fi
[[ -n "$PY" ]] || die "Python 3.10+ not found. Install it (macOS: brew install python) and re-run, or pass --python."
PYV="$("$PY" -c 'import sys; print("%d.%d.%d" % sys.version_info[:3])')"

# --- location -----------------------------------------------------------------
if [[ "$YES" -eq 0 && -t 0 ]]; then
  read -r -p "Install location [$HOME_DIR]: " ans
  HOME_DIR="${ans:-$HOME_DIR}"
fi
HOME_DIR="${HOME_DIR/#\~/$HOME}"
mkdir -p "$HOME_DIR"
HOME_DIR="$(cd "$HOME_DIR" && pwd)"          # absolute, whatever was typed
[[ "$HOME_DIR" != "$PWD" && "$HOME_DIR" != "$HOME" ]] || die "refusing to install into $HOME_DIR; pass --home <dir>"
VENV="$HOME_DIR/venv"; DATA="$HOME_DIR/data"; BIN="$VENV/bin/eoa-mcp"

# --- release pointer -----------------------------------------------------------
say "Release"
POINTER="$HOME_DIR/eoa-mcp-latest.json"   # a copy, for display and for the record
if [[ "$FROM" == http* ]]; then
  curl -fsSL "$FROM/eoa-mcp-latest.json" -o "$POINTER" || die "cannot download $FROM/eoa-mcp-latest.json"
else
  FROM="$(cd "$FROM" && pwd)"
  cp "$FROM/eoa-mcp-latest.json" "$POINTER" || die "no eoa-mcp-latest.json in $FROM"
fi
read -r SERVER_VERSION EDITION WHEEL WHEEL_SHA <<<"$("$PY" - "$POINTER" <<'PYEOF'
import json, sys
p = json.load(open(sys.argv[1]))
w = p.get("wheel") or {}
print(p["server_version"], p["data"]["edition"], w.get("url", ""), w.get("sha256", ""))
PYEOF
)"
[[ -n "$WHEEL" && -n "$WHEEL_SHA" ]] || die "release pointer has no wheel entry"
echo "  server $SERVER_VERSION, data edition $EDITION, python $PYV ($PY)"
echo "  install home: $HOME_DIR"

# --- venv + wheel ----------------------------------------------------------------
say "Server"
[[ -x "$VENV/bin/python" ]] || "$PY" -m venv "$VENV"
"$VENV/bin/python" -m pip install --quiet --upgrade pip >/dev/null
# Fetch the wheel ourselves and check it against the pointer before pip sees it.
WHEEL_LOCAL="$HOME_DIR/$WHEEL"
if [[ "$FROM" == http* ]]; then
  curl -fsSL "$FROM/$WHEEL" -o "$WHEEL_LOCAL" || die "cannot download $FROM/$WHEEL"
else
  cp "$FROM/$WHEEL" "$WHEEL_LOCAL"
fi
GOT="$("$PY" - "$WHEEL_LOCAL" <<'PYEOF'
import hashlib, sys
print(hashlib.sha256(open(sys.argv[1], "rb").read()).hexdigest())
PYEOF
)"
[[ "$GOT" == "$WHEEL_SHA" ]] || die "wheel SHA-256 mismatch (expected $WHEEL_SHA, got $GOT)"
"$VENV/bin/python" -m pip install --quiet --upgrade "$WHEEL_LOCAL"
# pip treats an installed wheel of the SAME version as satisfied and keeps the old
# files, so a rebuild that fixes code without a version bump (e.g. a second build of
# one publish) would self-test the stale package. The SHA above proved this wheel is
# the one we mean; reinstall the package itself from it (dependencies stay as they are).
"$VENV/bin/python" -m pip install --quiet --force-reinstall --no-deps "$WHEEL_LOCAL"
echo "  eoa-mcp $("$BIN" version) installed"

# --- data ---------------------------------------------------------------------
say "Data"
# The pointer names the bundle relative to its own location, so fetch from
# the release location itself (site URL or the build's dist/mcp directory).
"$BIN" fetch-data --from "$FROM/eoa-mcp-latest.json" --dest "$DATA"
export EOA_DATA_DIR="$DATA"

# --- model -----------------------------------------------------------------------
if [[ "$MODEL" -eq 1 ]]; then
  say "Embedding model (Qdrant/bge-small-en-v1.5-onnx-Q, Apache-2.0, ~67 MB)"
  "$BIN" fetch-model
fi

# --- verify --------------------------------------------------------------------
say "Doctor"
"$BIN" doctor
if [[ "$TEST" -eq 1 ]]; then
  say "Self-test (packaged test-suite against the installed data — a minute or two)"
  "$BIN" self-test --quick
fi

# --- how to connect -------------------------------------------------------------
say "Done. Add the server to your client:"
echo; echo "Claude Desktop — merge into claude_desktop_config.json:"
"$BIN" config claude-desktop
echo; echo "Claude Code:"
"$BIN" config claude-code
echo; echo "Re-run this script any time to update. Data only: $BIN fetch-data"
}

main "$@"
