#!/usr/bin/env sh
# Установка CapyAgent одной строкой.
#
#   curl -fsSL https://capyagent.ru/install.sh | sh
#
# 🔴 На минимальном Debian или Ubuntu (контейнер, свежий VPS) нет ни curl, ни
# корневых сертификатов, и строка выше падает раньше, чем доходит до этого
# скрипта: «curl: not found». Сначала одна команда от root:
#
#   apt-get update && apt-get install -y curl ca-certificates
#
# 🔴 Скажем прямо, что тут происходит: вы запускаете у себя то, что вам прислал
# наш сервер. Это удобно и это доверие к нам и к TLS - не больше и не меньше.
# Если так не хотите (и правильно, если не хотите):
#
#   curl -fsSLO https://capyagent.ru/install.sh
#   less install.sh          # прочитать
#   sh install.sh
#
# 🔴 Ставит В ДОМАШНИЙ КАТАЛОГ и БЕЗ sudo. Службой на весь сервер - отдельным
# шагом и осознанно: программа получает доступ к вашим системам, и решение
# «пусть работает всегда от имени машины» человек принимает отдельно от
# решения «дай посмотреть».
set -eu

# 🔴 Файлы берутся с нашего канала выпуска capyagent.ru/dl (решение владельца
# 05.09). Выпуски GitHub остаются архивом версий, но репозиторий закрыт, и
# постороннему они отвечают 404 - неотличимо от «выпуска нет».
BAZA="${CAPYAGENT_BASE:-https://capyagent.ru/dl/latest}"
KUDA="${CAPYAGENT_BIN:-$HOME/.local/bin}"

skazat() { printf '%s\n' "$*"; }
upast() { printf '🔴 %s\n' "$*" >&2; exit 1; }

# ---------- какая машина ----------
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
case "$(uname -m)" in
  x86_64|amd64) ARCH=amd64 ;;
  aarch64|arm64) ARCH=arm64 ;;
  *) upast "Не знаю сборки под $(uname -m). Есть linux amd64/arm64 и macOS arm64." ;;
esac
case "$OS" in
  linux|darwin) : ;;
  *) upast "Не знаю сборки под $OS." ;;
esac
IMYA="capyagent-$OS-$ARCH"

# ---------- чем качать ----------
if command -v curl >/dev/null 2>&1; then
  vzyat() { curl -fsSL "$1"; }
  vzyat_v() { curl -fsSL "$1" -o "$2"; }
elif command -v wget >/dev/null 2>&1; then
  vzyat() { wget -qO- "$1"; }
  vzyat_v() { wget -qO "$2" "$1"; }
else
  upast "Нет ни curl, ни wget - нечем скачать."
fi

# 🔴 Сумму проверяем обязательно, и без чем считать не ставим. «Поставлю без
# проверки» здесь означало бы: возьму у сети исполняемый файл и запущу, не
# посмотрев. Отказ честнее.
if command -v sha256sum >/dev/null 2>&1; then
  summa() { sha256sum "$1" | awk '{print $1}'; }
elif command -v shasum >/dev/null 2>&1; then
  summa() { shasum -a 256 "$1" | awk '{print $1}'; }
else
  upast "Нет ни sha256sum, ни shasum - нечем проверить, что файл дошёл целым."
fi

skazat "CapyAgent: ставлю $IMYA"
skazat "  откуда: $BAZA"
skazat "  куда:   $KUDA"

# ---------- что выпущено ----------
VREM=$(mktemp -d)
trap 'rm -rf "$VREM"' EXIT INT TERM

# 🔴 Называем самую вероятную причину отказа. Человек, читающий «проверьте
# сеть», будет чинить сеть, даже если дело в сертификатах.
vzyat "$BAZA/checksums.txt" > "$VREM/checksums.txt" 2>/dev/null \
  || upast "Не забрать список сумм с $BAZA.
   Вероятные причины по убыванию:
   1) нет сети или закрыт доступ к $(printf '%s' "$BAZA" | sed 's#^[a-z]*://##; s#/.*##');
   2) нет корневых сертификатов (минимальный Debian/Ubuntu):
      apt-get install -y ca-certificates;
   3) свой адрес задан неверно через CAPYAGENT_BASE."

# Ищем нашу строку. Пути в файле записаны как bin/<имя>.
OZHID=$(grep "/$IMYA\$" "$VREM/checksums.txt" | awk '{print $1}' | head -1 || true)
[ -n "$OZHID" ] || upast "В выпуске нет сборки под $OS/$ARCH."

skazat "  качаю..."
# 🔴 Два адреса, и порядок не случаен. GitHub Releases хранит вложения
# ПЛОСКО: имя вложения не может содержать косую черту, и «.../download/bin/имя»
# отвечает 404 всегда - хотя в checksums.txt пути записаны с bin/. Свой сервер
# отдаёт каталог выпуска как есть: файл лежит в bin/, а рядом, в корне, та же
# жёсткая ссылка под плоским именем для старых клиентов (build-release.sh).
# Пробуем плоское имя, затем bin/ - отказ только после обоих.
vzyat_v "$BAZA/$IMYA" "$VREM/$IMYA" 2>/dev/null \
  || vzyat_v "$BAZA/bin/$IMYA" "$VREM/$IMYA" 2>/dev/null \
  || upast "Не скачать бинарник: ни $BAZA/$IMYA, ни $BAZA/bin/$IMYA не отвечает."

NASHLA=$(summa "$VREM/$IMYA")
[ "$NASHLA" = "$OZHID" ] || {
  printf '🔴 Контрольная сумма не сошлась.\n' >&2
  printf '   пришло:    %s\n' "$NASHLA" >&2
  printf '   ожидалось: %s\n' "$OZHID" >&2
  printf '   Файл по дороге изменился - запускать его нельзя.\n' >&2
  exit 1
}
skazat "  сумма сошлась"

mkdir -p "$KUDA"
chmod 755 "$VREM/$IMYA"
mv "$VREM/$IMYA" "$KUDA/capyagent"

# ---------- виден ли он ----------
if ! command -v capyagent >/dev/null 2>&1; then
  skazat ""
  skazat "🔴 $KUDA не в вашем PATH. Добавьте строку в ~/.profile или ~/.zshrc:"
  skazat "     export PATH=\"\$PATH:$KUDA\""
  skazat "   Или зовите по полному пути: $KUDA/capyagent"
fi

skazat ""
skazat "Поставлено: $("$KUDA/capyagent" version 2>/dev/null || echo "$KUDA/capyagent")"
skazat ""

# 🔴 Мастер запускаем САМИ, если человек сидит за терминалом.
#
# Установка, которая заканчивается словами «а теперь наберите ещё команду», -
# это лишняя ступенька, и на ней половина уходит. У соседей мастер открывается
# сам, и это не украшение: человек, поставивший программу одной строкой, ждёт,
# что дальше с ним заговорят.
#
# 🔴 Проверяем /dev/tty, а не стандартный ввод: при `curl ... | sh` ввод занят
# самим скриптом, и мастер, смотрящий только на него, откажется работать.
# Проверяем ОТКРЫТИЕМ, а не правами: в контейнере без терминала /dev/tty
# лежит с правами на чтение, но не открывается, и `[ -r /dev/tty ]` пускал
# сюда, чтобы оболочка напечатала «cannot open /dev/tty» вместо нашей
# подсказки.
#
# 🔴 Файл настроек мастер выбирает сам, и выбирает тот, который читает
# программа: без службы - файл каталога данных (`capyagent config path`), а
# если человек согласится запустить агента службой (мастер предлагает это,
# когда настроен бот), - файл окружения службы. Называть ему файл отсюда
# нельзя: до 01.10 скрипт передавал --файл каталога данных, и root, выбравший
# службу, получал настройки там, куда системная служба не смотрит.
#
# 🔴 Провал мастера - не «ничего не записано»: он мог записать настройки и не
# запустить службу (модель не поднялась, бот не ответил). Что именно не так,
# мастер пишет сам строкой выше.
if [ -n "${CAPYAGENT_SETUP_ANSWERS:-}" ]; then
  # Файл ответов: вопросов нет, setup берёт путь из переменной сам.
  "$KUDA/capyagent" setup || upast "Настройка по файлу ответов не закончена: причина выше."
elif ( : </dev/tty ) 2>/dev/null; then
  skazat "Настраиваю. Спрошу про модель и проверю её живьём."
  skazat ""
  "$KUDA/capyagent" setup < /dev/tty || {
    skazat ""
    skazat "Мастер не закончил: что не так, написано выше. Продолжить, когда удобно:"
    skazat "  $KUDA/capyagent setup"
  }
else
  skazat "Дальше одна команда - она спросит про модель, проверит её живьём"
  skazat "и, если настроите бота, запустит агента службой:"
  skazat "  $KUDA/capyagent setup"
fi

skazat ""
skazat "🔴 Что программа умеет и куда ходит - покажет она сама:"
skazat "  $KUDA/capyagent doctor --prove"
