#!/bin/bash

# --- GLOBAL VARS & COLORS ---
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m'

# --- ROOT CHECK ---
if [ "$EUID" -ne 0 ]; then
    echo -e "${RED}Пожалуйста, запустите скрипт от имени root${NC}"
    exit 1
fi

# --- HELPER FUNCTIONS ---

# Бэкап файла только если бэкапа еще нет
backup_file() {
    local file=$1
    if [ -f "$file" ]; then
        if [ ! -f "${file}.bak" ]; then
            cp "$file" "${file}.bak"
            echo -e "${GREEN}Бэкап создан: ${file}.bak${NC}"
        else
            echo -e "${YELLOW}Бэкап уже существует, пропускаем: ${file}.bak${NC}"
        fi
    fi
}

restore_file() {
    local file=$1
    if [ -f "${file}.bak" ]; then
        cp "${file}.bak" "$file"
        echo -e "${GREEN}Файл восстановлен из бэкапа: $file${NC}"
    else
        echo -e "${RED}Бэкап не найден!${NC}"
    fi
}

install_base_dependencies() {
    if ! command -v curl &> /dev/null || ! command -v git &> /dev/null; then
        echo -e "${BLUE}--- Установка зависимостей ---${NC}"
        apt-get update -qq
        apt-get install -y curl wget unzip git ufw socat jq certbot speedtest-cli cron nano dnsutils
    fi
    if ! command -v docker &> /dev/null; then
        echo -e "${YELLOW}Docker не найден, устанавливаем...${NC}"
        curl -fsSL https://get.docker.com | sh
    fi
}

pause_func() {
    read -p "Нажмите Enter, чтобы продолжить..."
}

# ==========================================
# 1. OPTIMIZATION MENU
# ==========================================

opt_toggle_ipv6() {
    backup_file "/etc/sysctl.conf"
    if grep -q "net.ipv6.conf.all.disable_ipv6 = 1" /etc/sysctl.conf; then
        # Включаем IPv6 (удаляем блокировку)
        sed -i '/net.ipv6.conf.all.disable_ipv6 = 1/d' /etc/sysctl.conf
        sed -i '/net.ipv6.conf.default.disable_ipv6 = 1/d' /etc/sysctl.conf
        sed -i '/net.ipv6.conf.lo.disable_ipv6 = 1/d' /etc/sysctl.conf
        echo -e "${GREEN}IPv6 Включен (строки блокировки удалены).${NC}"
    else
        # Выключаем IPv6
        echo "net.ipv6.conf.all.disable_ipv6 = 1" >> /etc/sysctl.conf
        echo "net.ipv6.conf.default.disable_ipv6 = 1" >> /etc/sysctl.conf
        echo "net.ipv6.conf.lo.disable_ipv6 = 1" >> /etc/sysctl.conf
        echo -e "${RED}IPv6 Выключен.${NC}"
    fi
    sysctl -p
    pause_func
}

opt_toggle_bbr() {
    backup_file "/etc/sysctl.conf"
    if grep -q "tcp_congestion_control = bbr" /etc/sysctl.conf; then
        sed -i '/net.core.default_qdisc = fq/d' /etc/sysctl.conf
        sed -i '/net.ipv4.tcp_congestion_control = bbr/d' /etc/sysctl.conf
        echo -e "${RED}BBR Выключен.${NC}"
    else
        echo "net.core.default_qdisc = fq" >> /etc/sysctl.conf
        echo "net.ipv4.tcp_congestion_control = bbr" >> /etc/sysctl.conf
        echo -e "${GREEN}BBR Включен.${NC}"
    fi
    sysctl -p
    pause_func
}

opt_rollback_sysctl() {
    restore_file "/etc/sysctl.conf"
    sysctl -p
    pause_func
}

opt_custom_dns() {
    backup_file "/etc/systemd/resolved.conf"
    mkdir -p /etc/systemd/resolved.conf.d/
    cat <<EOF > /etc/systemd/resolved.conf
[Resolve]
DNS=1.1.1.1 8.8.8.8
EOF
    systemctl restart systemd-resolved
    echo -e "${GREEN}DNS установлены на 1.1.1.1 и 8.8.8.8${NC}"
    pause_func
}

opt_restore_dns() {
    restore_file "/etc/systemd/resolved.conf"
    systemctl restart systemd-resolved
    pause_func
}

opt_kernel_xanmod() {
    echo -e "${BLUE}Установка XanMod...${NC}"
    
    # Репозиторий
    wget -qO - https://dl.xanmod.org/archive.key | gpg --dearmor -o /usr/share/keyrings/xanmod-archive-keyring.gpg --yes
    echo 'deb [signed-by=/usr/share/keyrings/xanmod-archive-keyring.gpg] http://deb.xanmod.org releases main' | tee /etc/apt/sources.list.d/xanmod-release.list
    apt-get update
    
    # Версия CPU
    wget -qO - https://dl.xanmod.org/check_x86-64_psabi.sh | awk -f - > /tmp/cpu_version
    CPU_VER=$(cat /tmp/cpu_version)
    
    # Установка
    if [[ "$CPU_VER" == *"v3"* ]] || [[ "$CPU_VER" == *"v4"* ]]; then
        apt-get install -y linux-xanmod-edge-x64v3
    elif [[ "$CPU_VER" == *"v2"* ]]; then
        apt-get install -y linux-xanmod-edge-x64v2
    else
        apt-get install -y linux-xanmod-edge-x64v1
    fi
    rm /tmp/cpu_version

    # GRUB Fix
    echo -e "${YELLOW}Настройка приоритета загрузки GRUB...${NC}"
    backup_file "/etc/default/grub"
    sed -i 's/^GRUB_DEFAULT=.*/GRUB_DEFAULT=0/' /etc/default/grub
    sed -i 's/^GRUB_TIMEOUT=.*/GRUB_TIMEOUT=5/' /etc/default/grub
    update-grub
    
    echo -e "${GREEN}Ядро установлено. Приоритет выставлен.${NC}"
    
    # Запрос на перезагрузку
    read -p "Перезагрузить сервер сейчас для применения изменений? (y/n): " REBOOT_ASK
    if [[ "$REBOOT_ASK" =~ ^[Yy]$ ]]; then
        echo -e "${YELLOW}Перезагрузка...${NC}"
        reboot
    else
        echo -e "${YELLOW}Не забудьте перезагрузиться вручную!${NC}"
        pause_func
    fi
}

opt_rollback_kernel() {
    echo -e "${RED}--- Откат ядра на стандартное (Generic) ---${NC}"
    
    # 1. Установка Generic
    echo -e "${YELLOW}Установка стандартного ядра (linux-generic)...${NC}"
    apt-get update
    apt-get install --reinstall -y linux-generic linux-headers-generic linux-image-generic
    
    # 2. Удаление XanMod
    echo -e "${YELLOW}Поиск и удаление пакетов XanMod...${NC}"
    XANMOD_PACKAGES=$(dpkg --list | grep -E 'xanmod' | awk '{print $2}')
    
    if [ -n "$XANMOD_PACKAGES" ]; then
        echo -e "Удаляем: $XANMOD_PACKAGES"
        apt-get purge -y $XANMOD_PACKAGES
    else
        echo -e "${GREEN}Пакеты XanMod не найдены.${NC}"
    fi
    
    # 3. Чистка
    echo -e "${YELLOW}Очистка и обновление загрузчика...${NC}"
    apt-get autoremove -y
    update-grub
    
    # 4. Удаление репозитория
    rm -f /etc/apt/sources.list.d/xanmod-release.list
    
    echo -e "${GREEN}XanMod удален, Generic восстановлен.${NC}"
    
    # Запрос на перезагрузку
    read -p "Перезагрузить сервер сейчас для применения изменений? (y/n): " REBOOT_ASK
    if [[ "$REBOOT_ASK" =~ ^[Yy]$ ]]; then
        echo -e "${YELLOW}Перезагрузка...${NC}"
        reboot
    else
        echo -e "${YELLOW}Не забудьте перезагрузиться вручную!${NC}"
        pause_func
    fi
}

menu_optimization() {
    while true; do
        echo -e "\n${CYAN}--- ОПТИМИЗАЦИЯ СИСТЕМЫ ---${NC}"
        echo "1. Вкл/Выкл IPv6"
        echo "2. Вкл/Выкл BBR"
        echo "3. Откат файла sysctl.conf (BBR/IPv6)"
        echo "4. Установить DNS (1.1.1.1)"
        echo "5. Восстановить дефолтный DNS"
        echo "6. Установить ядро XanMod"
        echo "7. Удалить ядро XanMod (Откат)"
        echo "0. Назад"
        read -p "Выбор: " opt_c
        case $opt_c in
            1) opt_toggle_ipv6 ;;
            2) opt_toggle_bbr ;;
            3) opt_rollback_sysctl ;;
            4) opt_custom_dns ;;
            5) opt_restore_dns ;;
            6) opt_kernel_xanmod ;;
            7) opt_rollback_kernel ;;
            0) return ;;
            *) echo "Ошибка";;
        esac
    done
}

# ==========================================
# 2. REMNAWAVE MANAGEMENT
# ==========================================

rw_install_panel() {
    install_base_dependencies
    echo -e "${BLUE}--- Установка Панели ---${NC}"
    
    # 1. Создаем сеть (игнорируем ошибку, если уже есть)
    docker network create remnawave-network 2>/dev/null || true

    mkdir -p /opt/remnawave
    cd /opt/remnawave || exit
    
    # 2. Скачивание
	if ! curl -fsSL -o docker-compose.yml https://raw.githubusercontent.com/remnawave/backend/refs/heads/main/docker-compose-prod.yml; then
		echo -e "${RED}ОШИБКА: Не удалось скачать!${NC}"
		echo -e "Проверьте подключение к интернету или доступность GitHub."
		exit 1
	fi

	if ! curl -fsSL -o .env https://raw.githubusercontent.com/remnawave/backend/refs/heads/main/.env.sample; then
		echo -e "${RED}ОШИБКА: Не удалось скачать!${NC}"
		echo -e "Проверьте подключение к интернету или доступность GitHub."
		exit 1
	fi

    # 3. Подключаем панель к сети через override
    cat <<EOF > docker-compose.override.yml
services:
  remnawave:
    networks:
      - remnawave-network
networks:
  remnawave-network:
    external: true
EOF

    # 4. Генерация ключей
    echo -e "${YELLOW}Генерация ключей...${NC}"
    sed -i "s/^JWT_AUTH_SECRET=.*/JWT_AUTH_SECRET=$(openssl rand -hex 64)/" .env
    sed -i "s/^JWT_API_TOKENS_SECRET=.*/JWT_API_TOKENS_SECRET=$(openssl rand -hex 64)/" .env
    sed -i "s/^METRICS_PASS=.*/METRICS_PASS=$(openssl rand -hex 64)/" .env
    sed -i "s/^WEBHOOK_SECRET_HEADER=.*/WEBHOOK_SECRET_HEADER=$(openssl rand -hex 64)/" .env
    
    DB_PASS=$(openssl rand -hex 24)
    sed -i "s/^POSTGRES_PASSWORD=.*/POSTGRES_PASSWORD=$DB_PASS/" .env
    sed -i "s|^\\(DATABASE_URL=\"postgresql://postgres:\\)[^\\@]*\\(@.*\\)|\\1$DB_PASS\\2|" .env

	while [[ -z "$SUB_DOMAIN" ]]; do
        read -p "Введите домен для страницы подписки (например, sub.domain.com): " SUB_DOMAIN
        if [[ -z "$SUB_DOMAIN" ]]; then
            echo -e "${RED}Ошибка: Домен не может быть пустым!${NC}"
        fi
    done
    if [ -n "$SUB_DOMAIN" ]; then
        sed -i "s/SUB_PUBLIC_DOMAIN=.*/SUB_PUBLIC_DOMAIN=$SUB_DOMAIN/" .env
    fi

    # Запуск панели
    echo -e "${YELLOW}Запуск контейнеров панели...${NC}"
	if ! docker compose up -d; then
		echo -e "${RED}ОШИБКА: Не удалось запустить Docker контейнеры!${NC}"
		echo -e "${YELLOW}Возможно, заняты порты или ошибка в конфиге.${NC}"
		# Тут можно предложить посмотреть логи: docker compose logs
		return 1
	fi
    echo -e "${GREEN}Панель запущена.${NC}"

    # === ТАЙМЕР ===
    echo -e "${CYAN}Ожидание инициализации базы данных и API (15 сек)...${NC}"
    for i in {15..1}; do
        echo -ne "Осталось: $i \r"
        sleep 1
    done
    echo -e "\n${GREEN}Готово. Продолжаем настройку...${NC}"

    # --- ПОДПИСКА ---
    read -p "Установить страницу подписки? (y/n): " INSTALL_SUB
    
    if [[ "$INSTALL_SUB" =~ ^[Yy]$ ]]; then
        mkdir -p /opt/remnawave/subscription
        cd /opt/remnawave/subscription || exit
        
        echo -e "${YELLOW}Скачивание app-config.json...${NC}"
        # Исправленная ссылка
        wget -O app-config.json https://raw.githubusercontent.com/legiz-ru/my-remnawave/main/sub-page/app-config.json
        
        if [ ! -s app-config.json ]; then
            echo "{}" > app-config.json
        fi

        echo -e "${CYAN}Настройка внешнего вида:${NC}"
        read -p "Meta Title: " META_TITLE
        read -p "Meta Description: " META_DESC
        META_TITLE=${META_TITLE:-"Subscription page"}
        META_DESC=${META_DESC:-"Subscription page description"}

        # Docker Compose Подписки
        cat <<EOF > docker-compose.yml
services:
    remnawave-subscription-page:
        image: remnawave/subscription-page:latest
        container_name: remnawave-subscription-page
        hostname: remnawave-subscription-page
        restart: always
        env_file:
            - .env
        volumes:
            - ./app-config.json:/opt/app/frontend/assets/app-config.json
        ports:
            - '127.0.0.1:3010:3010'
        networks:
            - remnawave-network

networks:
    remnawave-network:
        external: true
EOF

        cat <<EOF > .env
APP_PORT=3010
REMNAWAVE_PANEL_URL=http://remnawave:3000
META_TITLE="$META_TITLE"
META_DESCRIPTION="$META_DESC"
EOF
        
        echo -e "${YELLOW}Запуск контейнера подписки...${NC}"
        if ! docker compose up -d; then
			echo -e "${RED}ОШИБКА: Не удалось запустить Docker контейнеры!${NC}"
			echo -e "${YELLOW}Возможно, заняты порты или ошибка в конфиге.${NC}"
			# Тут можно предложить посмотреть логи: docker compose logs
			return 1
		fi
        echo -e "${GREEN}Подписка установлена.${NC}"
    else
        echo "Пропущено."
    fi
    pause_func
}

rw_remove_panel() {
    echo -e "${RED}ВНИМАНИЕ! Это действие необратимо!${NC}"
    echo -e "Будут удалены:"
    echo -e "- Панель и база данных (ВКЛЮЧАЯ VOLUMES)"
    echo -e "- Страница подписки"
    echo -e "- Nginx (Reverse Proxy)"
    echo -e "- Все SSL сертификаты и конфиги"
    echo -e "- Сеть Docker 'remnawave-network'"
    
    read -p "Вы уверены? (введите 'yes' для подтверждения): " CONFIRM
    if [ "$CONFIRM" == "yes" ]; then
        echo -e "${YELLOW}Остановка контейнеров и удаление volumes...${NC}"
        
        # Флаг -v удаляет связанные volumes (базу данных)
        if [ -d "/opt/remnawave/nginx" ]; then
            cd /opt/remnawave/nginx && docker compose down -v 2>/dev/null
        fi
        
        if [ -d "/opt/remnawave/subscription" ]; then
            cd /opt/remnawave/subscription && docker compose down -v 2>/dev/null
        fi
        
        if [ -d "/opt/remnawave" ]; then
            cd /opt/remnawave && docker compose down -v 2>/dev/null
        fi
        
        echo -e "${YELLOW}Удаление сети...${NC}"
        docker network rm remnawave-network 2>/dev/null
        
        echo -e "${YELLOW}Удаление файлов...${NC}"
        rm -rf /opt/remnawave
        
        # Дополнительная зачистка "осиротевших" томов, если вдруг имена не совпали
        echo -e "${YELLOW}Зачистка неиспользуемых томов Remnawave...${NC}"
        # Удаляем volume с именем 'remnawave_postgres_data' (стандартное имя)
        docker volume rm remnawave_postgres_data 2>/dev/null || true
        
        echo -e "${GREEN}Все компоненты Remnawave и данные успешно удалены.${NC}"
    else
        echo "Отмена."
    fi
    pause_func
}

rw_install_node() {
    install_base_dependencies
    echo -e "${BLUE}--- Установка Ноды ---${NC}"
    mkdir -p /opt/remnanode
    cd /opt/remnanode || exit
    
    # Ввод данных
	while true; do
        read -p "Введите NODE_PORT (например, 2222): " NODE_PORT
        
        if [[ -z "$NODE_PORT" ]]; then
            echo -e "${RED}Ошибка: Порт не может быть пустым!${NC}"
        elif ! [[ "$NODE_PORT" =~ ^[0-9]+$ ]]; then
            echo -e "${RED}Ошибка: Порт должен содержать только цифры!${NC}"
        elif (( NODE_PORT < 1 || NODE_PORT > 65535 )); then
            echo -e "${RED}Ошибка: Порт должен быть в диапазоне 1-65535!${NC}"
        else
            break # Всё ок, выходим из цикла
        fi
    done
    
    # Проверка занятости порта
    if lsof -Pi :"$NODE_PORT" -sTCP:LISTEN -t >/dev/null ; then
        echo -e "${RED}Внимание: Порт $NODE_PORT уже занят!${NC}"
        lsof -i :"$NODE_PORT"
        read -p "Продолжить все равно? (y/n): " FORCE_PORT
        if [[ ! "$FORCE_PORT" =~ ^[Yy]$ ]]; then return; fi
    fi

    # Если ключ пустой, ругаемся
	while [[ -z "$NODE_SECRET" ]]; do
        read -p "Введите SECRET_KEY (скопируйте из Панели -> Nodes -> Add -> Secret Key): " NODE_SECRET
        if [[ -z "$NODE_SECRET" ]]; then
            echo -e "${RED}Ошибка: SECRET_KEY не может быть пустым!${NC}"
        fi
    done
    
    # Настройка ротации логов
    mkdir -p /var/log/remnanode
    cat <<EOF > /etc/logrotate.d/remnanode
/var/log/remnanode/*.log {
    size 50M rotate 5 compress missingok notifempty copytruncate
}
EOF

    # Генерация docker-compose.yml (с правильными отступами)
    # Используем кавычки для SECRET_KEY, так как там спецсимволы
    cat <<EOF > docker-compose.yml
services:
  remnanode:
    container_name: remnanode
    hostname: remnanode
    image: remnawave/node:latest
    network_mode: host
    restart: always
    environment:
      - NODE_PORT=$NODE_PORT
      - SECRET_KEY='$NODE_SECRET'
    volumes:
      - "/var/log/remnanode:/var/log/remnanode"
EOF
    
    # Запуск
    echo -e "${YELLOW}Запуск ноды...${NC}"
	if ! docker compose up -d; then
		echo -e "${RED}ОШИБКА: Не удалось запустить Docker контейнеры!${NC}"
		echo -e "${YELLOW}Возможно, заняты порты или ошибка в конфиге.${NC}"
		# Тут можно предложить посмотреть логи: docker compose logs
		return 1
	fi
    
    # АВТОМАТИЧЕСКОЕ ОТКРЫТИЕ ПОРТА В UFW
    # Если UFW включен, порт 2000/2222 будет закрыт, и панель не увидит ноду
    if ufw status | grep -q "Status: active"; then
        echo -e "${YELLOW}UFW активен. Настраиваем доступ к порту $NODE_PORT...${NC}"
        
        # Получаем IP панели (в данном случае 127.0.0.1 не сработает, если стучимся через внешний IP)
        # Лучше открыть для всех или спросить IP панели
        echo "1. Открыть порт $NODE_PORT для ВСЕХ (проще, но менее безопасно)"
        echo "2. Открыть порт $NODE_PORT только для IP Панели"
        read -p "Выбор (1/2): " UFW_CHOICE
        
        if [ "$UFW_CHOICE" == "2" ]; then
            read -p "Введите IP Панели: " PANEL_IP
            # Пытаемся зарезолвить, если введен домен
            if [[ "$PANEL_IP" =~ [a-zA-Z] ]]; then
                PANEL_IP=$(getent hosts "$PANEL_IP" | awk '{ print $1 }' | head -n 1)
            fi
            
            if [ -n "$PANEL_IP" ]; then
                ufw allow from "$PANEL_IP" to any port "$NODE_PORT" proto tcp
                echo -e "${GREEN}Доступ разрешен для $PANEL_IP${NC}"
            else
                echo -e "${RED}Некорректный IP, порт не открыт!${NC}"
            fi
        else
            # Открываем для всех (дефолт)
            ufw allow "$NODE_PORT"/tcp
            echo -e "${GREEN}Порт $NODE_PORT открыт для всех.${NC}"
        fi
        
        ufw reload
    fi
    
    echo -e "${GREEN}Нода установлена и запущена.${NC}"
    pause_func
}

rw_remove_node() {
    echo -e "${RED}ВНИМАНИЕ! Вы собираетесь удалить Ноду.${NC}"
    read -p "Вы уверены? (type 'yes'): " CONFIRM
    if [ "$CONFIRM" == "yes" ]; then
        echo -e "${YELLOW}Остановка контейнера...${NC}"
        if [ -d "/opt/remnanode" ]; then
            cd /opt/remnanode && docker compose down
            
            # Пытаемся найти порт из конфига, чтобы предложить закрыть его в UFW
            NODE_PORT=$(grep "NODE_PORT=" docker-compose.yml | cut -d= -f2)
            # Если в env файле или переменной, логика сложнее, но попробуем простой grep
            if [ -z "$NODE_PORT" ]; then
                # Пробуем найти внутри файла, если формат NODE_PORT: 2000
                NODE_PORT=$(grep "NODE_PORT" docker-compose.yml | awk '{print $2}' | tr -d '"' | tr -d "'")
            fi
        fi

        echo -e "${YELLOW}Удаление файлов...${NC}"
        rm -rf /opt/remnanode
        rm -f /etc/logrotate.d/remnanode
        
        # Удаляем логи
        read -p "Удалить логи ноды (/var/log/remnanode)? (y/n): " DEL_LOGS
        if [[ "$DEL_LOGS" =~ ^[Yy]$ ]]; then
            rm -rf /var/log/remnanode
        fi

        # Удаление правила UFW
        if [ -n "$NODE_PORT" ]; then
            echo -e "${YELLOW}Обнаружен порт ноды: $NODE_PORT${NC}"
            read -p "Удалить правило UFW для порта $NODE_PORT? (y/n): " DEL_UFW
            if [[ "$DEL_UFW" =~ ^[Yy]$ ]]; then
                ufw delete allow "$NODE_PORT"/tcp
                # На случай, если было правило 'allow from IP' - оно сложнее удаляется по порту
                # ufw delete allow from ... (сложно угадать IP), поэтому удаляем только простое allow PORT
                echo -e "Попытка удаления правила UFW завершена."
            fi
        fi
        
        echo -e "${GREEN}Нода удалена.${NC}"
    else
        echo "Отмена."
    fi
    pause_func
}


rw_setup_proxy() {
    install_base_dependencies
	NGINX_CONF_DIR="/opt/remnawave/nginx"
    mkdir -p "$NGINX_CONF_DIR"
    echo -e "${BLUE}--- Настройка Nginx и SSL ---${NC}"
    
    # 1. Установка acme.sh с валидацией почты
    if [ ! -d "/root/.acme.sh" ]; then
        while true; do
            read -p "Введите ваш Email для Let's Encrypt: " LE_EMAIL
            # Простой Regex для email
            if [[ "$LE_EMAIL" =~ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; then
                break
            else
                echo -e "${RED}Некорректный email! Попробуйте снова.${NC}"
            fi
        done
        
        curl https://get.acme.sh | sh -s email="$LE_EMAIL"
        source ~/.bashrc
    fi

    echo -e "Выберите тип сертификата:"
    echo -e "1) ${GREEN}Wildcard (*.domain.com)${NC} - требуется Cloudflare API"
    echo -e "2) ${GREEN}Обычный (Standalone)${NC} - для панели и подписки отдельно"
    read -r CERT_CHOICE

    
    # Очистка мусорных папок, если docker по ошибке создал директории вместо файлов
    rm -rf "$NGINX_CONF_DIR"/*.key "$NGINX_CONF_DIR"/*.pem 2>/dev/null

    # Переменные для путей
    CERT_PANEL=""
    KEY_PANEL=""
    CERT_SUB=""
    KEY_SUB=""
    
    if [ "$CERT_CHOICE" == "1" ]; then
        # ... (Ввод данных Cloudflare) ...
		while [[ -z "$MAIN_DOMAIN" ]]; do
			read -p "Введите основной домен (например, domain.com): " MAIN_DOMAIN
			if [[ -z "$MAIN_DOMAIN" ]]; then
				echo -e "${RED}Ошибка: Домен не может быть пустым!${NC}"
			fi
		done

        while [[ -z "$CF_KEY" ]]; do
			read -p "Введите Cloudflare Global API Key (или Token): " CF_KEY
			CF_KEY=$(echo "$CF_KEY" | xargs)
			if [[ -z "$CF_KEY" ]] || [[ ${#CF_KEY} -lt 20 ]]; then
			   echo -e "${RED}Подозрительно короткий ключ. Проверьте данные!${NC}"
			fi
		done
		
		while [[ -z "$CF_ID" ]]; do
			read -p "Введите Cloudflare Account ID: " CF_ID
			CF_ID=$(echo "$CF_KEY" | xargs)
			if [[ -z "$CF_ID" ]] || [[ ${#CF_ID} -lt 20 ]]; then
			   echo -e "${RED}Подозрительно короткий Account ID. Проверьте данные!${NC}"
			fi
		done
        export CF_Token="$CF_KEY"; export CF_Account_ID="$CF_ID"
        
        # 1. Выпускаем сертификат (сохраняется в ~/.acme.sh)
        # --force на случай, если уже есть
        /root/.acme.sh/acme.sh --issue --dns dns_cf \
        -d "$MAIN_DOMAIN" -d "*.$MAIN_DOMAIN" --force
		if [ $? -ne 0 ]; then
			echo -e "${RED}ОШИБКА: Не удалось выпустить сертификат через Cloudflare!${NC}"
			echo -e "${YELLOW}Проверьте API Key, Account ID и правильность домена.${NC}"
			return 1  # Выход из функции, чтобы не ломать Nginx
		fi
        
        # 2. Устанавливаем сертификат в папку Nginx и прописываем reloadcmd
        # Добавляем "|| true", чтобы ошибка "контейнер не найден" при ПЕРВОЙ установке не пугала
        /root/.acme.sh/acme.sh --install-cert -d "$MAIN_DOMAIN" \
        --key-file "$NGINX_CONF_DIR/wildcard.key" \
        --fullchain-file "$NGINX_CONF_DIR/wildcard.pem" \
        --reloadcmd "docker exec remnawave-nginx nginx -s reload || true"
        
        PANEL_DOMAIN="panel.$MAIN_DOMAIN"
        SUB_DOMAIN="sub.$MAIN_DOMAIN"
        
        echo -e "${YELLOW}Предполагаемые поддомены: $PANEL_DOMAIN и $SUB_DOMAIN${NC}"
        read -p "Использовать их? (y/n - n для ручного ввода): " DOMAIN_CONFIRM
        if [[ "$DOMAIN_CONFIRM" =~ ^[Nn]$ ]]; then
             read -p "Введите полный домен ПАНЕЛИ: " PANEL_DOMAIN
             read -p "Введите полный домен ПОДПИСКИ: " SUB_DOMAIN
        fi
        
        # Для Wildcard пути одинаковые
        CERT_PANEL="/etc/nginx/ssl/wildcard.pem"
        KEY_PANEL="/etc/nginx/ssl/wildcard.key"
        CERT_SUB="/etc/nginx/ssl/wildcard.pem"
        KEY_SUB="/etc/nginx/ssl/wildcard.key"

	else
        # --- STANDALONE ---
		while [[ -z "$PANEL_DOMAIN" ]]; do
			read -p "Введите домен для ПАНЕЛИ (panel.domain.com): " PANEL_DOMAIN
			if [[ -z "$PANEL_DOMAIN" ]]; then
				echo -e "${RED}Ошибка: Домен не может быть пустым!${NC}"
			fi
		done
		while [[ -z "$SUB_DOMAIN" ]]; do
			read -p "Введите домен для ПОДПИСКИ (sub.domain.com): " SUB_DOMAIN
			if [[ -z "$SUB_DOMAIN" ]]; then
				echo -e "${RED}Ошибка: Домен не может быть пустым!${NC}"
			fi
		done
        
        echo -e "${YELLOW}Остановка Nginx для освобождения 80 порта...${NC}"
        # Игнорируем ошибку, если контейнера нет
        docker stop remnawave-nginx 2>/dev/null || true
        
        # Получение сертификатов
        # Добавляем "|| true" в хуки, чтобы ошибка "No such container" не ломала процесс
        echo -e "${CYAN}Выпуск сертификата для Панели ($PANEL_DOMAIN)...${NC}"
        /root/.acme.sh/acme.sh --issue --standalone -d "$PANEL_DOMAIN" --force \
        --pre-hook "docker stop remnawave-nginx || true" \
        --post-hook "docker start remnawave-nginx || true"
        
        /root/.acme.sh/acme.sh --install-cert -d "$PANEL_DOMAIN" \
        --key-file "$NGINX_CONF_DIR/privkey.key" \
        --fullchain-file "$NGINX_CONF_DIR/fullchain.pem"
		
		if [ ! -f "$NGINX_CONF_DIR/fullchain.pem" ] || [ ! -s "$NGINX_CONF_DIR/fullchain.pem" ]; then
			echo -e "${RED}ОШИБКА: Файл сертификата не найден или пуст!${NC}"
			echo -e "${YELLOW}Nginx не запустится без сертификатов. Прерываем настройку.${NC}"
			return 1
		fi
        
        echo -e "${CYAN}Выпуск сертификата для Подписки ($SUB_DOMAIN)...${NC}"
        /root/.acme.sh/acme.sh --issue --standalone -d "$SUB_DOMAIN" --force \
        --pre-hook "docker stop remnawave-nginx || true" \
        --post-hook "docker start remnawave-nginx || true"
        
        /root/.acme.sh/acme.sh --install-cert -d "$SUB_DOMAIN" \
        --key-file "$NGINX_CONF_DIR/subdomain_privkey.key" \
        --fullchain-file "$NGINX_CONF_DIR/subdomain_fullchain.pem"
		
		if [ ! -f "$NGINX_CONF_DIR/subdomain_privkey.pem" ] || [ ! -s "$NGINX_CONF_DIR/subdomain_fullchain.pem" ]; then
			echo -e "${RED}ОШИБКА: Файл сертификата не найден или пуст!${NC}"
			echo -e "${YELLOW}Nginx не запустится без сертификатов. Прерываем настройку.${NC}"
			return 1
		fi
        
        CERT_PANEL="/etc/nginx/ssl/fullchain.pem"
        KEY_PANEL="/etc/nginx/ssl/privkey.key"
        CERT_SUB="/etc/nginx/ssl/subdomain_fullchain.pem"
        KEY_SUB="/etc/nginx/ssl/subdomain_privkey.key"
    fi

    # Генерация Полного Nginx Conf
    cd "$NGINX_CONF_DIR" || exit
    
    cat <<EOF > nginx.conf
upstream remnawave {
    server remnawave:3000;
}

upstream remnawave-subscription-page {
    server remnawave-subscription-page:3010;
}

server {
    server_name $PANEL_DOMAIN;

    listen 443 ssl reuseport;
    listen [::]:443 ssl reuseport;
    http2 on;

    location / {
        proxy_http_version 1.1;
        proxy_pass http://remnawave;
        proxy_set_header Host \$host;
        proxy_set_header X-Real-IP \$remote_addr;
        proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto \$scheme;
    }

    # SSL Configuration (Mozilla Intermediate Guidelines)
    ssl_protocols          TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305;

    ssl_session_timeout 1d;
    ssl_session_cache shared:MozSSL:10m;
    ssl_session_tickets    off;
    
    # Пути сертификатов (внутри контейнера)
    ssl_certificate "$CERT_PANEL";
    ssl_certificate_key "$KEY_PANEL";
    ssl_trusted_certificate "$CERT_PANEL";

    ssl_stapling           on;
    ssl_stapling_verify    on;
    resolver               1.1.1.1 1.0.0.1 8.8.8.8 8.8.4.4 208.67.222.222 208.67.220.220 valid=60s;
    resolver_timeout       2s;

    # Gzip Compression
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_buffers 16 8k;
    gzip_http_version 1.1;
    gzip_min_length 256;
    gzip_types
        application/atom+xml
        application/geo+json
        application/javascript
        application/x-javascript
        application/json
        application/ld+json
        application/manifest+json
        application/rdf+xml
        application/rss+xml
        application/xhtml+xml
        application/xml
        font/eot
        font/otf
        font/ttf
        image/svg+xml
        text/css
        text/javascript
        text/plain
        text/xml;
}

server {
    server_name $SUB_DOMAIN;

    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;

    location / {
        proxy_http_version 1.1;
        proxy_pass http://remnawave-subscription-page;
        proxy_set_header Host \$host;
        proxy_set_header X-Real-IP \$remote_addr;
        proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto \$scheme;
        proxy_set_header X-Forwarded-Host \$host;
        proxy_set_header X-Forwarded-Port \$server_port;

        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }

    # SSL Configuration (Mozilla Intermediate Guidelines)
    ssl_protocols          TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305;

    ssl_session_timeout 1d;
    ssl_session_cache shared:MozSSL:10m;
    ssl_session_tickets    off;
    
    # Пути сертификатов (внутри контейнера)
    ssl_certificate "$CERT_SUB";
    ssl_certificate_key "$KEY_SUB";
    ssl_trusted_certificate "$CERT_SUB";

    ssl_stapling           on;
    ssl_stapling_verify    on;
    resolver               1.1.1.1 1.0.0.1 8.8.8.8 8.8.4.4 208.67.222.222 208.67.220.220 valid=60s;
    resolver_timeout       2s;

    # Gzip Compression
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_buffers 16 8k;
    gzip_http_version 1.1;
    gzip_min_length 256;
    gzip_types
        application/atom+xml
        application/geo+json
        application/javascript
        application/x-javascript
        application/json
        application/ld+json
        application/manifest+json
        application/rdf+xml
        application/rss+xml
        application/xhtml+xml
        application/xml
        font/eot
        font/otf
        font/ttf
        image/svg+xml
        text/css
        text/javascript
        text/plain
        text/xml;
}

server {
    listen 443 ssl default_server;
    listen [::]:443 ssl default_server;
    server_name _;

    ssl_reject_handshake on;
}
EOF

    # Docker Compose Nginx (Исправленный формат)
    cat <<EOF > docker-compose.yml
services:
    remnawave-nginx:
        image: nginx:1.28
        container_name: remnawave-nginx
        hostname: remnawave-nginx
        restart: always
        ports:
            - '0.0.0.0:443:443'
        volumes:
            - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
EOF
    if [ "$CERT_CHOICE" == "1" ]; then
        echo "            - ./wildcard.pem:/etc/nginx/ssl/wildcard.pem:ro" >> docker-compose.yml
        echo "            - ./wildcard.key:/etc/nginx/ssl/wildcard.key:ro" >> docker-compose.yml
    else
        echo "            - ./fullchain.pem:/etc/nginx/ssl/fullchain.pem:ro" >> docker-compose.yml
        echo "            - ./privkey.key:/etc/nginx/ssl/privkey.key:ro" >> docker-compose.yml
        echo "            - ./subdomain_fullchain.pem:/etc/nginx/ssl/subdomain_fullchain.pem:ro" >> docker-compose.yml
        echo "            - ./subdomain_privkey.key:/etc/nginx/ssl/subdomain_privkey.key:ro" >> docker-compose.yml
    fi
    
    # Закрываем services и добавляем networks
    cat <<EOF >> docker-compose.yml
        networks:
            - remnawave-network

networks:
    remnawave-network:
        name: remnawave-network
        driver: bridge
        external: true
EOF

    if ! docker compose up -d; then
		echo -e "${RED}ОШИБКА: Не удалось запустить Docker контейнеры!${NC}"
		echo -e "${YELLOW}Возможно, заняты порты или ошибка в конфиге.${NC}"
		# Тут можно предложить посмотреть логи: docker compose logs
		return 1
	fi
    echo -e "${GREEN}Nginx запущен!${NC}"
    pause_func
}

rw_setup_sni_fallback() {
    install_base_dependencies
    
    # Пути
    BASE_DIR="/opt/remnawave/nginx"
    HTML_DIR="$BASE_DIR/html"
    CONF_FILE="$BASE_DIR/nginx.conf"
    COMPOSE_FILE="$BASE_DIR/docker-compose.yml"
    
    echo -e "${BLUE}--- Настройка SNI Fallback (Заглушка Reality) ---${NC}"
    echo "Эта функция подготовит локальный веб-сервер для маскировки."
    
    while [[ -z "$SNI_DOMAIN" ]]; do
        read -p "Введите домен для заглушки (например, node1.domain.com): " SNI_DOMAIN
        if [[ -z "$SNI_DOMAIN" ]]; then
            echo -e "${RED}Ошибка: Домен не может быть пустым!${NC}"
        fi
    done

    # 2. Проверка порта (не пустой + только цифры + диапазон 1-65535)
    while true; do
        read -p "Введите порт для заглушки (например, 9443): " FALLBACK_PORT
        
        if [[ -z "$FALLBACK_PORT" ]]; then
            echo -e "${RED}Ошибка: Порт не может быть пустым!${NC}"
        elif ! [[ "$FALLBACK_PORT" =~ ^[0-9]+$ ]]; then
            echo -e "${RED}Ошибка: Порт должен содержать только цифры!${NC}"
        elif (( FALLBACK_PORT < 1 || FALLBACK_PORT > 65535 )); then
            echo -e "${RED}Ошибка: Порт должен быть в диапазоне 1-65535!${NC}"
        else
            break # Всё ок, выходим из цикла
        fi
    done
    
    # --- ШАГ 0: Проверка режима (Панель или Чистая Нода) ---
    IS_PANEL_SERVER=false
    if [ -f "$CONF_FILE" ] && grep -q "upstream remnawave" "$CONF_FILE"; then
        IS_PANEL_SERVER=true
        echo -e "${YELLOW}Обнаружена конфигурация Панели. Будем интегрироваться.${NC}"
    else
        echo -e "${YELLOW}Конфигурация Панели не найдена. Режим 'Чистая Нода'.${NC}"
        mkdir -p "$BASE_DIR"
    fi

    # Создаем папку и HTML
    mkdir -p "$HTML_DIR"
    
    echo -e "${YELLOW}Генерация sni.html...${NC}"
    cat <<'EOF' > "$HTML_DIR/sni.html"
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>System Status</title>
    <style>
        :root {
            --bg: #0b0f19;
            --surface: rgba(23, 33, 53, 0.9); /* Чуть темнее для читаемости */
            --primary: #3b82f6;
            --text: #e2e8f0;
            --text-dim: #94a3b8;
            --green: #10b981;
            --red: #ef4444;
            --font-mono: 'Fira Code', 'Consolas', monospace;
        }

        body {
            margin: 0;
            background: var(--bg);
            color: var(--text);
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
            overflow: hidden;
            height: 100vh;
            display: flex;
            align-items: center;
            justify-content: center;
        }

        #bg-canvas {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            z-index: 0;
            /* Убрали opacity в CSS, будем регулировать в JS */
        }

        .card {
            position: relative;
            z-index: 10;
            background: var(--surface);
            backdrop-filter: blur(20px);
            -webkit-backdrop-filter: blur(20px);
            border: 1px solid rgba(255,255,255,0.08);
            border-radius: 16px;
            padding: 40px;
            width: 90%;
            max-width: 500px;
            box-shadow: 0 25px 50px -12px rgba(0,0,0,0.6);
            animation: fadeIn 0.6s ease-out;
        }

        .header {
            display: flex;
            align-items: center;
            gap: 16px;
            margin-bottom: 24px;
            padding-bottom: 20px;
            border-bottom: 1px solid rgba(255,255,255,0.05);
        }

        .status-dot {
            width: 12px;
            height: 12px;
            background: var(--red);
            border-radius: 50%;
            box-shadow: 0 0 12px var(--red);
            animation: blink 2s infinite;
        }

        h1 { margin: 0; font-size: 1.25rem; font-weight: 600; }
        .subtitle { font-size: 0.875rem; color: var(--text-dim); }

        .message-box { margin-bottom: 30px; }
        .title { 
            font-size: 1.5rem; 
            font-weight: 700; 
            margin-bottom: 10px; 
            background: linear-gradient(90deg, #fff, #94a3b8); 
            -webkit-background-clip: text; 
            -webkit-text-fill-color: transparent; 
        }
        .desc { color: var(--text-dim); line-height: 1.6; font-size: 0.95rem; }

        .terminal {
            background: #000;
            border-radius: 8px;
            padding: 16px;
            font-family: var(--font-mono);
            font-size: 0.75rem;
            color: var(--green);
            height: 140px; /* Чуть выше */
            overflow: hidden;
            border: 1px solid rgba(255,255,255,0.1);
            position: relative;
            display: flex;
            flex-direction: column;
            justify-content: flex-end; /* Логи снизу вверх */
        }
        
        /* Градиент затемнения сверху терминала */
        .terminal::before {
            content: '';
            position: absolute;
            top: 0; left: 0; right: 0; height: 40px;
            background: linear-gradient(to bottom, #000, transparent);
            pointer-events: none;
            z-index: 2;
        }

        .log-line { margin-bottom: 4px; display: block; }
        .log-line.error { color: var(--red); }
        .log-line.warn { color: #f59e0b; }

        .footer {
            margin-top: 24px;
            display: flex;
            justify-content: space-between;
            font-size: 0.75rem;
            color: var(--text-dim);
            font-family: var(--font-mono);
        }

        @keyframes blink { 50% { opacity: 0.4; } }
        @keyframes fadeIn { from { opacity: 0; transform: scale(0.95); } to { opacity: 1; transform: scale(1); } }
    </style>
</head>
<body>
    
    <!-- Canvas для фона -->
    <canvas id="bg-canvas"></canvas>

    <div class="card">
        <div class="header">
            <div class="status-dot"></div>
            <div>
                <h1 id="sys-header">System Alert</h1>
                <div class="subtitle" id="incident-id">INC-LOADING...</div>
            </div>
        </div>

        <div class="message-box">
            <div class="title" id="main-title">Service Unavailable</div>
            <div class="desc" id="main-desc">Loading status info...</div>
        </div>

        <div class="terminal" id="terminal">
            <!-- Logs go here -->
        </div>

        <div class="footer">
            <span id="node-id">Node: ...</span>
            <span id="timer">Retry in 30s</span>
        </div>
    </div>

    <script>
        // --- 1. Multilanguage Support ---
        const langData = {
            ru: {
                title: "Техническое обслуживание",
                desc: "Наши системы зафиксировали повышенную нагрузку. В данный момент трафик перенаправляется через резервные каналы. Пожалуйста, подождите.",
                header: "Системный статус",
                retry: "Повтор через"
            },
            en: {
                title: "Service Unavailable",
                desc: "Our automated monitoring systems detected an anomaly. Traffic is currently being rerouted to mitigation centers. Please wait.",
                header: "System Alert",
                retry: "Retry in"
            },
            zh: {
                title: "系统维护中",
                desc: "我们的监控系统检测到异常。流量正在重新路由至缓解中心。请稍候。",
                header: "系统警报",
                retry: "重试"
            },
            fa: {
                title: "سرویس در دسترس نیست",
                desc: "سیستم‌های نظارتی ما ناهنجاری شناسایی کرده‌اند. ترافیک در حال حاضر به مراکز کاهش بار هدایت می‌شود.",
                header: "هشدار سیستم",
                retry: "تلاش مجدد در"
            }
        };

        // Detect Language
        const userLang = navigator.language || navigator.userLanguage; 
        const langCode = userLang.startsWith('ru') ? 'ru' : 
                         userLang.startsWith('zh') ? 'zh' : 
                         userLang.startsWith('fa') ? 'fa' : 'en';

        const content = langData[langCode];
        document.getElementById('main-title').innerText = content.title;
        document.getElementById('main-desc').innerText = content.desc;
        document.getElementById('sys-header').innerText = content.header;

        // --- 2. Random Incident ID & Node ---
        const randHex = len => [...Array(len)].map(() => Math.floor(Math.random() * 16).toString(16)).join('').toUpperCase();
        document.getElementById('incident-id').innerText = `INC-${randHex(6)} • Critical`;
        document.getElementById('node-id').innerText = `Node: ${['AMS','FRA','LON','NYC'][Math.floor(Math.random()*4)]}-${randHex(2)}`;

        // --- 3. Fake Terminal Logs ---
        const terminal = document.getElementById('terminal');
        const logs = [
            { text: "Initializing handshake...", type: "normal", delay: 100 },
            { text: "Verifying integrity checksums...", type: "normal", delay: 800 },
            { text: "WARN: High latency detected on port 443", type: "warn", delay: 1500 },
            { text: "Attempting failover routing...", type: "normal", delay: 2400 },
            { text: "ERROR: Connection timed out (upstream)", type: "error", delay: 3200 },
            { text: "Retrying connection (attempt 2/5)...", type: "normal", delay: 4500 },
            { text: "Waiting for available socket...", type: "normal", delay: 6000 }
        ];

        let logIndex = 0;
        function addLog() {
            if (logIndex >= logs.length) return;
            const log = logs[logIndex];
            
            setTimeout(() => {
                const div = document.createElement('div');
                div.className = `log-line ${log.type}`;
                div.innerText = `> [${new Date().toISOString().split('T')[1].split('.')[0]}] ${log.text}`;
                terminal.appendChild(div);
                
                logIndex++;
                addLog();
            }, logIndex === 0 ? 100 : (logs[logIndex].delay - logs[logIndex-1].delay));
        }
        addLog();

        // --- 4. Canvas Background (Particles) ---
        const canvas = document.getElementById('bg-canvas');
        const ctx = canvas.getContext('2d');
        
        let width, height;
        const particles = [];

        function resize() {
            width = canvas.width = window.innerWidth;
            height = canvas.height = window.innerHeight;
        }
        window.addEventListener('resize', resize);
        resize();

        class Particle {
            constructor() {
                this.x = Math.random() * width;
                this.y = Math.random() * height;
                this.vx = (Math.random() - 0.5) * 0.5;
                this.vy = (Math.random() - 0.5) * 0.5;
                this.size = Math.random() * 2;
                this.alpha = Math.random() * 0.5 + 0.1;
            }
            update() {
                this.x += this.vx;
                this.y += this.vy;
                if (this.x < 0) this.x = width;
                if (this.x > width) this.x = 0;
                if (this.y < 0) this.y = height;
                if (this.y > height) this.y = 0;
            }
            draw() {
                ctx.fillStyle = `rgba(100, 116, 139, ${this.alpha})`;
                ctx.beginPath();
                ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
                ctx.fill();
            }
        }

        for (let i = 0; i < 50; i++) particles.push(new Particle());

        function animate() {
            ctx.clearRect(0, 0, width, height);
            
            // Draw connections
            ctx.lineWidth = 0.5;
            for (let i = 0; i < particles.length; i++) {
                let p = particles[i];
                p.update();
                p.draw();
                
                for (let j = i + 1; j < particles.length; j++) {
                    let p2 = particles[j];
                    let dx = p.x - p2.x;
                    let dy = p.y - p2.y;
                    let dist = Math.sqrt(dx*dx + dy*dy);
                    
                    if (dist < 100) {
                        ctx.strokeStyle = `rgba(100, 116, 139, ${0.1 * (1 - dist/100)})`;
                        ctx.beginPath();
                        ctx.moveTo(p.x, p.y);
                        ctx.lineTo(p2.x, p2.y);
                        ctx.stroke();
                    }
                }
            }
            requestAnimationFrame(animate);
        }
        animate();

        // --- 5. Countdown Timer with Auto-Reload ---
        let count = 30; // Секунды до ретрая
        const timerElem = document.getElementById('timer');
        
        const timerInterval = setInterval(() => {
            count--;
            
            if (count <= 0) {
                clearInterval(timerInterval);
                timerElem.innerText = "Connecting...";
                
                // Добавляем лог о рестарте
                const div = document.createElement('div');
                div.className = 'log-line normal';
                div.innerText = `> [${new Date().toISOString().split('T')[1].split('.')[0]}] Reloading session...`;
                terminal.appendChild(div);
                
                // Эффектная пауза и релоад
                setTimeout(() => {
                    location.reload();
                }, 1500);
            } else {
                timerElem.innerText = `${content.retry} ${count}s`;
            }
        }, 1000);

    </script>
</body>
</html>

EOF

    # --- ШАГ 1: Сертификаты ---
    CERT_PATH=""
    KEY_PATH=""
    
    # Проверка на Wildcard от панели
    if [ -f "$BASE_DIR/wildcard.pem" ]; then
        echo "Нашел wildcard сертификат."
        CERT_PATH="/etc/nginx/ssl/wildcard.pem"
        KEY_PATH="/etc/nginx/ssl/wildcard.key"
    else
        # Выпускаем Standalone
        if [ ! -d "/root/.acme.sh" ]; then
            echo -e "${RED}Установка Acme.sh...${NC}"
            curl https://get.acme.sh | sh
        fi
        
        echo -e "${YELLOW}Выпуск сертификата для $SNI_DOMAIN...${NC}"
        
        # Если это панель - гасим Nginx, если нода - порта 80 скорее всего свободен
        if [ "$IS_PANEL_SERVER" = true ]; then
             docker stop remnawave-nginx 2>/dev/null || true
        fi
        
        /root/.acme.sh/acme.sh --issue --standalone -d "$SNI_DOMAIN" --force
        
        # Копируем ключи в папку Nginx (чтобы смонтировать)
        /root/.acme.sh/acme.sh --install-cert -d "$SNI_DOMAIN" \
        --key-file "$BASE_DIR/sni_privkey.key" \
        --fullchain-file "$BASE_DIR/sni_fullchain.pem"
        
        if [ "$IS_PANEL_SERVER" = true ]; then
             docker start remnawave-nginx 2>/dev/null || true
        fi
        
        CERT_PATH="/etc/nginx/ssl/sni_fullchain.pem"
        KEY_PATH="/etc/nginx/ssl/sni_privkey.key"
    fi

	echo "Создаем минимальный nginx.conf..."
	
	cat <<EOF >> "$CONF_FILE"
# --- SNI FALLBACK ($SNI_DOMAIN) ---
server {
    server_name $SNI_DOMAIN;
    listen $FALLBACK_PORT ssl proxy_protocol;
    http2 on;

    set_real_ip_from 127.0.0.1;
    set_real_ip_from 10.0.0.0/8;
    set_real_ip_from 172.16.0.0/12;
    set_real_ip_from 192.168.0.0/16;
    real_ip_header proxy_protocol;

    root /usr/share/nginx/html/custom;
    index sni.html;

    # Логика обработки запросов
    location = /sni.html {
        add_header Cache-Control "no-store, no-cache, must-revalidate";
        log_not_found off;
    }

    location / {
        # Если файл не найден - редирект на именованный файл /sni.html
        try_files \$uri \$uri/ /sni.html;
        add_header Cache-Control "no-store, no-cache, must-revalidate";
    }

    # SSL Configuration (Mozilla Intermediate Guidelines)
    ssl_protocols          TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305;

    ssl_session_timeout 1d;
    ssl_session_cache shared:MozSSL:10m;
    ssl_session_tickets    off;

    # Пути сертификатов (внутри контейнера)
    ssl_certificate "$CERT_PATH";
    ssl_certificate_key "$KEY_PATH";
    ssl_trusted_certificate "$CERT_PATH";

    ssl_stapling           on;
    ssl_stapling_verify    on;
    resolver               1.1.1.1 1.0.0.1 8.8.8.8 8.8.4.4 208.67.222.222 208.67.220.220 valid=60s;
    resolver_timeout       2s;

    # Gzip Compression
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_buffers 16 8k;
    gzip_http_version 1.1;
    gzip_min_length 256;
    gzip_types
        application/atom+xml
        application/geo+json
        application/javascript
        application/x-javascript
        application/json
        application/ld+json
        application/manifest+json
        application/rdf+xml
        application/rss+xml
        application/xhtml+xml
        application/xml
        font/eot
        font/otf
        font/ttf
        image/svg+xml
        text/css
        text/javascript
        text/plain
        text/xml;
}
EOF

    # --- ШАГ 2: Конфигурация Nginx ---
    if [ "$IS_PANEL_SERVER" = true ]; then
        # === ВАРИАНТ А: Добавляем в существующий конфиг ===
        if ! grep -q "SNI FALLBACK" "$CONF_FILE"; then
            echo "$BLOCK_CONTENT" >> "$CONF_FILE"
            echo "Конфиг обновлен."
        fi
        
        # Обновляем compose (добавляем порт и volumes)
        if ! grep -q "$FALLBACK_PORT:$FALLBACK_PORT" "$COMPOSE_FILE"; then
            sed -i "/ports:/a \            - '127.0.0.1:$FALLBACK_PORT:$FALLBACK_PORT'" "$COMPOSE_FILE"
        fi
         if ! grep -q "/usr/share/nginx/html/custom" "$COMPOSE_FILE"; then
            sed -i "/volumes:/a \            - ./html:/usr/share/nginx/html/custom:ro" "$COMPOSE_FILE"
        fi
        # Если сертификаты не wildcard, добавляем их вольюмы
        if [[ "$CERT_PATH" == *"sni_fullchain"* ]] && ! grep -q "sni_fullchain.pem" "$COMPOSE_FILE"; then
             sed -i "/volumes:/a \            - ./sni_fullchain.pem:/etc/nginx/ssl/sni_fullchain.pem:ro" "$COMPOSE_FILE"
             sed -i "/volumes:/a \            - ./sni_privkey.key:/etc/nginx/ssl/sni_privkey.key:ro" "$COMPOSE_FILE"
        fi
        
        cd "$BASE_DIR"
		if ! docker compose up -d --force-recreate; then
			echo -e "${RED}ОШИБКА: Не удалось запустить Docker контейнеры!${NC}"
			echo -e "${YELLOW}Возможно, заняты порты или ошибка в конфиге.${NC}"
			# Тут можно предложить посмотреть логи: docker compose logs
			return 1
		fi

    else
        # === ВАРИАНТ Б: Создаем с нуля (Чистая Нода) ===
        echo "Создаем docker-compose.yml..."
        cat <<EOF > "$COMPOSE_FILE"
services:
  nginx:
    image: nginx:latest
    container_name: remnawave-fallback
    restart: always
    network_mode: "host"  # Используем host, чтобы Xray легко стучался на 127.0.0.1
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./html:/usr/share/nginx/html/custom:ro
EOF
        # Добавляем вольюмы сертификатов
        if [[ "$CERT_PATH" == *"sni_fullchain"* ]]; then
            sed -i "/volumes:/a \      - ./sni_fullchain.pem:/etc/nginx/ssl/sni_fullchain.pem:ro" "$COMPOSE_FILE"
            sed -i "/volumes:/a \      - ./sni_privkey.key:/etc/nginx/ssl/sni_privkey.key:ro" "$COMPOSE_FILE"
        fi
        
        echo "Запуск Nginx..."
        cd "$BASE_DIR" docker compose down
		if ! docker compose up -d; then
			echo -e "${RED}ОШИБКА: Не удалось запустить Docker контейнеры!${NC}"
			echo -e "${YELLOW}Возможно, заняты порты или ошибка в конфиге.${NC}"
			# Тут можно предложить посмотреть логи: docker compose logs
			return 1
		fi
    fi
    
    echo -e "\n\n\n${RED}------------ ------------ Внимание:------------ ------------ "
	echo -e "${GREEN}Настройка завершена!${NC}"
    echo -e "Nginx слушает на порту: ${CYAN}$FALLBACK_PORT${NC} (SSL)"
    echo -e "Настройки для Xray Reality:"
    echo -e "  Target (Dest): ${CYAN}127.0.0.1:$FALLBACK_PORT${NC}"
    echo -e "  ServerNames:   ${CYAN}$SNI_DOMAIN${NC}"
	echo -e "{RED}Важно:"
	echo -e "${GREEN}Убедитесь, что в Xray отключен 'sniffing -> routeOnly', иначе fallback может не сработать."
	echo -e 'В Xray также добавьте "xver": 1 (необходимо, так как включен proxy_protocol, чтобы логи nginx определяли реальный IP клиента, открывшего адрес заглушки.'
    pause_func
}


menu_remnawave() {
    while true; do
        echo -e "\n${CYAN}--- REMNAWAVE MANAGEMENT ---${NC}"
        echo "1. Установить Панель (+ Подписка)"
        echo "2. Удалить Панель (Full Wipe)"
        echo "3. Установить Ноду"
        echo "4. Удалить Ноду"
        echo "5. Настроить Reverse Proxy (Nginx)"
		echo "6. Создать SNI-заглушку (Reality Fallback)"
        echo "0. Назад"
        read -p "Выбор: " rc
        case $rc in
            1) rw_install_panel ;;
            2) rw_remove_panel ;;
            3) rw_install_node ;;
            4) rw_remove_node ;;
            5) rw_setup_proxy ;;
			6) rw_setup_sni_fallback ;;
            0) return ;;
            *) echo "Ошибка";;
        esac
    done
}

# ==========================================
# 3. COMPONENT MANAGEMENT
# ==========================================

comp_warp_inst() {
    echo -e "${BLUE}--- Установка WARP ---${NC}"
    
    # Установка базового клиента
    echo "Устанавливаем WARP клиент..."
    bash <(curl -fsSL https://raw.githubusercontent.com/distillium/warp-native/main/install.sh)
    
    echo -e "${YELLOW}Настройка Ansible для управления WARP...${NC}"
    apt-get install -y ansible
    ansible-galaxy install themelbine.warp_native
    
    # Создание плейбука
    cat <<EOF > /opt/warp_playbook.yml
- hosts: localhost
  connection: local
  become: yes
  roles:
      - themelbine.warp_native
  vars:
      warp_native_state: present
      warp_native_modify_resolv: true
      warp_native_temp_nameservers:
          - "1.1.1.1"
          - "8.8.8.8"
EOF
    
    echo -e "${GREEN}WARP установлен.${NC}"
    echo -e "Файл управления создан: ${CYAN}/opt/warp_playbook.yml${NC}"
    echo -e "Для применения настроек через Ansible запустите: ${YELLOW}ansible-playbook /opt/warp_playbook.yml${NC}"
    pause_func
}

comp_warp_del() {
    bash <(curl -fsSL https://raw.githubusercontent.com/distillium/warp-native/main/uninstall.sh)
    echo -e "${GREEN}WARP удален.${NC}"
    pause_func
}

comp_tblock_inst() {
    echo -e "${BLUE}--- Установка Torrent Blocker ---${NC}"
    
    # Создаем папку логов заранее
    mkdir -p /var/log/remnanode
    
    # Автоматическая подстановка пути к логам при установке
    echo -e "${YELLOW}Запуск установщика с автоматическим вводом пути логов...${NC}"
    echo "/var/log/remnanode/access.log" | bash <(curl -fsSL git.new/install)
    
    mkdir -p /opt/tblocker
    
	while true; do
		read -p "Введите длительность блокировки (в минутах), default 10: " BLOCK_DUR
        
        if [[ -z "$BLOCK_DUR" ]]; then
            echo -e "${RED}Ошибка: Значение времени не может быть пустым!${NC}"
        elif ! [[ "$BLOCK_DUR" =~ ^[0-9]+$ ]]; then
            echo -e "${RED}Ошибка: Значение времени может содержать только цифры!${NC}"
        elif (( BLOCK_DUR < 1 || BLOCK_DUR > 43200 )); then
            echo -e "${RED}Ошибка: Значение времени должно быть указано в диапазоне 1-43200 (1 месяц)!${NC}"
        else
            break # Всё ок, выходим из цикла
        fi
    done
	
    BLOCK_DUR=${BLOCK_DUR:-10}
    
    echo -e "${YELLOW}Запись конфигурации в /opt/tblocker/config.yaml...${NC}"
    cat <<EOF > /opt/tblocker/config.yaml
# Файл логов для мониторинга
LogFile: "/var/log/remnanode/access.log"

# Продолжительность блокировки в минутах
BlockDuration: $BLOCK_DUR

# Тег, используемый для идентификации торрент-трафика в логах
TorrentTag: "TORRENT"

# Файрволл для блокировки (iptables, nft)
BlockMode: "iptables"

# IP-адреса для обхода блокировки
BypassIPS:
  - "127.0.0.1"
  - "::1"

# Директория для хранения данных о блокировке
StorageDir: "/opt/tblocker"

# Регулярное выражение для обработки имени пользователя в вебхуках
UsernameRegex: "^(.+)$"
EOF

    systemctl restart tblocker
    echo -e "${GREEN}Torrent Blocker настроен и перезапущен.${NC}"
    echo -e "Файл конфига: ${CYAN}/opt/tblocker/config.yaml${NC}"
    pause_func
}

comp_tblock_del() {
    systemctl stop tblocker
    systemctl disable tblocker
    rm /usr/local/bin/tblocker
    rm /etc/systemd/system/tblocker.service
    rm -rf /opt/tblocker
    systemctl daemon-reload
    echo -e "${GREEN}Torrent Blocker удален.${NC}"
    pause_func
}

# ==========================================
# DNS LOAD BALANCER
# ==========================================

comp_lb_monitor_inst() {
    echo -e "${BLUE}--- Установка Агента Мониторинга (Node) ---${NC}"
    
    install_base_dependencies
    
    # 1. Зависимости Python
    echo -e "${YELLOW}Установка Python зависимостей...${NC}"
    apt-get install -y python3-pip
    if ! pip3 install psutil 2>/dev/null; then
        apt-get install -y python3-psutil || pip3 install psutil --break-system-packages
    fi

    # 2. Создание скрипта
    mkdir -p /opt/remnawave-balancer
    
    cat << 'EOF' > /opt/remnawave-balancer/monitor.py
import psutil
from http.server import BaseHTTPRequestHandler, HTTPServer
import json

PORT = 5050

class SystemStatsHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        if self.path == '/stats':
            try:
                cpu = psutil.cpu_percent(interval=0.5)
                ram = psutil.virtual_memory().percent
                load_1m, _, _ = psutil.getloadavg()
                
                stats = {
                    "cpu_percent": cpu,
                    "ram_percent": ram,
                    "load_avg_1m": load_1m,
                    "status": "online"
                }
                
                self.send_response(200)
                self.send_header('Content-type', 'application/json')
                self.end_headers()
                self.wfile.write(json.dumps(stats).encode('utf-8'))
            except Exception as e:
                self.send_error(500, str(e))
        else:
            self.send_response(404)
            self.end_headers()

def run():
    server_address = ('0.0.0.0', PORT)
    httpd = HTTPServer(server_address, SystemStatsHandler)
    print(f"Monitor Agent running on port {PORT}...")
    httpd.serve_forever()

if __name__ == "__main__":
    run()
EOF

    # 3. Systemd
    cat << 'EOF' > /etc/systemd/system/remnawave-monitor.service
[Unit]
Description=Remnawave Node Monitor Agent
After=network.target

[Service]
User=root
WorkingDirectory=/opt/remnawave-balancer
ExecStart=/usr/bin/python3 /opt/remnawave-balancer/monitor.py
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

    # 4. Запуск
    systemctl daemon-reload
    systemctl enable --now remnawave-monitor
    
    # 5. UFW
    if ufw status | grep -q "Status: active"; then
        echo -e "${YELLOW}Открываем порт 5050 в UFW...${NC}"
        ufw allow 5050/tcp
    fi
    
    echo -e "${GREEN}Агент мониторинга установлен (Port 5050).${NC}"
    pause_func
}

comp_lb_monitor_del() {
    echo -e "${YELLOW}Удаление Агента мониторинга...${NC}"

    # Проверка и остановка сервиса
    if systemctl list-units --full -all | grep -Fq 'remnawave-monitor.service'; then
        systemctl stop remnawave-monitor
        systemctl disable remnawave-monitor
        rm /etc/systemd/system/remnawave-monitor.service
        echo "Сервис отключен."
    else
        echo "Сервис не найден, пропускаем."
    fi

    # Удаление файла скрипта
    if [ -f "/opt/remnawave-balancer/monitor.py" ]; then
        rm /opt/remnawave-balancer/monitor.py
        echo "Скрипт удален."
    fi

    # Удаление правила UFW (если оно есть)
    if ufw status | grep -q "5050"; then
        ufw delete allow 5050/tcp >/dev/null 2>&1
        echo "Порт 5050 закрыт в UFW."
    fi

    systemctl daemon-reload

    # Удаление папки, если она пуста (или полная зачистка, если там только мусор)
    # Если там лежит и balancer.py (мастер и агент на одном сервере), то удалять папку нельзя!
    if [ -d "/opt/remnawave-balancer" ]; then
        # Проверяем, есть ли там balancer.py
        if [ ! -f "/opt/remnawave-balancer/balancer.py" ]; then
            rm -rf /opt/remnawave-balancer
            echo "Папка /opt/remnawave-balancer удалена."
        else
            echo -e "${YELLOW}Папка не удалена, так как в ней находится balancer.py${NC}"
        fi
    fi
    
    echo -e "${GREEN}Агент мониторинга полностью удален.${NC}"
    pause_func
}

comp_lb_master_inst() {
    echo -e "${BLUE}--- Установка Балансировщика (Master) ---${NC}"
    
    install_base_dependencies
    mkdir -p /opt/remnawave-balancer
    
    # Проверка зависимостей
    echo -e "${YELLOW}Установка Python requests...${NC}"
    apt-get install -y python3-requests || pip3 install requests --break-system-packages

    CONFIG_FILE="/opt/remnawave-balancer/balancer.py"
	NODES_FILE="/opt/remnawave-balancer/nodes.json"
    
    # Если файла нет, создаем с шаблоном, иначе редактируем текущий
    if [ ! -f "$CONFIG_FILE" ]; then
        echo -e "Введите данные Cloudflare для управления доменом."
        while [[ -z "$CF_ZONE" ]]; do
			read -p "CF Zone ID: " CF_ZONE
			CF_ZONE=$(echo "$CF_ZONE" | tr -d ' ')
			if [[ -z "$CF_ZONE" ]]; then echo -e "${RED}Пусто!${NC}"; fi
		done

		while [[ -z "$CF_TOKEN" ]]; do
			read -p "CF Token: " CF_TOKEN
			CF_TOKEN=$(echo "$CF_TOKEN" | tr -d ' ')
			if [[ -z "$CF_TOKEN" ]]; then echo -e "${RED}Пусто!${NC}"; fi
		done

		while [[ -z "$DNS_REC" ]]; do
			read -p "DNS Record (например, best.domain.com): " DNS_REC
			DNS_REC=$(echo "$DNS_REC" | tr -d ' ')
			if [[ -z "$DNS_REC" ]]; then echo -e "${RED}Пусто!${NC}"; fi
		done
		
		if [ ! -f "$NODES_FILE" ]; then
            echo "[]" > "$NODES_FILE"
        fi
		
        # Создаем болванку скрипта
        cat <<EOF > "$CONFIG_FILE"
import requests
import time
import logging
import json
import os
from logging.handlers import RotatingFileHandler

CF_ZONE_ID = "$CF_ZONE"
CF_TOKEN = "$CF_TOKEN"
DNS_RECORD_NAME = "$DNS_REC"
CHECK_INTERVAL = 60 # Как часто проверять (в секундах)
NODES_FILE = "$NODES_FILE"

# Настройка логгера
# 1. Хендлер для файла (с ротацией)
# maxBytes=5*1024*1024 -> 5 Мегабайт
# backupCount=3 -> Хранить 3 последних файла (balancer.log, balancer.log.1, balancer.log.2)
logger = logging.getLogger()
logger.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
file_handler = RotatingFileHandler("/var/log/remnawave-balancer.log", maxBytes=5*1024*1024, backupCount=3, encoding='utf-8')
file_handler.setFormatter(formatter)

# 2. Хендлер для консоли (чтобы видеть в systemctl status)
stream_handler = logging.StreamHandler()
stream_handler.setFormatter(formatter)
logger.addHandler(file_handler)
logger.addHandler(stream_handler)

def load_nodes():
    """Читает список нод из JSON файла."""
    if not os.path.exists(NODES_FILE):
        logging.error(f"Nodes file not found: {NODES_FILE}")
        return []
    try:
        with open(NODES_FILE, 'r', encoding='utf-8') as f:
            return json.load(f)
    except Exception as e:
        logging.error(f"Error loading nodes.json: {e}")
        return []

def get_node_health(node):
    try:
        url = f"http://{node['ip']}:{node['port']}/stats"
        resp = requests.get(url, timeout=5)
        if resp.status_code == 200:
            return resp.json()
    except Exception as e:
        logging.warning(f"Node {node['name']} ({node['ip']}) unreachable: {e}")
    return None

def update_dns(ip_address):
    headers = {"Authorization": f"Bearer {CF_TOKEN}", "Content-Type": "application/json"}
    try:
        list_url = f"https://api.cloudflare.com/client/v4/zones/{CF_ZONE_ID}/dns_records?name={DNS_RECORD_NAME}"
        r = requests.get(list_url, headers=headers)
        data = r.json()
        if not data.get('result'):
            logging.error(f"DNS record {DNS_RECORD_NAME} not found!")
            return
        
        record = data['result'][0]
        if record['content'] == ip_address:
            logging.info(f"IP is actual ({ip_address}). No changes.")
            return

        update_url = f"https://api.cloudflare.com/client/v4/zones/{CF_ZONE_ID}/dns_records/{record['id']}"
        payload = {"content": ip_address, "name": DNS_RECORD_NAME, "type": "A", "proxied": False, "ttl": 60}
        requests.put(update_url, headers=headers, json=payload)
        logging.info(f"SUCCESS: DNS Updated -> {ip_address}")
    except Exception as e:
        logging.error(f"Cloudflare API Error: {e}")

def main():
    logging.info("Starting Balancer...")
    while True:
        nodes = load_nodes()
        best_node = None
        min_score = 9999
        
        if not nodes:
            logging.error("No nodes configured!")
            time.sleep(CHECK_INTERVAL)
            continue

        for node in nodes:
            stats = get_node_health(node)
            if stats:
                # Score formula: CPU + RAM/2 + Load*10 (Lower is better)
                score = stats['cpu_percent'] + (stats['ram_percent'] / 2) + (stats['load_avg_1m'] * 10)
                if score < min_score:
                    min_score = score
                    best_node = node
        
        if best_node:
            logging.info(f"Winner: {best_node['name']} Score: {min_score:.1f}")
            update_dns(best_node['ip'])
        else:
            logging.critical("All nodes down!")
        
        time.sleep(CHECK_INTERVAL)

if __name__ == "__main__":
    main()
EOF
    fi

    # Systemd Service
    cat << 'EOF' > /etc/systemd/system/remnawave-balancer.service
[Unit]
Description=Remnawave DNS Load Balancer
After=network.target

[Service]
User=root
WorkingDirectory=/opt/remnawave-balancer
ExecStart=/usr/bin/python3 /opt/remnawave-balancer/balancer.py
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target
EOF
    systemctl daemon-reload
    systemctl enable --now remnawave-balancer
    
    echo -e "${GREEN}Балансировщик установлен.${NC}"
    echo -e "Используйте меню управления нодами для добавления серверов."
    pause_func
}

comp_lb_manage_nodes() {
    NODES_FILE="/opt/remnawave-balancer/nodes.json"
    
    if [ ! -f "$NODES_FILE" ]; then
        echo -e "${RED}Файл конфигурации $NODES_FILE не найден!${NC}"
        echo -e "Сначала установите Балансировщик."
        pause_func
        return
    fi
    
    while true; do
        echo -e "\n${CYAN}--- Управление Нодами (JSON) ---${NC}"
        echo "Текущий список:"
        # Красивый вывод JSON (если есть jq, иначе cat)
        if command -v jq &> /dev/null; then
            jq '.' "$NODES_FILE"
        else
            cat "$NODES_FILE"
        fi
        
        echo -e "\n1. Добавить Ноду"
        echo "2. Очистить список"
        echo "3. Перезапустить сервис (обычно не требуется)"
        echo "0. Назад"
        read -p "Выбор: " ch
        
        case $ch in
            1)
                # --- ВАЛИДАЦИЯ (из прошлого ответа) ---
                while [[ -z "$N_NAME" ]]; do
                    read -p "Имя ноды (например, NL-1): " N_NAME
                    if [[ -z "$N_NAME" ]]; then echo -e "${RED}Пусто!${NC}"; fi
                done
                while [[ -z "$N_IP" ]]; do
                    read -p "IP адрес: " N_IP
                    if [[ -z "$N_IP" ]]; then echo -e "${RED}Пусто!${NC}"; fi
                done
                while true; do
                    read -p "Порт агента (default 5050): " N_PORT_INPUT
                    N_PORT=${N_PORT_INPUT:-5050}
                    if [[ "$N_PORT" =~ ^[0-9]+$ ]]; then break; fi
                    echo -e "${RED}Число!${NC}"
                done
                # -------------------------------------

                # МАГИЯ PYTHON: Добавляем запись в JSON безопасно
                python3 -c "
import json
import sys

try:
    with open('$NODES_FILE', 'r') as f:
        data = json.load(f)
except:
    data = []

new_node = {'name': '$N_NAME', 'ip': '$N_IP', 'port': int('$N_PORT')}
data.append(new_node)

with open('$NODES_FILE', 'w') as f:
    json.dump(data, f, indent=4)
print('OK')
"
                echo -e "${GREEN}Нода добавлена в JSON!${NC}"
                echo -e "${YELLOW}Изменения применятся автоматически через 60 сек.${NC}"
                
                # Очистка переменных для следующего цикла
                N_NAME=""
                N_IP=""
                ;;
            2)
                echo "[]" > "$NODES_FILE"
                echo -e "${YELLOW}Список очищен.${NC}"
                ;;
            3)
                systemctl restart remnawave-balancer
                echo -e "${GREEN}Сервис перезапущен.${NC}"
                ;;
            0) return ;;
        esac
    done
}

comp_lb_master_del() {
    echo -e "${RED}Удаление Балансировщика (Master)...${NC}"
    read -p "Вы уверены? (y/n): " CONFIRM
    if [[ ! "$CONFIRM" =~ ^[Yy]$ ]]; then return; fi

    # Проверка сервиса
    if systemctl list-units --full -all | grep -Fq 'remnawave-balancer.service'; then
        systemctl stop remnawave-balancer
        systemctl disable remnawave-balancer
        rm /etc/systemd/system/remnawave-balancer.service
        echo "Сервис отключен."
    else
        echo "Сервис не найден, пропускаем."
    fi

    # Удаление скрипта
    if [ -f "/opt/remnawave-balancer/balancer.py" ]; then
        rm /opt/remnawave-balancer/balancer.py
        echo "Скрипт удален."
    fi
    
	# Удаление списка нод
	if [ -f "/opt/remnawave-balancer/nodes.json" ]; then
        rm /opt/remnawave-balancer/nodes.json
        echo "Конфиг нод удален."
    fi
	
    # Удаление логов
    if [ -f "/var/log/remnawave-balancer.log" ]; then
        rm /var/log/remnawave-balancer.log*
        echo "Логи очищены."
    fi

    systemctl daemon-reload

    # Удаление папки
    if [ -d "/opt/remnawave-balancer" ]; then
        # Проверяем, не установлен ли тут монитор
        if [ ! -f "/opt/remnawave-balancer/monitor.py" ]; then
            rm -rf /opt/remnawave-balancer
            echo "Папка /opt/remnawave-balancer удалена."
        else
            echo -e "${YELLOW}Папка не удалена, так как в ней находится monitor.py${NC}"
        fi
    fi

    echo -e "${GREEN}Балансировщик удален.${NC}"
    pause_func
}


comp_lb_menu() {
    while true; do
        echo -e "\n${CYAN}--- DNS LOAD BALANCER ---${NC}"
        echo "1. Установить Балансировщик (на Master сервер)"
		echo "2. Установить Агента (на Worker ноды)"
        echo "3. Управление нодами (Добавить/Удалить)"
        echo "4. Просмотр логов балансировщика"
        echo "5. Удалить Балансировщик (управление DNS)"
        echo "6. Удалить Агента (состояние ноды)"
        echo "0. Назад"
        read -p "Выбор: " lb_c
        
        case $lb_c in
            1) comp_lb_master_inst ;;
			2) comp_lb_monitor_inst ;;
            3) comp_lb_manage_nodes ;;
            4) 
               if [ -f "/var/log/remnawave-balancer.log" ]; then
                   tail -f -n 50 /var/log/remnawave-balancer.log
               else
                   echo "Лог файл не найден. Возможно, сервис не запущен."
                   pause_func
               fi
               ;;
            5) comp_lb_master_del ;; # <-- Вызов новой функции
            6) comp_lb_monitor_del ;; # <-- Вызов удаления агента
            0) return ;;
        esac
    done
}


menu_components() {
    while true; do
        echo -e "\n${CYAN}--- ДОП. КОМПОНЕНТЫ ---${NC}"
        echo "1. Установить WARP"
        echo "2. Удалить WARP"
        echo "3. Установить Torrent Blocker"
        echo "4. Удалить Torrent Blocker"
		echo "5. Load Balancer (DNS)"
        echo "0. Назад"
        read -p "Выбор: " cc
        case $cc in
            1) comp_warp_inst ;;
            2) comp_warp_del ;;
            3) comp_tblock_inst ;;
            4) comp_tblock_del ;;
			5) comp_lb_menu ;;
            0) return ;;
            *) echo "Ошибка";;
        esac
    done
}


# ==========================================
# 4. --- ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ FIREWALL ---
# ==========================================

ufw_toggle_ipv6() {
    echo -e "${BLUE}--- Управление IPv6 в UFW ---${NC}"
    
    # Проверка текущего статуса в конфиге
    CURRENT_STATUS=$(grep "^IPV6=" /etc/default/ufw | cut -d= -f2)
    echo -e "Текущий статус IPv6 в UFW: ${YELLOW}$CURRENT_STATUS${NC}"
    
    echo "1. Включить (IPV6=yes)"
    echo "2. Выключить (IPV6=no)"
    echo "0. Отмена"
    read -p "Выбор: " ipv6_choice
    
    case $ipv6_choice in
        1)
            sed -i 's/IPV6=no/IPV6=yes/g' /etc/default/ufw
            echo -e "${GREEN}IPv6 включен в конфиге UFW.${NC}"
            ;;
        2)
            sed -i 's/IPV6=yes/IPV6=no/g' /etc/default/ufw
            echo -e "${RED}IPv6 отключен в конфиге UFW.${NC}"
            ;;
        0) return ;;
    esac
    
    echo -e "${YELLOW}Перезагрузка правил UFW...${NC}"
    ufw reload
    pause_func
}

ufw_full_setup() {
    install_base_dependencies
    echo -e "${BLUE}--- Полная настройка UFW ---${NC}"
    
    # Сброс
    ufw default deny incoming
    ufw default allow outgoing
    
    # SSH
    SSH_PORT=$(grep "^Port" /etc/ssh/sshd_config | awk '{print $2}' | head -n 1)
    if [ -z "$SSH_PORT" ]; then SSH_PORT=22; fi
    echo -e "${YELLOW}Разрешаем SSH ($SSH_PORT)...${NC}"
    ufw allow "$SSH_PORT"/tcp
    
    # Web
    echo -e "${YELLOW}Разрешаем Web (80, 443)...${NC}"
    ufw allow 80/tcp
    ufw allow 443/tcp
    
    # Node API
    read -p "Открыть доступ к API Ноды для Панели? (y/n): " IS_NODE
    if [[ "$IS_NODE" =~ ^[Yy]$ ]]; then
		DEFAULT_PORT=""
        NODE_CONFIG="/opt/remnanode/docker-compose.yml"
        
        if [ -f "$NODE_CONFIG" ]; then
            # Ищем строку NODE_PORT=... и чистим её от кавычек и пробелов
            DETECTED_PORT=$(grep "NODE_PORT=" "$NODE_CONFIG" | cut -d'=' -f2 | tr -d '"' | tr -d "'" | tr -d ' ')
            
            # Проверяем, что найденное значение - число
            if [[ "$DETECTED_PORT" =~ ^[0-9]+$ ]]; then
                DEFAULT_PORT="$DETECTED_PORT"
                echo -e "${YELLOW}Обнаружен конфиг ноды с портом: $DEFAULT_PORT${NC}"
            fi
        fi
        # ------------------------------------

        while true; do
            if [ -n "$DEFAULT_PORT" ]; then
                read -p "Порт API Ноды [нажмите Enter для $DEFAULT_PORT]: " NP
                NP=${NP:-$DEFAULT_PORT} # Если пусто, берем дефолт
            else
                read -p "Порт API Ноды (напр. 2222): " NP
            fi

            if [[ -z "$NP" ]]; then
                echo -e "${RED}Ошибка: Порт не может быть пустым!${NC}"
            elif ! [[ "$NP" =~ ^[0-9]+$ ]]; then
                echo -e "${RED}Ошибка: Порт должен содержать только цифры!${NC}"
            elif (( NP < 1 || NP > 65535 )); then
                echo -e "${RED}Ошибка: Порт должен быть в диапазоне 1-65535!${NC}"
            else
                break # Всё ок, выходим из цикла
            fi
        done

		while [[ -z "$PANEL_INPUT" ]]; do
			read -p "IP или Домен Панели:" PANEL_INPUT
			if [[ -z "$PANEL_INPUT" ]]; then
				echo -e "${RED}Ошибка: IP или Домен не могут быть пустыми!${NC}"
			fi
		done
        
        # Попытка резолва домена в IP
        if [[ "$PANEL_INPUT" =~ [a-zA-Z] ]]; then
            echo -e "${YELLOW}Вы ввели домен. Пытаемся получить IP...${NC}"
            RESOLVED_IP=$(getent hosts "$PANEL_INPUT" | awk '{ print $1 }' | head -n 1)
            
            if [[ -n "$RESOLVED_IP" ]]; then
                echo -e "IP адрес получен: ${GREEN}$RESOLVED_IP${NC}"
                FINAL_IP="$RESOLVED_IP"
            else
                echo -e "${RED}Ошибка: Не удалось узнать IP домена!${NC}"
                FINAL_IP=""
            fi
        else
            # Это уже IP
            FINAL_IP="$PANEL_INPUT"
        fi

        if [[ -n "$NP" && -n "$FINAL_IP" ]]; then
            ufw allow from "$FINAL_IP" to any port "$NP" proto tcp
            echo -e "${GREEN}Разрешен доступ $FINAL_IP -> :$NP${NC}"
        else
            echo -e "${RED}Правило для API не добавлено (неверные данные).${NC}"
        fi
    fi
    
    # Extra ports
    read -p "Открыть дополнительные порты? (y/n): " EXTRA
    if [[ "$EXTRA" =~ ^[Yy]$ ]]; then
        read -p "Введите порты через пробел: " PORTS
        for P in $PORTS; do ufw allow $P; done
    fi
    
    echo "y" | ufw enable
    echo -e "${GREEN}Настройка завершена.${NC}"
    pause_func
}

# --- МЕНЮ FIREWALL ---
menu_firewall() {
    while true; do
        echo -e "\n${CYAN}--- НАСТРОЙКА UFW (FIREWALL) ---${NC}"
        echo "1. Полная автоматическая настройка (Сброс + SSH + Web)"
        echo "2. Вкл/Выкл IPv6 в UFW"
        echo "3. Показать статус (ufw status)"
        echo "4. Отключить Firewall (Disable)"
        echo "0. Назад"
        read -p "Выбор: " f_choice
        
        case $f_choice in
            1) ufw_full_setup ;;
            2) ufw_toggle_ipv6 ;;
            3) ufw status verbose; pause_func ;;
            4) ufw disable; echo -e "${RED}Firewall выключен${NC}"; pause_func ;;
            0) return ;;
            *) echo "Ошибка";;
        esac
    done
}

# ==========================================
# 5. SERVICE MANAGEMENT (EDIT/LOGS/POWER)
# ==========================================

srv_edit_app_config() {
    local FILE="/opt/remnawave/subscription/app-config.json"
    if [ ! -f "$FILE" ]; then
         echo -e "${RED}Файл $FILE не найден! Сначала установите подписку.${NC}"
         pause_func
         return
    fi
    
    echo -e "Выберите метод редактирования:"
    echo "1. Nano (Обычный редактор)"
    echo "2. Полная замена (Вставить текст)"
    read -p "Выбор: " ec
    
    if [ "$ec" == "1" ]; then
        nano "$FILE"
    elif [ "$ec" == "2" ]; then
        echo -e "${YELLOW}Вставьте содержимое JSON. Нажмите Enter, затем Ctrl+D для сохранения.${NC}"
        cat > "$FILE"
        echo -e "${GREEN}Файл сохранен.${NC}"
    fi
    echo "Не забудьте перезагрузить контейнер подписки!"
    pause_func
}

srv_quick_edit() {
    while true; do
        echo -e "\n${CYAN}--- РЕДАКТИРОВАНИЕ ---${NC}"
        echo "1. .env Панели"
        echo "2. .env Подписки"
        echo "3. app-config.json (Конфиг подписки)"
        echo "4. Nginx Config"
        echo "5. TBlocker Config"
        echo "0. Назад"
        read -p "Файл: " qe
        case $qe in
            1) nano /opt/remnawave/.env ;;
            2) nano /opt/remnawave/subscription/.env ;;
            3) srv_edit_app_config ;;
            4) nano /opt/remnawave/nginx/nginx.conf ;;
            5) nano /opt/tblocker/config.yaml ;;
            0) return ;;
        esac
    done
}

srv_power() {
    echo -e "\n1. Start  2. Stop  3. Restart"
    read -p "Действие: " act
    echo -e "1. Panel  2. Sub  3. Node  4. Nginx  5. TBlocker"
    read -p "Сервис: " srv
    
    # Определяем команду
    case $act in
        1) CMD="up -d"; SCMD="start" ;;
        2) CMD="down"; SCMD="stop" ;;
        3) CMD="restart"; SCMD="restart" ;;
    esac
    
    case $srv in
        1) cd /opt/remnawave && docker compose $CMD ;;
        2) cd /opt/remnawave/subscription && docker compose $CMD ;;
        3) cd /opt/remnanode && docker compose $CMD ;;
        4) cd /opt/remnawave/nginx && docker compose $CMD ;;
        5) systemctl $SCMD tblocker ;;
    esac
    pause_func
}

srv_logs() {
    echo -e "1. Panel  2. Sub  3. Node  4. Nginx  5. TBlocker"
    read -p "Логи чего: " lg
    case $lg in
        1) cd /opt/remnawave && docker compose logs -f ;;
        2) cd /opt/remnawave/subscription && docker compose logs -f ;;
        3) cd /opt/remnanode && docker compose logs -f ;;
        4) cd /opt/remnawave/nginx && docker compose logs -f ;;
        5) journalctl -u tblocker -f --no-pager ;;
    esac
}

menu_services() {
    while true; do
        echo -e "\n${CYAN}--- УПРАВЛЕНИЕ СЕРВИСАМИ ---${NC}"
        echo "1. Быстрое редактирование конфигов"
        echo "2. Управление питанием (Start/Stop/Restart)"
        echo "3. Просмотр логов"
        echo "0. Назад"
        read -p "Выбор: " sc
        case $sc in
            1) srv_quick_edit ;;
            2) srv_power ;;
            3) srv_logs ;;
            0) return ;;
        esac
    done
}

# ==========================================
# MAIN MENU
# ==========================================
echo -e "${YELLOW}Обновление списков пакетов...${NC}"
apt-get update -qq

while true; do
    echo -e "\n${BLUE}=== REMNAWAVE ULTIMATE V1.0 ===${NC}"
    echo "1. Оптимизация системы (IPv6, BBR, DNS, Kernel)"
    echo "2. Установка Remnawave (Панель, Нода, Nginx, Selfsteal)"
    echo "3. Доп. компоненты (WARP, TBlocker, DNS-Balancer)"
    echo "4. Настройка UFW (Firewall)"
    echo "5. Управление сервисами (Edit, Logs, Restart)"
    echo "0. Выход"
    
    read -p "Ваш выбор: " main_c
    case $main_c in
        1) menu_optimization ;;
        2) menu_remnawave ;;
        3) menu_components ;;
        4) menu_firewall ;;
        5) menu_services ;;
        0) exit 0 ;;
    esac
done
