#!/bin/sh
# rProxy — Менеджер обратного прокси для роутеров Keenetic
# Публикация локальных сервисов через SSH-туннели + nginx на VPS
# http://5.104.75.50:3000/Petro1990/rProxy

VERSION="1.0.0"
CONF_DIR="/opt/etc/rproxy"
CONF_FILE="$CONF_DIR/rproxy.conf"
SERVICES_DIR="$CONF_DIR/services"
PID_DIR="/opt/var/run/rproxy"
SSH_KEY="$CONF_DIR/id_rsa"
REMOTE_NGINX_DIR="/etc/nginx/sites-enabled"
BASE_TUNNEL_PORT=10000

# ─── Цвета ───────────────────────────────────────────────────────────
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
BOLD='\033[1m'
DIM='\033[2m'
NC='\033[0m'

msg()     { printf "${GREEN}▸${NC} %s\n" "$*"; }
warn()    { printf "${YELLOW}⚠${NC} %s\n" "$*"; }
err()     { printf "${RED}✖${NC} %s\n" "$*" >&2; }
header()  { printf "\n${CYAN}${BOLD}%s${NC}\n" "$*"; }

# ─── Утилиты ─────────────────────────────────────────────────────────
clear_screen() { printf "\033[2J\033[H"; }

draw_box() {
    local title="$1"
    printf "${CYAN}╔══════════════════════════════════════════════╗${NC}\n"
    printf "${CYAN}║${NC}  ${BOLD}%-44s${NC}${CYAN}║${NC}\n" "$title"
    printf "${CYAN}╚══════════════════════════════════════════════╝${NC}\n"
}

draw_separator() {
    printf "${DIM}──────────────────────────────────────────────────${NC}\n"
}

prompt() {
    printf "\n${CYAN}▸${NC} $1"
    read -r REPLY
}

pause() {
    printf "\n${DIM}Нажмите Enter для продолжения...${NC}"
    read -r _
}

check_conf() {
    if [ ! -f "$CONF_FILE" ]; then
        return 1
    fi
    . "$CONF_FILE"
    return 0
}

load_service() {
    local svc_file="$SERVICES_DIR/$1.conf"
    if [ ! -f "$svc_file" ]; then
        err "Сервис '$1' не найден"
        return 1
    fi
    . "$svc_file"
}

ssh_cmd() {
    if [ "$VPS_AUTH" = "password" ]; then
        sshpass -p "$VPS_PASS" ssh -o StrictHostKeyChecking=no -p "$VPS_PORT" "$VPS_USER@$VPS_HOST" "$@"
    else
        ssh -o StrictHostKeyChecking=no -i "$SSH_KEY" -p "$VPS_PORT" "$VPS_USER@$VPS_HOST" "$@"
    fi
}

scp_cmd() {
    if [ "$VPS_AUTH" = "password" ]; then
        sshpass -p "$VPS_PASS" scp -o StrictHostKeyChecking=no -P "$VPS_PORT" "$@"
    else
        scp -o StrictHostKeyChecking=no -i "$SSH_KEY" -P "$VPS_PORT" "$@"
    fi
}

next_free_port() {
    local port=$BASE_TUNNEL_PORT
    while true; do
        local used=0
        for f in "$SERVICES_DIR"/*.conf 2>/dev/null; do
            [ -f "$f" ] || continue
            grep -q "TUNNEL_PORT=$port" "$f" && used=1 && break
        done
        [ "$used" -eq 0 ] && echo "$port" && return
        port=$((port + 1))
    done
}

get_pid_file() { echo "$PID_DIR/$1.pid"; }

is_running() {
    local pf
    pf=$(get_pid_file "$1")
    [ -f "$pf" ] && kill -0 "$(cat "$pf")" 2>/dev/null
}

count_services() {
    local count=0
    for f in "$SERVICES_DIR"/*.conf 2>/dev/null; do
        [ -f "$f" ] && count=$((count + 1))
    done
    echo $count
}

# ══════════════════════════════════════════════════════════════════════
# ГЛАВНОЕ МЕНЮ
# ══════════════════════════════════════════════════════════════════════
main_menu() {
    while true; do
        clear_screen
        draw_box "rProxy v$VERSION"
        printf "\n"

        if ! check_conf; then
            printf "  ${YELLOW}⚠ VPS не настроен${NC}\n\n"
            printf "  ${BOLD}1)${NC} Настроить подключение к VPS\n"
            printf "  ${BOLD}0)${NC} Выход\n"
            prompt "Выберите действие: "
            case "$REPLY" in
                1) do_setup ;;
                0|q) printf "\n"; exit 0 ;;
                *) ;;
            esac
            continue
        fi

        # Подсчёт сервисов и статусов
        local total=0 online=0
        for f in "$SERVICES_DIR"/*.conf 2>/dev/null; do
            [ -f "$f" ] || continue
            total=$((total + 1))
            . "$f"
            is_running "$SVC_NAME" && online=$((online + 1))
        done

        printf "  ${DIM}VPS:${NC} ${BOLD}$VPS_HOST${NC}  "
        printf "${DIM}Сервисов:${NC} ${BOLD}$total${NC}  "
        printf "${DIM}Онлайн:${NC} ${GREEN}${BOLD}$online${NC}\n"
        draw_separator
        printf "\n"

        printf "  ${BOLD}1)${NC}  📋  Список сервисов и статус\n"
        printf "  ${BOLD}2)${NC}  ➕  Добавить сервис\n"
        printf "  ${BOLD}3)${NC}  ❌  Удалить сервис\n"
        draw_separator
        printf "  ${BOLD}4)${NC}  ▶️   Запустить туннель\n"
        printf "  ${BOLD}5)${NC}  ⏹️   Остановить туннель\n"
        printf "  ${BOLD}6)${NC}  🔄  Перезапустить туннель\n"
        draw_separator
        printf "  ${BOLD}7)${NC}  ⚙️   Настройки VPS\n"
        printf "  ${BOLD}0)${NC}  🚪  Выход\n"

        prompt "Выберите действие: "

        case "$REPLY" in
            1) show_status ;;
            2) do_add_interactive ;;
            3) do_remove_interactive ;;
            4) do_start_interactive ;;
            5) do_stop_interactive ;;
            6) do_restart_interactive ;;
            7) do_setup ;;
            0|q) clear_screen; exit 0 ;;
            *) ;;
        esac
    done
}

# ══════════════════════════════════════════════════════════════════════
# СТАТУС
# ══════════════════════════════════════════════════════════════════════
show_status() {
    clear_screen
    draw_box "Список сервисов"
    printf "\n"

    local has_services=0
    local idx=0

    printf "  ${BOLD}%-4s %-14s %-22s %-7s %-9s %-18s${NC}\n" "№" "ИМЯ" "ЦЕЛЬ" "ПОРТ" "СТАТУС" "ДОМЕН"
    draw_separator

    for f in "$SERVICES_DIR"/*.conf 2>/dev/null; do
        [ -f "$f" ] || continue
        has_services=1
        idx=$((idx + 1))
        . "$f"

        local status_text
        if is_running "$SVC_NAME"; then
            status_text="${GREEN}● онлайн${NC}"
        else
            status_text="${RED}○ офлайн${NC}"
        fi

        local domain_text="${SVC_DOMAIN:-—}"
        local auto_text=""
        [ "$SVC_ENABLED" = "yes" ] && auto_text=" ${DIM}[авто]${NC}"

        printf "  %-4s %-14s %-22s %-7s ${status_text}  %-18s${auto_text}\n" \
            "$idx" "$SVC_NAME" "$SVC_TARGET_HOST:$SVC_TARGET_PORT" "$SVC_EXT_PORT" "$domain_text"
    done

    if [ "$has_services" -eq 0 ]; then
        printf "\n  ${YELLOW}Нет добавленных сервисов.${NC}\n"
        printf "  ${DIM}Выберите «Добавить сервис» в главном меню.${NC}\n"
    fi

    printf "\n"
    pause
}

# ══════════════════════════════════════════════════════════════════════
# ДОБАВИТЬ СЕРВИС (интерактивно)
# ══════════════════════════════════════════════════════════════════════
do_add_interactive() {
    clear_screen
    draw_box "Добавить новый сервис"
    printf "\n"

    prompt "Название сервиса (латиницей, без пробелов): "
    local name="$REPLY"
    [ -z "$name" ] && { warn "Название не может быть пустым"; pause; return; }

    if [ -f "$SERVICES_DIR/$name.conf" ]; then
        err "Сервис '$name' уже существует"
        pause
        return
    fi

    prompt "Адрес локального сервиса (например, 192.168.1.100:8080): "
    local target="$REPLY"
    [ -z "$target" ] && { warn "Адрес не может быть пустым"; pause; return; }

    printf "\n  Привязать к домену?\n"
    printf "  ${BOLD}1)${NC} Да — указать доменное имя (порт 80)\n"
    printf "  ${BOLD}2)${NC} Нет — указать внешний порт\n"
    prompt "Выберите [2]: "
    local mode="${REPLY:-2}"

    local domain=""
    local ext_port=""

    if [ "$mode" = "1" ]; then
        prompt "Доменное имя (например, mysite.example.com): "
        domain="$REPLY"
        [ -z "$domain" ] && { warn "Домен не указан"; pause; return; }
        ext_port=80
    else
        local suggested
        suggested=$(next_free_port)
        prompt "Внешний порт [$suggested]: "
        ext_port="${REPLY:-$suggested}"
    fi

    # Разбор адреса
    local target_host="${target%:*}"
    local target_port="${target#*:}"
    if [ "$target_host" = "$target_port" ]; then
        target_port="$target_host"
        target_host="127.0.0.1"
    fi

    local tunnel_port
    tunnel_port=$(next_free_port)

    printf "\n"
    draw_separator
    printf "  ${BOLD}Сервис:${NC}        $name\n"
    printf "  ${BOLD}Цель:${NC}          $target_host:$target_port\n"
    printf "  ${BOLD}Туннель:${NC}       порт $tunnel_port\n"
    [ -n "$domain" ] && printf "  ${BOLD}Домен:${NC}         $domain\n"
    printf "  ${BOLD}Внешний порт:${NC}  $ext_port\n"
    draw_separator

    prompt "Всё верно? Добавить сервис? (д/н) [д]: "
    local confirm="${REPLY:-д}"
    case "$confirm" in
        д|Д|y|Y|да|yes) ;;
        *) msg "Отменено"; pause; return ;;
    esac

    printf "\n"
    msg "Добавляю сервис '$name'..."

    # Генерация конфига nginx
    local nginx_conf=""
    if [ -n "$domain" ]; then
        nginx_conf="# rProxy: $name
server {
    listen 80;
    server_name $domain;

    location / {
        proxy_pass http://127.0.0.1:$tunnel_port;
        proxy_http_version 1.1;
        proxy_set_header Upgrade \$http_upgrade;
        proxy_set_header Connection \"upgrade\";
        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_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }
}
"
    else
        nginx_conf="# rProxy: $name
server {
    listen $ext_port;

    location / {
        proxy_pass http://127.0.0.1:$tunnel_port;
        proxy_http_version 1.1;
        proxy_set_header Upgrade \$http_upgrade;
        proxy_set_header Connection \"upgrade\";
        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_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }
}
"
    fi

    # Деплой nginx конфига на VPS
    local tmp_file="/tmp/rproxy_nginx_$name.conf"
    printf '%s' "$nginx_conf" > "$tmp_file"
    scp_cmd "$tmp_file" "$VPS_USER@$VPS_HOST:$REMOTE_NGINX_DIR/rproxy_$name.conf" || {
        err "Не удалось загрузить конфиг nginx на VPS"
        rm -f "$tmp_file"
        pause
        return
    }
    rm -f "$tmp_file"

    # Перезагрузка nginx
    ssh_cmd "nginx -t && systemctl reload nginx" || {
        err "Ошибка конфигурации nginx на VPS"
        ssh_cmd "rm -f $REMOTE_NGINX_DIR/rproxy_$name.conf"
        pause
        return
    }

    # Сохранение конфига сервиса
    cat > "$SERVICES_DIR/$name.conf" <<EOF
# rProxy сервис: $name
SVC_NAME="$name"
SVC_TARGET_HOST="$target_host"
SVC_TARGET_PORT="$target_port"
SVC_TUNNEL_PORT="$tunnel_port"
SVC_EXT_PORT="$ext_port"
SVC_DOMAIN="$domain"
SVC_ENABLED="yes"
EOF

    msg "Сервис '$name' добавлен!"

    # Автозапуск туннеля
    do_start_service "$name"
    pause
}

# ══════════════════════════════════════════════════════════════════════
# УДАЛИТЬ СЕРВИС (интерактивно)
# ══════════════════════════════════════════════════════════════════════
do_remove_interactive() {
    clear_screen
    draw_box "Удалить сервис"
    printf "\n"

    local services=""
    local idx=0
    for f in "$SERVICES_DIR"/*.conf 2>/dev/null; do
        [ -f "$f" ] || continue
        idx=$((idx + 1))
        . "$f"
        local st="○"
        is_running "$SVC_NAME" && st="●"
        printf "  ${BOLD}%d)${NC}  %s  %s  (%s:%s)\n" "$idx" "$st" "$SVC_NAME" "$SVC_TARGET_HOST" "$SVC_TARGET_PORT"
        services="$services $SVC_NAME"
    done

    if [ "$idx" -eq 0 ]; then
        printf "  ${YELLOW}Нет сервисов для удаления.${NC}\n"
        pause
        return
    fi

    printf "  ${BOLD}0)${NC}  Назад\n"
    prompt "Выберите сервис для удаления: "

    [ "$REPLY" = "0" ] && return
    [ -z "$REPLY" ] && return

    local sel_name
    sel_name=$(echo "$services" | tr ' ' '\n' | sed -n "${REPLY}p")
    [ -z "$sel_name" ] && { warn "Неверный выбор"; pause; return; }

    prompt "Удалить сервис '$sel_name'? (д/н) [н]: "
    local confirm="${REPLY:-н}"
    case "$confirm" in
        д|Д|y|Y|да|yes) ;;
        *) msg "Отменено"; pause; return ;;
    esac

    load_service "$sel_name" || { pause; return; }
    is_running "$sel_name" && do_stop_service "$sel_name"

    msg "Удаляю конфиг nginx на VPS..."
    ssh_cmd "rm -f $REMOTE_NGINX_DIR/rproxy_$sel_name.conf && nginx -t && systemctl reload nginx" || {
        warn "Не удалось удалить конфиг nginx на VPS"
    }

    rm -f "$SERVICES_DIR/$sel_name.conf"
    rm -f "$(get_pid_file "$sel_name")"

    msg "Сервис '$sel_name' удалён"
    pause
}

# ══════════════════════════════════════════════════════════════════════
# ВЫБОР СЕРВИСА (общий)
# ══════════════════════════════════════════════════════════════════════
select_service() {
    local title="$1"
    local filter="$2"  # all, running, stopped

    local services=""
    local idx=0
    for f in "$SERVICES_DIR"/*.conf 2>/dev/null; do
        [ -f "$f" ] || continue
        . "$f"

        local running=0
        is_running "$SVC_NAME" && running=1

        # Фильтр
        case "$filter" in
            running) [ "$running" -eq 0 ] && continue ;;
            stopped) [ "$running" -eq 1 ] && continue ;;
        esac

        idx=$((idx + 1))
        local st="${RED}○${NC}"
        [ "$running" -eq 1 ] && st="${GREEN}●${NC}"
        printf "  ${BOLD}%d)${NC}  %b  %-14s  %s:%s" "$idx" "$st" "$SVC_NAME" "$SVC_TARGET_HOST" "$SVC_TARGET_PORT"
        [ -n "$SVC_DOMAIN" ] && printf "  ${DIM}(%s)${NC}" "$SVC_DOMAIN"
        printf "\n"
        services="$services $SVC_NAME"
    done

    if [ "$idx" -eq 0 ]; then
        printf "  ${YELLOW}Нет подходящих сервисов.${NC}\n"
        SELECTED_SERVICE=""
        return 1
    fi

    printf "  ${BOLD}a)${NC}  Все сервисы\n"
    printf "  ${BOLD}0)${NC}  Назад\n"
    prompt "Выберите сервис: "

    [ "$REPLY" = "0" ] && { SELECTED_SERVICE=""; return 1; }
    if [ "$REPLY" = "a" ] || [ "$REPLY" = "A" ] || [ "$REPLY" = "а" ] || [ "$REPLY" = "А" ]; then
        SELECTED_SERVICE="__ALL__"
        return 0
    fi

    SELECTED_SERVICE=$(echo "$services" | tr ' ' '\n' | sed -n "${REPLY}p")
    [ -z "$SELECTED_SERVICE" ] && { warn "Неверный выбор"; return 1; }
    return 0
}

# ══════════════════════════════════════════════════════════════════════
# ЗАПУСК / ОСТАНОВ / ПЕРЕЗАПУСК (интерактивно)
# ══════════════════════════════════════════════════════════════════════
do_start_interactive() {
    clear_screen
    draw_box "Запустить туннель"
    printf "\n"
    select_service "Запустить" "stopped" || { pause; return; }

    if [ "$SELECTED_SERVICE" = "__ALL__" ]; then
        do_start_all
    else
        do_start_service "$SELECTED_SERVICE"
    fi
    pause
}

do_stop_interactive() {
    clear_screen
    draw_box "Остановить туннель"
    printf "\n"
    select_service "Остановить" "running" || { pause; return; }

    if [ "$SELECTED_SERVICE" = "__ALL__" ]; then
        do_stop_all
    else
        do_stop_service "$SELECTED_SERVICE"
    fi
    pause
}

do_restart_interactive() {
    clear_screen
    draw_box "Перезапустить туннель"
    printf "\n"
    select_service "Перезапустить" "all" || { pause; return; }

    if [ "$SELECTED_SERVICE" = "__ALL__" ]; then
        for f in "$SERVICES_DIR"/*.conf 2>/dev/null; do
            [ -f "$f" ] || continue
            . "$f"
            do_stop_service "$SVC_NAME"
            sleep 1
            do_start_service "$SVC_NAME"
        done
    else
        load_service "$SELECTED_SERVICE"
        do_stop_service "$SELECTED_SERVICE"
        sleep 1
        do_start_service "$SELECTED_SERVICE"
    fi
    pause
}

# ══════════════════════════════════════════════════════════════════════
# ЗАПУСК / ОСТАНОВ (одного сервиса)
# ══════════════════════════════════════════════════════════════════════
do_start_service() {
    local name="$1"
    load_service "$name" || return

    if is_running "$name"; then
        warn "Сервис '$name' уже запущен"
        return
    fi

    msg "Запускаю туннель '$name' ($SVC_TARGET_HOST:$SVC_TARGET_PORT → VPS:$SVC_TUNNEL_PORT)..."

    mkdir -p "$PID_DIR"
    local pid_file
    pid_file=$(get_pid_file "$name")

    local ssh_opts="-o StrictHostKeyChecking=no -o ServerAliveInterval=30 -o ServerAliveCountMax=3 -o ExitOnForwardFailure=yes"

    if [ "$VPS_AUTH" = "password" ]; then
        AUTOSSH_GATETIME=0 sshpass -p "$VPS_PASS" autossh -M 0 -f -N \
            $ssh_opts \
            -p "$VPS_PORT" \
            -R "0.0.0.0:$SVC_TUNNEL_PORT:$SVC_TARGET_HOST:$SVC_TARGET_PORT" \
            "$VPS_USER@$VPS_HOST" &
    else
        AUTOSSH_GATETIME=0 autossh -M 0 -f -N \
            $ssh_opts \
            -i "$SSH_KEY" \
            -p "$VPS_PORT" \
            -R "0.0.0.0:$SVC_TUNNEL_PORT:$SVC_TARGET_HOST:$SVC_TARGET_PORT" \
            "$VPS_USER@$VPS_HOST" &
    fi

    local bg_pid=$!
    sleep 2

    local real_pid
    real_pid=$(pgrep -f "autossh.*$SVC_TUNNEL_PORT:$SVC_TARGET_HOST:$SVC_TARGET_PORT" 2>/dev/null | head -1)
    [ -z "$real_pid" ] && real_pid=$(pgrep -f "ssh.*$SVC_TUNNEL_PORT:$SVC_TARGET_HOST:$SVC_TARGET_PORT" 2>/dev/null | head -1)
    [ -z "$real_pid" ] && real_pid=$bg_pid

    echo "$real_pid" > "$pid_file"
    msg "Туннель '$name' запущен (PID: $real_pid)"
}

do_stop_service() {
    local name="$1"
    local pid_file
    pid_file=$(get_pid_file "$name")

    if [ ! -f "$pid_file" ]; then
        warn "Сервис '$name' не запущен"
        return
    fi

    local pid
    pid=$(cat "$pid_file")
    kill "$pid" 2>/dev/null
    pkill -f "ssh.*:$name.*$VPS_HOST" 2>/dev/null

    rm -f "$pid_file"
    msg "Туннель '$name' остановлен"
}

do_start_all() {
    for f in "$SERVICES_DIR"/*.conf 2>/dev/null; do
        [ -f "$f" ] || continue
        . "$f"
        [ "$SVC_ENABLED" = "yes" ] && do_start_service "$SVC_NAME"
    done
}

do_stop_all() {
    for f in "$SERVICES_DIR"/*.conf 2>/dev/null; do
        [ -f "$f" ] || continue
        . "$f"
        do_stop_service "$SVC_NAME"
    done
}

# ══════════════════════════════════════════════════════════════════════
# НАСТРОЙКА VPS
# ══════════════════════════════════════════════════════════════════════
do_setup() {
    clear_screen
    draw_box "Настройка подключения к VPS"
    printf "\n"

    # Показать текущие настройки, если есть
    if check_conf; then
        printf "  ${DIM}Текущие настройки:${NC}\n"
        printf "  Хост: ${BOLD}$VPS_HOST${NC}  Порт: ${BOLD}$VPS_PORT${NC}  Пользователь: ${BOLD}$VPS_USER${NC}  Авторизация: ${BOLD}$VPS_AUTH${NC}\n"
        draw_separator
        printf "\n"
    fi

    prompt "IP-адрес VPS: "
    local vps_host="$REPLY"
    [ -z "$vps_host" ] && { warn "IP-адрес обязателен"; pause; return; }

    prompt "SSH порт [22]: "
    local vps_port="${REPLY:-22}"

    prompt "SSH пользователь [root]: "
    local vps_user="${REPLY:-root}"

    printf "\n  Метод авторизации:\n"
    printf "  ${BOLD}1)${NC} SSH-ключ (рекомендуется)\n"
    printf "  ${BOLD}2)${NC} Пароль\n"
    prompt "Выберите [1]: "
    local auth_choice="${REPLY:-1}"

    local vps_auth="key"
    local vps_pass=""

    if [ "$auth_choice" = "2" ]; then
        vps_auth="password"
        printf "  SSH пароль: "
        stty -echo 2>/dev/null
        read -r vps_pass
        stty echo 2>/dev/null
        printf "\n"

        if ! command -v sshpass >/dev/null 2>&1; then
            msg "Устанавливаю sshpass..."
            opkg install sshpass 2>/dev/null || {
                err "Не удалось установить sshpass. Установите вручную: opkg install sshpass"
                pause
                return
            }
        fi
    else
        if [ ! -f "$SSH_KEY" ]; then
            msg "Генерирую SSH-ключ..."
            mkdir -p "$CONF_DIR"
            ssh-keygen -t rsa -b 4096 -f "$SSH_KEY" -N "" -q
            msg "Ключ создан: $SSH_KEY"
        fi
    fi

    # Проверка подключения
    printf "\n"
    msg "Проверяю подключение к $vps_host..."
    if [ "$vps_auth" = "password" ]; then
        if ! sshpass -p "$vps_pass" ssh -o StrictHostKeyChecking=no -o ConnectTimeout=10 \
            -p "$vps_port" "$vps_user@$vps_host" "echo ok" >/dev/null 2>&1; then
            err "Не удалось подключиться к VPS. Проверьте параметры."
            pause
            return
        fi
    else
        msg "Копирую SSH-ключ на VPS..."
        printf "  Введите пароль VPS для копирования ключа:\n"
        ssh-copy-id -i "$SSH_KEY.pub" -p "$vps_port" "$vps_user@$vps_host" 2>/dev/null || {
            cat "$SSH_KEY.pub" | ssh -p "$vps_port" "$vps_user@$vps_host" \
                "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
        }

        if ! ssh -o StrictHostKeyChecking=no -o ConnectTimeout=10 \
            -i "$SSH_KEY" -p "$vps_port" "$vps_user@$vps_host" "echo ok" >/dev/null 2>&1; then
            err "Не удалось подключиться к VPS по ключу."
            pause
            return
        fi
    fi
    msg "Подключение успешно!"

    # Настройка nginx на VPS
    msg "Настраиваю nginx на VPS..."
    local ssh_setup_cmd
    if [ "$vps_auth" = "password" ]; then
        ssh_setup_cmd="sshpass -p \"$vps_pass\" ssh -o StrictHostKeyChecking=no -p $vps_port $vps_user@$vps_host"
    else
        ssh_setup_cmd="ssh -o StrictHostKeyChecking=no -i $SSH_KEY -p $vps_port $vps_user@$vps_host"
    fi

    eval $ssh_setup_cmd "'
        if ! command -v nginx >/dev/null 2>&1; then
            echo \"Устанавливаю nginx...\"
            apt-get update -qq && apt-get install -y -qq nginx >/dev/null 2>&1 || \
            yum install -y nginx >/dev/null 2>&1 || {
                echo \"FAIL: не удалось установить nginx\"
                exit 1
            }
        fi
        mkdir -p /etc/nginx/sites-enabled
        if ! grep -q \"include.*sites-enabled\" /etc/nginx/nginx.conf 2>/dev/null; then
            sed -i \"/http {/a\\\\    include /etc/nginx/sites-enabled/*.conf;\" /etc/nginx/nginx.conf 2>/dev/null
        fi
        systemctl enable nginx 2>/dev/null
        systemctl start nginx 2>/dev/null
        echo OK
    '" || {
        warn "Не удалось автоматически настроить nginx. Убедитесь, что nginx установлен на VPS."
    }

    # Сохранение конфига
    mkdir -p "$CONF_DIR" "$SERVICES_DIR" "$PID_DIR"
    cat > "$CONF_FILE" <<EOF
# rProxy — настройки VPS
VPS_HOST="$vps_host"
VPS_PORT="$vps_port"
VPS_USER="$vps_user"
VPS_AUTH="$vps_auth"
VPS_PASS="$vps_pass"
EOF
    chmod 600 "$CONF_FILE"

    msg "Конфигурация сохранена!"
    printf "\n  ${GREEN}${BOLD}VPS настроен и готов к работе.${NC}\n"
    pause
}

# ══════════════════════════════════════════════════════════════════════
# ТОЧКА ВХОДА
# ══════════════════════════════════════════════════════════════════════
mkdir -p "$CONF_DIR" "$SERVICES_DIR" "$PID_DIR" 2>/dev/null

# Поддержка прямых команд для init-скрипта и автоматизации
case "${1:-}" in
    start)      check_conf && do_start_all ;;
    stop)       check_conf && do_stop_all ;;
    restart)    check_conf && do_stop_all; sleep 1; do_start_all ;;
    status)
        check_conf || { err "VPS не настроен"; exit 1; }
        for f in "$SERVICES_DIR"/*.conf 2>/dev/null; do
            [ -f "$f" ] || continue
            . "$f"
            local state="остановлен"
            is_running "$SVC_NAME" && state="работает"
            local info="$SVC_NAME  $SVC_TARGET_HOST:$SVC_TARGET_PORT → :$SVC_EXT_PORT"
            [ -n "$SVC_DOMAIN" ] && info="$info ($SVC_DOMAIN)"
            echo "$info [$state]"
        done
        ;;
    -v|--version) echo "rProxy v$VERSION" ;;
    "")         main_menu ;;
    *)          main_menu ;;
esac
