#!/bin/sh
# Установка клиента Desktop (RustDesk) на CentOS / RHEL / AlmaLinux / Rocky Linux / Fedora.
# Запуск: curl -fsSL https://cdas.ru/dl/centos-install.sh | bash
#
# Поддерживаются системы с glibc >= 2.28: CentOS Stream 9/10, RHEL 8/9/10,
# AlmaLinux 8/9, Rocky Linux 8/9, Fedora. CentOS 7 (glibc 2.17) не поддерживается.
set -eu

SERVER="cdas.ru:555"
RELAY="cdas.ru:556"
KEY="CmBtM7H2U620o3mi7A2mSmCNtphH9A1FK5Cgwd4PKr0="
PORTAL="https://cdas.ru"

echo "=== Desktop — установка клиента (CentOS / RHEL / Alma / Rocky) ==="

# --- права root (через sudo, если запущено обычным пользователем) ---
SUDO=""
if [ "$(id -u)" -ne 0 ]; then
  if command -v sudo >/dev/null 2>&1; then
    SUDO="sudo"
    echo "Нужны права root — использую sudo (может спросить пароль)."
  else
    echo "Ошибка: запустите скрипт от root (sudo отсутствует)." >&2
    exit 1
  fi
fi

# --- пакетный менеджер ---
if command -v dnf >/dev/null 2>&1; then
  PKG=dnf
elif command -v yum >/dev/null 2>&1; then
  PKG=yum
else
  echo "Ошибка: не найден dnf/yum — это не RHEL-совместимая система." >&2
  echo "Для Debian/Ubuntu используйте https://cdas.ru/dl/linux-install.sh" >&2
  exit 1
fi

# --- glibc: клиент собран под glibc 2.28+ ---
GLIBC=$(getconf GNU_LIBC_VERSION 2>/dev/null | awk '{print $2}' || true)
if [ -z "$GLIBC" ] || ! awk -v v="$GLIBC" 'BEGIN{exit !(v+0 >= 2.28)}'; then
  echo "Ошибка: glibc ${GLIBC:-не определена} слишком старая, нужна 2.28 или новее." >&2
  echo "CentOS 7 (glibc 2.17) не поддерживается — обновитесь до CentOS Stream 9," >&2
  echo "Rocky Linux 9 или AlmaLinux 9 (миграция: https://wiki.centos.org/Manuals/ReleaseNotes)." >&2
  exit 1
fi

VERSION_ID=$(sed -n 's/^VERSION_ID="\{0,1\}\([^"]*\)"\{0,1\}$/\1/p' /etc/os-release 2>/dev/null | head -n1 || true)
VERSION_ID=${VERSION_ID:-}

if grep -qi '^ID="centos"' /etc/os-release 2>/dev/null; then
  if [ "$VERSION_ID" = "8" ]; then
    echo "Внимание: CentOS Linux 8 снят с поддержки, зеркала не работают." >&2
    echo "Если репозитории не переведены на vault.centos.org — установка зависимостей" >&2
    echo "завершится ошибкой. Рекомендуется CentOS Stream 9 / Rocky 9 / Alma 9." >&2
  fi
fi

# --- архитектура ---
ARCH=$(uname -m)
case "$ARCH" in
  x86_64) RPM="rustdesk-linux-x64.rpm" ;;
  aarch64) RPM="rustdesk-linux-arm64.rpm" ;;
  *)
    echo "Ошибка: архитектура $ARCH не поддерживается (нужен x86_64 или aarch64)." >&2
    exit 1
    ;;
esac

TMP=$(mktemp -d)
trap 'rm -rf "$TMP"' EXIT INT TERM

# --- загрузчик файла ---
if ! command -v curl >/dev/null 2>&1 && ! command -v wget >/dev/null 2>&1; then
  echo "[0/5] Устанавливаю curl..."
  $SUDO $PKG install -y curl </dev/null >/dev/null || true
fi

echo "[1/5] Скачиваю $RPM с портала..."
if command -v curl >/dev/null 2>&1; then
  curl -fSL --retry 3 --connect-timeout 15 -o "$TMP/rustdesk.rpm" "$PORTAL/dl/$RPM"
else
  wget -O "$TMP/rustdesk.rpm" "$PORTAL/dl/$RPM"
fi

# --- зависимости, которые нужны клиенту в рантайме (RPM объявляет не все) ---
echo "[2/5] Проверяю зависимости..."
DEPS="gtk3 alsa-lib pulseaudio-libs libva libxkbcommon dbus-libs gstreamer1-plugins-base libX11 libXtst libXi libXfixes libXrandr libXinerama libXcursor libxcb libwayland-client"
MISSING=""
for p in $DEPS; do
  rpm -q "$p" >/dev/null 2>&1 || MISSING="$MISSING $p"
done
if [ -n "$MISSING" ]; then
  echo "  устанавливаю:$MISSING"
  for p in $MISSING; do
    if ! $SUDO $PKG install -y "$p" </dev/null >/dev/null 2>&1; then
      echo "  ! пакет $p не установился — продолжаю (проверьте репозитории)"
    fi
  done
else
  echo "  всё уже установлено"
fi

# libxdo (инъекция клавиатуры/мыши) клиент загружает динамически; в базовых
# репозиториях RHEL его нет — подключаем EPEL. Без него управление не работает.
if ! rpm -q libxdo >/dev/null 2>&1 && ! rpm -q xdotool >/dev/null 2>&1; then
  echo "  подключаю EPEL для libxdo (управление клавиатурой/мышью)..."
  $SUDO $PKG install -y epel-release </dev/null >/dev/null 2>&1 \
    || $SUDO $PKG install -y "https://dl.fedoraproject.org/pub/epel/epel-release-latest-${VERSION_ID%%.*}.noarch.rpm" </dev/null >/dev/null 2>&1 \
    || true
  $SUDO $PKG install -y libxdo </dev/null >/dev/null 2>&1 \
    || $SUDO $PKG install -y xdotool </dev/null >/dev/null 2>&1 \
    || echo "  ! libxdo не установился (на CentOS Stream 10 / RHEL 10 EPEL пока без xdotool)"
fi

# --- пакет клиента ---
echo "[3/5] Устанавливаю клиент из RPM..."
if ! $SUDO $PKG install -y --nogpgcheck "$TMP/rustdesk.rpm" </dev/null; then
  echo "Ошибка: не удалось установить пакет (не хватает зависимостей из репозиториев)." >&2
  echo "Проверьте, что репозитории BaseOS/AppStream доступны: $PKG repolist" >&2
  exit 1
fi

# --- конфигурация: служба должна быть остановлена, иначе клиент перезапишет файл ---
echo "[4/5] Настраиваю сервер $SERVER..."
$SUDO systemctl stop rustdesk 2>/dev/null || true

# $1 = каталог конфигов клиента (например /root/.config/rustdesk)
write_cfg() {
  $SUDO mkdir -p "$1" 2>/dev/null || return 0
  printf "[options]\ncustom-rendezvous-server = '%s'\nrelay-server = '%s'\nkey = '%s'\n" \
    "$SERVER" "$RELAY" "$KEY" | $SUDO tee "$1/RustDesk2.toml" > /dev/null
  # верхнеуровневое поле rendezvous_server в RustDesk.toml приоритетнее — удаляем
  if [ -f "$1/RustDesk.toml" ]; then
    $SUDO sed -i '/^rendezvous_server *=/d' "$1/RustDesk.toml" 2>/dev/null || true
  fi
}

# служба (root) читает /root/.config/rustdesk, GUI-клиент — ~/.config/rustdesk
write_cfg "/root/.config/rustdesk"
for H in /home/*; do
  [ -d "$H" ] && write_cfg "$H/.config/rustdesk"
done
# запасное системное расположение
$SUDO mkdir -p /var/lib/rustdesk/RustDesk/config 2>/dev/null || true
write_cfg "/var/lib/rustdesk/RustDesk/config" || true

$SUDO systemctl daemon-reload 2>/dev/null || true
$SUDO systemctl enable rustdesk >/dev/null 2>&1 || true
$SUDO systemctl restart rustdesk 2>/dev/null || true
sleep 2
ACTIVE=$($SUDO systemctl is-active rustdesk 2>/dev/null || true)

# --- итог ---
echo "[5/5] Готово."
echo "Сервер: $SERVER (релей: $RELAY)"
echo "Служба rustdesk: ${ACTIVE:-неизвестно}"

if [ "${ACTIVE:-}" != "active" ]; then
  echo "Внимание: служба не запустилась. Последние строки журнала:" >&2
  $SUDO journalctl -u rustdesk -n 15 --no-pager 2>/dev/null || true
fi

ID=$($SUDO timeout 20 /usr/bin/rustdesk --get-id 2>/dev/null | grep -E '^[0-9]+$' | tail -n1 || true)
if [ -n "$ID" ]; then
  echo "ID этого компьютера: $ID"
else
  echo "ID получить не удалось (нужна графическая сессия или запущенная служба)."
fi

# --- предупреждения по среде ---
DEFAULT_TARGET=$($SUDO systemctl get-default 2>/dev/null || true)
if [ "$DEFAULT_TARGET" != "graphical.target" ]; then
  echo ""
  echo "Внимание: система загружается в $DEFAULT_TARGET (без графики)."
  echo "RustDesk показывает и принимает управление только при наличии рабочего стола"
  echo "(GNOME/KDE/Xorg). На сервере без GUI клиент установится, но управлять им нельзя."
fi

if command -v loginctl >/dev/null 2>&1; then
  for S in $(loginctl list-sessions --no-legend 2>/dev/null | awk '{print $1}'); do
    T=$(loginctl show-session "$S" -p Type --value 2>/dev/null || true)
    if [ "$T" = "wayland" ]; then
      echo ""
      echo "Внимание: сессия $S работает на Wayland. Для стабильного захвата экрана"
      echo "выберите на экране входа сессию «GNOME on Xorg» (шестерёнка в углу)."
      break
    fi
  done
fi

echo ""
echo "Если был открыт GUI клиента — закройте и запустите заново, чтобы он перечитал конфиг."
echo "Постоянный пароль: в клиенте Настройки -> Безопасность -> Постоянный пароль."
echo "Исходящие порты: UDP 555 (регистрация), TCP 556 (релей) — firewall на клиенте их не блокирует."
