#!/bin/sh
# CodeSpark CLI installer — POSIX shell.
#
# Usage:
#   curl -fsSL https://get.codespark.tech | sh
#   curl -fsSL https://get.codespark.tech/cli/install.sh | sh
#
# Что делает:
#   1. Проверяет, что в системе есть Node.js >= 20.
#   2. Скачивает manifest sidecar и tarball, проверяет SHA-256.
#   3. Распаковывает в $CODESPARK_HOME/lib (по умолчанию $HOME/.codespark/lib).
#   4. Кладёт исполняемый shim в $CODESPARK_HOME/bin/codespark.
#   5. Печатает советы по PATH (если бин-папка туда не входит).
#
# Что НЕ делает:
#   — не bundle-ит Node (это удвоило бы размер per-platform; см. CLAUDE.md
#     pitfall про bundling-tax). Node >=20 — обязательное требование.
#   — не модифицирует .bashrc / .zshrc автоматически (только подсказка).
#
# Можно перебить переменные:
#   CODESPARK_HOME=/opt/codespark    Куда ставить (по умолчанию ~/.codespark).
#   CODESPARK_VERSION=0.0.1          Конкретная версия (по умолчанию latest).
#   CODESPARK_BASE_URL=https://...   Перебить URL CDN.

set -e

# Раньше базовым CDN был `downloads.codespark.tech`, но YC TF-провайдер
# каждый apply сбрасывает host_options на этом CDN-resource, и он
# превращается в NoSuchBucket. `get.codespark.tech` смотрит на тот же
# bucket через website-endpoint и работает стабильно — отдаёт обычные
# объекты в `/cli/...` и install.sh по `/`. Один источник правды и
# меньше движущихся частей. Можно перебить через CODESPARK_BASE_URL.
BASE_URL="${CODESPARK_BASE_URL:-https://get.codespark.tech/cli}"
INSTALL_HOME="${CODESPARK_HOME:-$HOME/.codespark}"
INSTALL_BIN="$INSTALL_HOME/bin"
INSTALL_LIB="$INSTALL_HOME/lib"

# ── Цвета ────────────────────────────────────────────────────────────
if [ -t 1 ] && [ -z "${NO_COLOR:-}" ]; then
  ACCENT='\033[38;5;208m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'
  RED='\033[0;31m'; DIM='\033[2m'; NC='\033[0m'
else
  ACCENT=''; GREEN=''; YELLOW=''; RED=''; DIM=''; NC=''
fi

say()   { printf "${ACCENT}==> %s${NC}\n" "$*"; }
ok()    { printf "${GREEN}    ✓ %s${NC}\n" "$*"; }
warn()  { printf "${YELLOW}    ! %s${NC}\n" "$*"; }
die()   { printf "${RED}    × %s${NC}\n" "$*" >&2; exit 1; }

printf "${ACCENT}⚡ CodeSpark CLI — установка${NC}\n\n"

# ── Проверка Node ────────────────────────────────────────────────────
if ! command -v node >/dev/null 2>&1; then
  die "Требуется Node.js 20+. Установите с https://nodejs.org/ и запустите снова."
fi
NODE_MAJOR=$(node -p 'process.versions.node.split(".")[0]' 2>/dev/null || echo 0)
if [ "$NODE_MAJOR" -lt 20 ]; then
  die "Найден Node.js $NODE_MAJOR, нужен >= 20. Обновите с https://nodejs.org/"
fi
ok "Node.js $(node -v)"

# ── Утилиты ──────────────────────────────────────────────────────────
if command -v curl >/dev/null 2>&1; then DOWNLOADER="curl -fsSL -o";
elif command -v wget >/dev/null 2>&1; then DOWNLOADER="wget -q -O";
else die "Нужен curl или wget."; fi

if command -v sha256sum >/dev/null 2>&1; then
  hash_cmd() { sha256sum "$1" | awk '{print $1}'; }
elif command -v shasum >/dev/null 2>&1; then
  hash_cmd() { shasum -a 256 "$1" | awk '{print $1}'; }
else
  die "Нужен sha256sum или shasum."
fi

# ── Версия + sha256 ──────────────────────────────────────────────────
VERSION="${CODESPARK_VERSION:-}"
if [ -z "$VERSION" ]; then
  say "Получаю манифест последней версии"
  TMP_META=$(mktemp)
  $DOWNLOADER "$TMP_META" "$BASE_URL/codespark-cli-latest.tar.gz.meta.json" \
    || die "не удалось скачать манифест: $BASE_URL/codespark-cli-latest.tar.gz.meta.json"
  VERSION=$(sed -n 's/.*"version":[[:space:]]*"\([^"]*\)".*/\1/p' "$TMP_META")
  EXPECTED_SHA=$(sed -n 's/.*"sha256":[[:space:]]*"\([^"]*\)".*/\1/p' "$TMP_META")
  rm -f "$TMP_META"
  [ -n "$VERSION" ] || die "не удалось распарсить версию из манифеста"
fi
ok "Версия: $VERSION"

TARBALL_NAME="codespark-cli-${VERSION}.tar.gz"
TARBALL_URL="$BASE_URL/$TARBALL_NAME"

# ── Скачивание + проверка ────────────────────────────────────────────
TMP_DIR=$(mktemp -d)
trap 'rm -rf "$TMP_DIR"' EXIT
TARBALL_PATH="$TMP_DIR/$TARBALL_NAME"

say "Скачиваю $TARBALL_URL"
$DOWNLOADER "$TARBALL_PATH" "$TARBALL_URL" || die "не удалось скачать $TARBALL_URL"

if [ -n "${EXPECTED_SHA:-}" ]; then
  ACTUAL_SHA=$(hash_cmd "$TARBALL_PATH")
  if [ "$EXPECTED_SHA" != "$ACTUAL_SHA" ]; then
    die "SHA-256 не совпадает! ожидали $EXPECTED_SHA, получили $ACTUAL_SHA"
  fi
  ok "SHA-256 проверен"
fi

# ── Распаковка ───────────────────────────────────────────────────────
say "Распаковываю в $INSTALL_HOME"
mkdir -p "$INSTALL_BIN" "$INSTALL_LIB"
tar -xzf "$TARBALL_PATH" -C "$TMP_DIR"
EXTRACTED="$TMP_DIR/codespark-cli-${VERSION}"
[ -d "$EXTRACTED" ] || die "распаковка вернула неожиданное дерево: содержимое $TMP_DIR"

# Полная замена lib/ — старая версия удаляется, чтобы не оставались мусорные файлы.
rm -rf "$INSTALL_LIB"
mkdir -p "$INSTALL_LIB"
cp -R "$EXTRACTED/lib/." "$INSTALL_LIB/"

# Wrapper в bin/. Перезаписываем — это сделает обновление безопасным.
cat > "$INSTALL_BIN/codespark" <<EOF
#!/bin/sh
exec node "$INSTALL_LIB/cli.mjs" "\$@"
EOF
chmod +x "$INSTALL_BIN/codespark"
ok "Установлено в $INSTALL_BIN/codespark"

# ── PATH-подсказка ───────────────────────────────────────────────────
case ":$PATH:" in
  *":$INSTALL_BIN:"*)
    say "Готово!"
    ok "Запустите: codespark"
    ;;
  *)
    say "Готово, но $INSTALL_BIN не в PATH."
    SHELL_RC="$HOME/.bashrc"
    [ -n "${ZSH_VERSION:-}" ] && SHELL_RC="$HOME/.zshrc"
    case "$SHELL" in
      */zsh) SHELL_RC="$HOME/.zshrc" ;;
      */fish) SHELL_RC="$HOME/.config/fish/config.fish" ;;
      */bash) SHELL_RC="$HOME/.bashrc" ;;
    esac
    printf "${DIM}    Добавьте в %s:${NC}\n" "$SHELL_RC"
    printf "      ${ACCENT}export PATH=\"%s:\$PATH\"${NC}\n" "$INSTALL_BIN"
    printf "${DIM}    Затем перезапустите терминал и выполните:${NC} ${ACCENT}codespark${NC}\n"
    ;;
esac
