#!/usr/bin/env bash
# Замер VPS для рейтинга: процессор, диск, сеть -> JSON.
# Запуск (под root, на чистом тестовом VPS):
#   bash bench.sh --provider "Название" --plan "Тариф" --price 500 --currency RUB
# Результат: файл bench-<провайдер>-<дата>.json в текущей папке.
# Скрипт ставит sysbench, fio, curl; создаёт временный файл 1 ГБ и удаляет его.

set -u
export LC_ALL=C

PROVIDER=""; PLAN=""; PRICE=""; CURRENCY="RUB"; REGION=""
while [ $# -gt 0 ]; do
  case "$1" in
    --provider) PROVIDER="$2"; shift 2 ;;
    --plan)     PLAN="$2"; shift 2 ;;
    --price)    PRICE="$2"; shift 2 ;;
    --currency) CURRENCY="$2"; shift 2 ;;
    --region)   REGION="$2"; shift 2 ;;
    *) echo "Неизвестный параметр: $1"; exit 1 ;;
  esac
done

if [ -z "$PROVIDER" ] || [ -z "$PLAN" ] || [ -z "$PRICE" ]; then
  echo "Нужно: --provider, --plan, --price (необязательно: --currency, --region)"; exit 1
fi
if [ "$(id -u)" -ne 0 ]; then echo "Запустите под root"; exit 1; fi

log() { echo "[$(date +%H:%M:%S)] $*" >&2; }
json_str() { printf '%s' "$1" | sed 's/\\/\\\\/g; s/"/\\"/g'; }
num_or_null() { case "$1" in ''|*[!0-9.]*) echo null ;; *) echo "$1" ;; esac; }

# --- Установка утилит ---
log "Устанавливаю sysbench, fio, curl"
if command -v apt-get >/dev/null; then
  export DEBIAN_FRONTEND=noninteractive
  apt-get update -qq >/dev/null && apt-get install -y -qq sysbench fio curl iputils-ping >/dev/null
elif command -v dnf >/dev/null; then
  dnf install -y -q epel-release >/dev/null 2>&1
  dnf install -y -q sysbench fio curl iputils >/dev/null
else
  echo "Поддерживаются Debian/Ubuntu и RHEL-подобные (dnf)"; exit 1
fi
for b in sysbench fio curl ping; do
  command -v "$b" >/dev/null || { echo "Не удалось установить $b"; exit 1; }
done

# --- Сведения о сервере ---
CPU_MODEL=$(grep -m1 'model name' /proc/cpuinfo | cut -d: -f2- | sed 's/^ *//')
CORES=$(nproc)
RAM_MB=$(free -m | awk '/^Mem:/{print $2}')
DISK_GB=$(df -BG --output=size / | tail -1 | tr -dc '0-9')
OS_NAME=$(. /etc/os-release 2>/dev/null; echo "${PRETTY_NAME:-unknown}")
VIRT=$(systemd-detect-virt 2>/dev/null || echo unknown)

# --- Процессор ---
log "Процессор: 1 поток, 10 с"
CPU_SINGLE=$(sysbench cpu --threads=1 --time=10 run | awk -F: '/events per second/{gsub(/ /,"",$2); print $2}')
log "Процессор: все потоки ($CORES), 10 с"
CPU_MULTI=$(sysbench cpu --threads="$CORES" --time=10 run | awk -F: '/events per second/{gsub(/ /,"",$2); print $2}')

# --- Диск ---
TESTFILE=/root/.bench-fio.tmp
trap 'rm -f "$TESTFILE"' EXIT
fio_iops() {  # $1 = rw, $2 = номер вхождения "iops" (1 = read, 2 = write)
  fio --name=bench --filename="$TESTFILE" --size=1G --direct=1 --ioengine=libaio \
      --bs=4k --iodepth=64 --numjobs=1 --rw="$1" --runtime=30 --time_based \
      --group_reporting --output-format=json 2>/dev/null \
    | grep -o '"iops" *: *[0-9.]*' | sed -n "${2}p" | grep -o '[0-9.]*$' | cut -d. -f1
}
fio_seq_mbps() {  # последовательное чтение 1М, МБ/с
  fio --name=bench --filename="$TESTFILE" --size=1G --direct=1 --ioengine=libaio \
      --bs=1M --iodepth=16 --numjobs=1 --rw=read --runtime=20 --time_based \
      --group_reporting --output-format=json 2>/dev/null \
    | grep -o '"bw" *: *[0-9]*' | sed -n 1p | grep -o '[0-9]*$' | awk '{printf "%d", $1/1024}'
}
log "Диск: случайное чтение 4K, 30 с"
DISK_RREAD=$(fio_iops randread 1)
log "Диск: случайная запись 4K, 30 с"
DISK_RWRITE=$(fio_iops randwrite 2)
log "Диск: последовательное чтение 1M, 20 с"
DISK_SEQ=$(fio_seq_mbps)
rm -f "$TESTFILE"

# --- Сеть ---
# Качаем с нескольких источников, берём лучший результат.
# Засчитываем только полностью скачанный файл (код 200 и не меньше 40 МБ).
DL_MBIT=""; DL_SRC=""
for url in 'https://speed.cloudflare.com/__down?bytes=50000000' \
           'https://proof.ovh.net/files/100Mb.dat' \
           'https://fsn1-speed.hetzner.com/100MB.bin'; do
  host=$(printf '%s' "$url" | cut -d/ -f3)
  log "Сеть: скачивание с $host"
  set -- $(curl -s -o /dev/null -m 60 -w '%{http_code} %{size_download} %{speed_download}' "$url")
  code=${1:-0}; size=${2:-0}; bps=${3:-0}
  if [ "$code" = "200" ] && awk -v s="$size" 'BEGIN{exit !(s >= 40000000)}'; then
    mbit=$(awk -v b="$bps" 'BEGIN{printf "%d", b*8/1000000}')
    log "  $mbit Мбит/с"
    if [ -z "$DL_MBIT" ] || [ "$mbit" -gt "$DL_MBIT" ]; then DL_MBIT=$mbit; DL_SRC=$host; fi
  else
    log "  не удалось (код $code, скачано $size байт)"
  fi
done

ping_ms() { ping -c 5 -W 2 "$1" 2>/dev/null | awk -F/ '/^rtt|^round-trip/{printf "%.1f", $5}'; }
PING_JSON=""
for host in ya.ru vk.com 1.1.1.1 8.8.8.8; do
  log "Пинг до $host"
  v=$(ping_ms "$host")
  PING_JSON="$PING_JSON\"$host\": $(num_or_null "$v"), "
done
PING_JSON="{${PING_JSON%, }}"

# --- Результат ---
DATE=$(date -u +%Y-%m-%dT%H:%M:%SZ)
SAFE=$(printf '%s' "$PROVIDER" | tr -c 'A-Za-z0-9._-' '_')
OUT="bench-${SAFE}-$(date +%Y%m%d-%H%M).json"

cat > "$OUT" <<EOF
{
  "bench_version": 1,
  "date": "$DATE",
  "provider": "$(json_str "$PROVIDER")",
  "plan": "$(json_str "$PLAN")",
  "region": "$(json_str "$REGION")",
  "price": $(num_or_null "$PRICE"),
  "currency": "$(json_str "$CURRENCY")",
  "server": {
    "cpu_model": "$(json_str "$CPU_MODEL")",
    "cores": $(num_or_null "$CORES"),
    "ram_mb": $(num_or_null "$RAM_MB"),
    "disk_gb": $(num_or_null "$DISK_GB"),
    "os": "$(json_str "$OS_NAME")",
    "virt": "$(json_str "$VIRT")"
  },
  "cpu": {
    "sysbench_single": $(num_or_null "$CPU_SINGLE"),
    "sysbench_multi": $(num_or_null "$CPU_MULTI")
  },
  "disk": {
    "randread_4k_iops": $(num_or_null "$DISK_RREAD"),
    "randwrite_4k_iops": $(num_or_null "$DISK_RWRITE"),
    "seqread_1m_mbps": $(num_or_null "$DISK_SEQ")
  },
  "net": {
    "download_mbit": $(num_or_null "$DL_MBIT"),
    "download_source": "$(json_str "$DL_SRC")",
    "ping_ms": $PING_JSON
  }
}
EOF

log "Готово: $OUT"
cat "$OUT"
