#!/usr/bin/env bash
# Customer bootstrap. Release builder embeds the public signing key, never a secret.
# Download completely and verify before extracting or executing the signed payload.
set -euo pipefail

main() {
  local bundle="" signature="" key="" verify_only=0 tmp
  local embedded_key='LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQ0lqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FnOEFNSUlDQ2dLQ0FnRUF3cUJCQ0lZbnhlbDBrbTd0a29SMwpYN05nZ2lOaDhsS1o3dnoxSmNCS3lEQk11UXhmT2M1TU11SzdEODdlNyt6bnVxRW5RdTBac05ramhrRkRaYk5SCmRPcXN1MHlHYUZHc2pNSkZnYWN0NWp5NjhtcHR1amVTcUxrN3hlRXZHRUxBMW1YeGxXTm5pOXhhVEN4dnoxRGQKN1BVUzU4NWV3MnA0dXZOVUhtQXNiY1N5TTE1ZHRVWTNJUUEyU0RTQ29zSGttWWs1QUhMMHE4SE1iOGdOMG05WQpHSXFBU2hDUkhYZ2VDQmpRaWkrOSthY1R2bXZoelFWNGFvZ3JRUzdLODlDVE1NbGRVVXpDd0Q2YXdVVVRYRGgxCm1nVXJFeTZyZC9mM2hhajJsM1ppRHBXbTR6NE51ejlueWZDaWtjUWxBdlFGUGhCbWZQcXJ5QnkwNzJrYm5ZU1YKaGhOZm1nNEh4UTlWZEtrRjB2RnA1dzNwdkIvZ3JkR29GSU9HU21VVklpU21TbWZybFQ3cFBKR01SbnA5VTdjOQpjVVJvRmczL2NQdklVNWZsRkpMdkd4SkdSUkg4R080WFhwY0dQek1kUkNDb2htMG1NRHljUVJBQlpBb1dPdHNnCkFUZ3Myb2h6ckhIODZObGZ3MExPVFBQZTJwcVZJK05CVWI3MmM0bXBnekdzV2lMNEdmUVc2ckVQbWtFOGJxYUcKQ0ZNZWtkYzlpY3lOU2h1cHRxa2ZMaFErMVdtVWk0bTFlbGhKT3puTGFUSHA0Y3ZMMm5CZE5nejNrbUdGb2RRZgpPS1BJWG9DS3N1K0h1UGZtVEhZaGdyYVNURFc4WGhzblZPYlBicE90T2tmK3d4T3k3L2FZWnZpMlB6eExSU3piCmtLbFRMclZid28rS1NyWWExWVc1THc4Q0F3RUFBUT09Ci0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLQo='
  local default_bundle='https://install.micator.com/releases/tracker-0.1.0-beta.20261003-amd64.tar.gz'
  local -a arguments=()
  while [ "$#" -gt 0 ]; do
    case "$1" in
      --bundle|--signature|--public-key)
        [ "$#" -ge 2 ] || { echo "Нет значения для $1" >&2; return 2; }
        case "$1" in --bundle) bundle=$2;; --signature) signature=$2;; --public-key) key=$2;; esac
        shift 2;;
      --verify-only) verify_only=1; shift;;
      --headless) arguments+=("$1"); shift;;
      --help|-h)
        echo 'Установка Tracker: bash install.sh [--bundle URL/FILE] [--signature URL/FILE] [--public-key FILE] [--panel DOMAIN --track DOMAIN --email EMAIL --admin-email LOGIN --path /opt/tracker] [--restore-env FILE]'
        echo 'Без параметров запускается мастер по IP. --setup-ip IP задаёт адрес вручную; --headless включает настройку в терминале. --verify-only проверяет подпись без установки.'
        return 0;;
      --panel|--track|--email|--admin-email|--path|--restore-env|--setup-ip)
        [ "$#" -ge 2 ] || { echo "Нет значения для $1" >&2; return 2; }
        arguments+=("$1" "$2"); shift 2;;
      *) echo "Неизвестный параметр: $1" >&2; return 2;;
    esac
  done
  if [ -z "$bundle" ] && [[ "$default_bundle" == https://* ]]; then bundle=$default_bundle; fi
  [ -n "$bundle" ] || { echo 'Нужен подписанный выпуск: --bundle URL/FILE' >&2; return 2; }
  if [ -z "$key" ] && [ "$embedded_key" = '__TRACKER_PUBLIC_'"KEY_B64__" ]; then
    echo 'В этот bootstrap ещё не встроен ключ выпуска. Укажите доверенный --public-key FILE.' >&2; return 2
  fi
  if [ "$verify_only" = 0 ]; then
    [ "$(id -u)" = 0 ] || { echo 'Установку запускать через sudo.' >&2; return 2; }
    [ "$(uname -s)" = Linux ] || { echo 'Для установки нужен Ubuntu 24.04.' >&2; return 2; }
    # Only distribution metadata is sourced; never source a downloaded env file.
    . /etc/os-release
    [ "$ID" = ubuntu ] && [ "$VERSION_ID" = 24.04 ] || { echo 'Поддерживается Ubuntu 24.04.' >&2; return 2; }
    if ! command -v python3 >/dev/null || ! command -v curl >/dev/null || ! command -v openssl >/dev/null; then
      export DEBIAN_FRONTEND=noninteractive
      apt-get update
      apt-get install -y --no-install-recommends ca-certificates curl openssl python3
    fi
  fi
  umask 077
  tmp=$(mktemp -d)
  trap "$(printf 'rm -rf -- %q' "$tmp")" EXIT
  if [ -n "$key" ]; then cp -- "$key" "$tmp/public.pem";
  else printf '%s' "$embedded_key" | openssl base64 -d -A > "$tmp/public.pem"; fi
  fetch() {
    case "$1" in
      https://*) curl --fail --silent --show-error --location --proto '=https' --proto-redir '=https' --connect-timeout 20 --max-time 1800 --max-filesize 8589934592 -o "$2" "$1";;
      *://*) echo 'Загрузка разрешена только по HTTPS.' >&2; return 2;;
      *) cp -- "$1" "$2";;
    esac
  }
  echo 'Загружаю подписанный выпуск…'
  fetch "$bundle" "$tmp/release.tar.gz"
  fetch "${signature:-$bundle.sig}" "$tmp/release.sig"
  openssl dgst -sha256 -verify "$tmp/public.pem" -signature "$tmp/release.sig" "$tmp/release.tar.gz" >/dev/null || {
    echo 'Подпись выпуска не прошла проверку. Установка остановлена.' >&2; return 1;
  }
  python3 - "$tmp/release.tar.gz" "$tmp/payload" <<'PY'
import sys, tarfile
from pathlib import Path, PurePosixPath
source, target = Path(sys.argv[1]), Path(sys.argv[2])
target.mkdir(mode=0o700)
with tarfile.open(source, 'r:gz') as archive:
    members = archive.getmembers()
    seen, total = set(), 0
    if len(members) > 10000:
        raise SystemExit('Слишком много файлов в выпуске')
    for member in members:
        path = PurePosixPath(member.name)
        if (path.is_absolute() or '..' in path.parts or member.name in seen or
            not member.name or '\\' in member.name or not (member.isfile() or member.isdir())):
            raise SystemExit('Небезопасный путь или тип файла в выпуске')
        seen.add(member.name)
        total += member.size
        if total > 16 * 1024**3:
            raise SystemExit('Распакованный выпуск слишком большой')
    for member in members:
        path = target / member.name
        if member.isdir():
            path.mkdir(mode=0o700, parents=True, exist_ok=True)
        else:
            path.parent.mkdir(mode=0o700, parents=True, exist_ok=True)
            with archive.extractfile(member) as src, path.open('xb') as dst:
                import shutil
                shutil.copyfileobj(src, dst)
            path.chmod(0o600)
PY
  if [ "$verify_only" = 1 ]; then
    python3 "$tmp/payload/deploy/install-runtime.py" verify --bundle "$tmp/payload"
  else
    python3 "$tmp/payload/deploy/install-runtime.py" install --bundle "$tmp/payload" "${arguments[@]}"
  fi
}
main "$@"
