#!/usr/bin/env bash
#
# Установка CLI `ush` (UniShift runner management).
#
# Скачивает бинарник под текущую ОС/архитектуру из storage.unishift.ru/cli
# и кладёт его в PATH.
#
# Запуск:
#   curl -fsSL https://storage.unishift.ru/cli/install.sh | bash
# либо, скачав файл:
#   ./install.sh
#
# Переопределяемые переменные окружения:
#   BASE_URL     откуда качать                 (https://storage.unishift.ru/cli)
#   INSTALL_DIR  куда положить бинарник        (/usr/local/bin)
#   BIN_NAME     имя файла в INSTALL_DIR       (ush)
#
# Примеры:
#   curl -fsSL …/install.sh | bash
#   curl -fsSL …/install.sh | INSTALL_DIR="$HOME/.local/bin" bash
#   INSTALL_DIR=/opt/bin ./install.sh
#
set -euo pipefail

BASE_URL="${BASE_URL:-https://storage.unishift.ru/cli}"
INSTALL_DIR="${INSTALL_DIR:-/usr/local/bin}"
BIN_NAME="${BIN_NAME:-ush}"

log()  { printf '\033[1;34m==>\033[0m %s\n' "$*"; }
warn() { printf '\033[1;33m warn:\033[0m %s\n' "$*" >&2; }
die()  { printf '\033[1;31mОшибка:\033[0m %s\n' "$*" >&2; exit 1; }

need_cmd() {
  command -v "$1" >/dev/null 2>&1 || die "нужна утилита '$1', но она не найдена в PATH"
}

need_cmd curl
need_cmd uname
need_cmd mktemp

# ─── ОС / архитектура ───
os=$(uname -s | tr '[:upper:]' '[:lower:]')
arch=$(uname -m)

case "$os" in
  linux|darwin) ;;
  msys*|mingw*|cygwin*)
    die "для Windows скачайте бинарник вручную: ${BASE_URL}/ush-windows-amd64.exe"
    ;;
  *) die "неподдерживаемая ОС: $(uname -s)" ;;
esac

case "$arch" in
  x86_64|amd64) arch=amd64 ;;
  aarch64|arm64) arch=arm64 ;;
  *) die "неподдерживаемая архитектура: $(uname -m)" ;;
esac

asset="ush-${os}-${arch}"
url="${BASE_URL}/${asset}"
dest="${INSTALL_DIR}/${BIN_NAME}"

log "Платформа: ${os}/${arch}"
log "Скачиваю ${url}"

tmp=$(mktemp)
trap 'rm -f "$tmp"' EXIT

curl -fsSL -o "$tmp" "$url" || die "не удалось скачать $url"
[ -s "$tmp" ] || die "скачанный файл пуст: $url"
chmod +x "$tmp"

# Опциональная проверка SHA256SUMS, если файл есть на storage.
sums_url="${BASE_URL}/SHA256SUMS"
if curl -fsSL -o /dev/null -w '' "$sums_url" 2>/dev/null; then
  if command -v sha256sum >/dev/null 2>&1 || command -v shasum >/dev/null 2>&1; then
    log "Проверяю контрольную сумму"
    sums=$(mktemp)
    trap 'rm -f "$tmp" "$sums"' EXIT
    curl -fsSL -o "$sums" "$sums_url" || die "не удалось скачать $sums_url"
    expected=$(awk -v f="$asset" '$2 == f || $2 == "./"f || $2 == "/"f { print $1; exit }' "$sums")
    if [ -n "${expected:-}" ]; then
      if command -v sha256sum >/dev/null 2>&1; then
        actual=$(sha256sum "$tmp" | awk '{ print $1 }')
      else
        actual=$(shasum -a 256 "$tmp" | awk '{ print $1 }')
      fi
      [ "$actual" = "$expected" ] || die "checksum mismatch для $asset (got $actual, want $expected)"
    else
      warn "в SHA256SUMS нет записи для $asset — пропускаю проверку"
    fi
  fi
fi

# ─── Установка ───
log "Устанавливаю в $dest"
mkdir -p "$INSTALL_DIR" 2>/dev/null || true

install_bin() {
  # атомарная замена: пишем во временный файл рядом, затем mv
  local staged="${dest}.new"
  if cp "$tmp" "$staged" 2>/dev/null && mv -f "$staged" "$dest" 2>/dev/null; then
    chmod +x "$dest"
    return 0
  fi
  rm -f "$staged" 2>/dev/null || true
  return 1
}

if ! install_bin; then
  if command -v sudo >/dev/null 2>&1; then
    warn "нет прав на запись в $INSTALL_DIR — пробую через sudo"
    sudo mkdir -p "$INSTALL_DIR"
    sudo cp "$tmp" "$dest"
    sudo chmod +x "$dest"
  else
    die "не удалось записать $dest (нужны права или задайте INSTALL_DIR=\$HOME/.local/bin)"
  fi
fi

log "Готово: $dest"
if command -v "$BIN_NAME" >/dev/null 2>&1; then
  log "Проверка: $($BIN_NAME --help 2>&1 | head -n 1 || true)"
else
  warn "$BIN_NAME не в PATH. Добавьте $INSTALL_DIR в PATH или перелогиньтесь."
fi

printf '\nУстановка завершена. Примеры:\n'
printf '  ush status\n'
printf '  ush install shell\n\n'
