#!/usr/bin/env bash
# Массовое развёртывание hard-monitor по SSH — в одну команду на список хостов.
# Для каждой машины: создать сервер на панели (если нет) → залить агента →
# установить (install.sh) → дождаться первого пакета.
#
#   ./deploy.sh --panel https://panel.example.com user@host1 user@host2
#
# Опции:
#   --panel URL      адрес панели (обязательно)
#   --token TOKEN    GHARD_ADMIN_TOKEN панели (нужен, если токен на панели задан)
#   --interval N     интервал агента в секундах (по умолчанию 30)
#   --recreate       если сервер с таким именем уже есть на панели — удалить
#                    его и создать заново (новый ключ); иначе ключ берётся
#                    из /opt/hard-monitor/.env на хосте, а запись переиспользуется
#   --git-install    ставить curl-ом прямо из репозитория (по умолчанию scp
#                    локальных файлов — работает даже без доступа хоста к гиту)
#
# Требования к хостам: ssh-доступ по ключу, python3, sudo без пароля
# (или запусти с agent'ом, который умеет отвечать на пароль sudo).

set -euo pipefail

PANEL=""
TOKEN=""
INTERVAL=30
RECREATE=0
GIT_INSTALL=0
TARGETS=()
RAW_BASE="https://git.gnexus.space/git/root/hard-panel/raw/branch/master"

say() { printf '\e[1;32m==>\e[0m %s\n' "$*"; }
warn() { printf '\e[1;33m!!\e[0m %s\n' "$*"; }
die() { printf '\e[1;31mошибка:\e[0m %s\n' "$*" >&2; exit 1; }
usage() { sed -n '2,20p' "$0" | sed 's/^# \{0,1\}//'; exit "${1:-0}"; }

while [[ $# -gt 0 ]]; do
    case "$1" in
        --panel) PANEL="$2"; shift 2 ;;
        --token) TOKEN="$2"; shift 2 ;;
        --interval) INTERVAL="$2"; shift 2 ;;
        --recreate) RECREATE=1; shift ;;
        --git-install) GIT_INSTALL=1; shift ;;
        -h|--help) usage 0 ;;
        -*) die "неизвестная опция: $1" ;;
        *) TARGETS+=("$1"); shift ;;
    esac
done

[[ "$PANEL" =~ ^https?:// ]] || { usage >&2; die "укажи --panel https://panel.example.com"; }
[[ ${#TARGETS[@]} -gt 0 ]] || { usage >&2; die "укажи хотя бы один хост: user@host"; }

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

api() { # api METHOD PATH [JSON]
    local method="$1" path="$2" body="${3:-}"
    curl -sS -X "$method" -H "Content-Type: application/json" \
        ${TOKEN:+-H "Authorization: Bearer $TOKEN"} \
        ${body:+-d "$body"} "$PANEL/api/v1$path"
}

# server_id по имени (пусто, если нет); python3 есть всюду, где есть ssh+curl
find_server() {
    api GET /servers | python3 -c "
import json, sys
name = sys.argv[1]
for s in json.load(sys.stdin):
    if s['name'] == name:
        print(s['id']); break
" "$1"
}

# первый пакет от сервера id (0/1)
is_online() {
    api GET /servers | python3 -c "
import json, sys
sid = int(sys.argv[1])
for s in json.load(sys.stdin):
    if s['id'] == sid:
        print(1 if s.get('status') == 'online' else 0); break
else:
    print(0)
" "$1"
}

for target in "${TARGETS[@]}"; do
    say "$target"
    ssh -o BatchMode=yes -o ConnectTimeout=10 "$target" true 2>/dev/null \
        || die "$target: нет ssh-доступа (проверь ключ/алиас)"

    name="$(ssh -o BatchMode=yes -o ConnectTimeout=10 "$target" 'hostname -s')"

    server_id="$(find_server "$name" || true)"
    key=""

    if [[ -n "$server_id" ]]; then
        if [[ $RECREATE -eq 1 ]]; then
            warn "сервер #$server_id «$name» уже есть — удаляю (--recreate)"
            api DELETE "/servers/$server_id" >/dev/null
            server_id=""
        else
            say "сервер #$server_id «$name» уже есть — переиспользую запись"
            key="$(ssh -o BatchMode=yes -o ConnectTimeout=10 "$target" \
                "grep -oP '^SERVER_KEY=\K.*' /opt/hard-monitor/.env 2>/dev/null || true")"
            if [[ -z "$key" ]]; then
                die "на $target нет /opt/hard-monitor/.env с ключом. Удали сервер «$name» на панели или запусти с --recreate"
            fi
            say "ключ взят из /opt/hard-monitor/.env на хосте"
        fi
    fi

    if [[ -z "$server_id" ]]; then
        say "создаю сервер «$name» на панели"
        resp="$(api POST /servers "{\"name\": \"$name\"}")"
        server_id="$(printf '%s' "$resp" | python3 -c 'import json,sys; print(json.load(sys.stdin)["id"])')"
        key="$(printf '%s' "$resp" | python3 -c 'import json,sys; print(json.load(sys.stdin)["key"])')"
    fi

    if [[ $GIT_INSTALL -eq 1 ]]; then
        say "устанавливаю агента (curl из $RAW_BASE)"
        ssh -o BatchMode=yes -o ConnectTimeout=10 "$target" \
            "curl -fsSL $RAW_BASE/monitor/install.sh | sudo bash -s -- '$PANEL' '$key' '$INTERVAL'"
    else
        say "заливаю файлы агента и устанавливаю"
        tmpd="/tmp/hard-monitor-install.$$"
        ssh -o BatchMode=yes -o ConnectTimeout=10 "$target" "mkdir -p '$tmpd'"
        scp -q "$SCRIPT_DIR/install.sh" "$SCRIPT_DIR/hard_monitor.py" \
            "$SCRIPT_DIR/hard-monitor.service" "$target:$tmpd/"
        ssh -o BatchMode=yes -o ConnectTimeout=10 -t "$target" \
            "sudo bash '$tmpd/install.sh' '$PANEL' '$key' '$INTERVAL'; rc=\$?; rm -rf '$tmpd'; exit \$rc" \
        || die "$target: установка не удалась"
    fi

    say "жду первый пакет (до $((INTERVAL * 4)) с)"
    ok=0
    for _ in $(seq 1 $((INTERVAL * 4 / 5))); do
        sleep 5
        if [[ "$(is_online "$server_id")" == "1" ]]; then ok=1; break; fi
    done
    if [[ $ok -eq 1 ]]; then
        say "✓ $target: агент онлайн (сервер #$server_id «$name»)"
    else
        die "$target: пакет не пришёл — смотри journalctl -u hard-monitor на хосте"
    fi
done

say "все хосты развёрнуты. Дашборд: $PANEL"