#!/bin/bash
# ========== configure_remnanode.sh ==========
# Полная настройка RemnaNode:
# 1. Выбор панели (ghost/freesurf/test)
# 2. Загрузка API-токена из удалённого файла ключей
# 3. Создание профиля (если отсутствует) с конфигурацией
# 4. Создание ноды с автоматическим определением IP, страны и порта
# 5. Создание reality-хоста (без лишних полей)
# 6. Создание xhttp-хоста с расширенными параметрами

# ---------- ЛОГИРОВАНИЕ ----------
log_info() { echo "ℹ️  [INFO] $(date '+%Y-%m-%d %H:%M:%S') - $1"; }
log_success() { echo "✅ [SUCCESS] $(date '+%Y-%m-%d %H:%M:%S') - $1"; }
log_warning() { echo "⚠️  [WARNING] $(date '+%Y-%m-%d %H:%M:%S') - $1"; }
log_error() { echo "❌ [ERROR] $(date '+%Y-%m-%d %H:%M:%S') - $1" >&2; }
log_step() { echo "📋 [STEP] $(date '+%Y-%m-%d %H:%M:%S') - $1"; echo "=================================================="; }
log_request() { echo "🔸 [REQUEST] $(date '+%Y-%m-%d %H:%M:%S') - $1"; }
log_response() { echo "🔹 [RESPONSE] $(date '+%Y-%m-%d %H:%M:%S') - $1"; }

# ---------- ПРОВЕРКА ROOT ----------
if [[ $EUID -ne 0 ]]; then
    log_error "Модуль должен запускаться с правами root"
    exit 1
fi

# ---------- ПРОВЕРКА ПЕРЕМЕННОЙ LOCATION ----------
if [[ -z "$LOCATION" ]]; then
    log_error "Переменная LOCATION не установлена. Запустите главный скрипт и введите локацию."
    exit 1
fi

log_info "Настройка RemnaNode для локации: $LOCATION"

# ---------- ПРОВЕРКА/УСТАНОВКА JQ ----------
log_step "Проверка наличия jq"
if ! command -v jq &> /dev/null; then
    log_warning "jq не найден. Устанавливаю..."
    if command -v apt &> /dev/null; then
        apt update && apt install -y jq
    elif command -v dnf &> /dev/null; then
        dnf install -y jq
    elif command -v yum &> /dev/null; then
        yum install -y jq
    elif command -v pacman &> /dev/null; then
        pacman -S --noconfirm jq
    else
        log_error "Не удалось установить jq. Установите вручную."
        exit 1
    fi
    log_success "jq установлен."
else
    log_success "jq уже установлен."
fi

# ---------- ВЫБОР ПАНЕЛИ ----------
log_step "Выбор панели"
while true; do
    echo "Доступные панели:"
    echo "  - ghost"
    echo "  - freesurf"
    echo "  - test"
    read -rp "Введите название панели (только строчные буквы): " Panel
    Panel=$(echo "$Panel" | tr '[:upper:]' '[:lower:]')
    case "$Panel" in
        ghost|freesurf|test)
            log_success "Выбрана панель: $Panel"
            break
            ;;
        *)
            log_error "Недопустимое название. Допустимо: ghost, freesurf, test."
            ;;
    esac
done

# ---------- ЗАГРУЗКА API-ТОКЕНА ИЗ УДАЛЁННОГО ФАЙЛА ----------
log_step "Загрузка ключей API"
KEYS_URL="https://cloud.free-surf.ru/script/key"
KEYS_FILE=$(mktemp)
if ! curl -fsSL "$KEYS_URL" -o "$KEYS_FILE"; then
    log_error "Не удалось загрузить файл ключей с $KEYS_URL"
    rm -f "$KEYS_FILE"
    exit 1
fi

# Определяем префикс для поиска ключа
case "$Panel" in
    test)     KEY_PREFIX="test" ;;
    ghost)    KEY_PREFIX="ghost" ;;
    freesurf) KEY_PREFIX="fresurf" ;;  # в файле ключей для freesurf написано fresurf
esac

# Ищем строку, начинающуюся с "KEY_PREFIX=" и извлекаем значение после =
API_TOKEN=$(grep "^${KEY_PREFIX}=" "$KEYS_FILE" | head -n1 | cut -d'=' -f2- | tr -d '\n\r')
rm -f "$KEYS_FILE"

if [[ -z "$API_TOKEN" ]]; then
    log_error "Не удалось найти ключ для панели $Panel в загруженном файле."
    exit 1
fi
log_success "API-токен для панели $Panel загружен (первые 20 символов: ${API_TOKEN:0:20}...)"

# Проверка токена
TEST_URL="https://${Panel}.4rp.su/api/config-profiles"
log_request "GET $TEST_URL (проверка токена)"
response=$(curl -s -w "%{http_code}" -X GET "$TEST_URL" -H "Authorization: Bearer $API_TOKEN" 2>&1)
http_code="${response: -3}"
body="${response%???}"
log_response "HTTP код: $http_code"
if [[ "$http_code" != "200" && "$http_code" != "201" ]]; then
    log_error "API-токен недействителен (код $http_code)."
    exit 1
fi
log_success "API-токен действителен."

API_URL="https://${Panel}.4rp.su/api"

# ---------- ПОДГОТОВКА JSON ДЛЯ ПРОФИЛЯ ----------
log_step "Подготовка конфигурации профиля"
PROFILE_NAME=$(echo "$LOCATION" | tr '[:lower:]' '[:upper:]')
log_info "Имя профиля: $PROFILE_NAME"

CONFIG_TEMPLATE=$(cat <<'EOF'
{
  "log": {
    "loglevel": "info"
  },
  "dns": {
    "port": 53,
    "servers": [
      "tcp://127.0.0.1"
    ],
    "queryStrategy": "UseIPv4"
  },
  "inbounds": [
    {
      "tag": "__LOCATION___vless_tcp",
      "port": 443,
      "protocol": "vless",
      "settings": {
        "clients": [],
        "decryption": "none"
      },
      "sniffing": {
        "enabled": true,
        "destOverride": [
          "http",
          "tls",
          "quic"
        ]
      },
      "streamSettings": {
        "network": "tcp",
        "security": "reality",
        "realitySettings": {
          "dest": "/dev/shm/__Panel___nginx.sock",
          "show": false,
          "xver": 1,
          "spiderX": "",
          "shortIds": [
            "63d3b84b13b62543"
          ],
          "privateKey": "bYe9ICeNkZllf3aJDo4HMzYevFygROrRxabMLdyLl5c",
          "serverNames": [
            "__Panel____LOCATION__.8rmdgz.ru"
          ]
        }
      }
    },
    {
      "tag": "__LOCATION___vless_xhttp",
      "listen": "/dev/shm/__Panel___xrxh.socket,0666",
      "protocol": "vless",
      "settings": {
        "clients": [],
        "fallbacks": [],
        "decryption": "none"
      },
      "sniffing": {
        "enabled": true,
        "destOverride": [
          "http",
          "tls",
          "quic"
        ]
      },
      "streamSettings": {
        "network": "xhttp",
        "xhttpSettings": {
          "mode": "auto",
          "path": "/xhttp/",
          "extra": {
            "noSSEHeader": true,
            "xPaddingBytes": "100-1000",
            "scMaxBufferedPosts": 30,
            "scMaxEachPostBytes": 1000000,
            "scStreamUpServerSecs": "20-80"
          }
        }
      }
    }
  ],
  "outbounds": [
    {
      "tag": "DIRECT",
      "protocol": "freedom"
    },
    {
      "tag": "BLOCK",
      "protocol": "blackhole"
    }
  ],
  "routing": {
    "rules": [
      {
        "ip": [
          "geoip:private"
        ],
        "type": "field",
        "outboundTag": "BLOCK"
      },
      {
        "type": "field",
        "protocol": [
          "bittorrent"
        ],
        "outboundTag": "BLOCK"
      }
    ]
  }
}
EOF
)

FINAL_JSON=$(echo "$CONFIG_TEMPLATE" | sed "s/__LOCATION__/$LOCATION/g" | sed "s/__Panel__/$Panel/g" | jq .)
if [[ $? -ne 0 ]]; then
    log_error "Ошибка при формировании JSON конфигурации."
    exit 1
fi
log_success "Конфигурация профиля подготовлена"

# ---------- СОЗДАНИЕ ПРОФИЛЯ ----------
log_step "Создание профиля через API"
PROFILE_URL="$API_URL/config-profiles"
log_request "POST $PROFILE_URL с именем профиля $PROFILE_NAME"

CREATE_JSON=$(jq -n --arg name "$PROFILE_NAME" --argjson config "$FINAL_JSON" '{name: $name, config: $config}')

response=$(curl -s -w "%{http_code}" -X POST "$PROFILE_URL" \
    -H "Authorization: Bearer $API_TOKEN" \
    -H "Content-Type: application/json" \
    -d "$CREATE_JSON" 2>&1)
http_code="${response: -3}"
body="${response%???}"

log_response "HTTP код: $http_code"
log_response "Тело ответа: $body"

PROFILE_UUID=""
INBOUNDS_JSON=""

if [[ "$http_code" == "201" ]]; then
    log_success "Профиль '$PROFILE_NAME' успешно создан."
    PROFILE_UUID=$(echo "$body" | jq -r '.response.uuid')
    INBOUNDS_JSON=$(echo "$body" | jq -c '.response.inbounds')
elif [[ "$http_code" == "409" ]]; then
    log_warning "Профиль с именем '$PROFILE_NAME' уже существует (код 409)."
    # Получаем UUID существующего профиля
    PROFILES_URL="$API_URL/config-profiles"
    response=$(curl -s -w "%{http_code}" -X GET "$PROFILES_URL" -H "Authorization: Bearer $API_TOKEN" 2>&1)
    http_code="${response: -3}"
    body="${response%???}"
    if [[ "$http_code" != "200" ]]; then
        log_error "Не удалось получить список профилей."
        exit 1
    fi
    PROFILE_UUID=$(echo "$body" | jq -r --arg name "$PROFILE_NAME" '.response.configProfiles[] | select(.name == $name) | .uuid')
    if [[ -z "$PROFILE_UUID" || "$PROFILE_UUID" == "null" ]]; then
        log_error "Не удалось найти UUID профиля '$PROFILE_NAME'."
        exit 1
    fi
    INBOUNDS_JSON=$(echo "$body" | jq -c --arg uuid "$PROFILE_UUID" '.response.configProfiles[] | select(.uuid == $uuid) | .inbounds')
    log_success "UUID профиля получен: $PROFILE_UUID"
else
    log_error "Ошибка при создании профиля (код $http_code)."
    exit 1
fi

# ---------- ПОЛУЧЕНИЕ UUID ИНБАУНДОВ ----------
if [[ -z "$INBOUNDS_JSON" || "$INBOUNDS_JSON" == "null" ]]; then
    log_error "Не удалось получить инбаунды профиля."
    exit 1
fi
log_success "Инбаунды профиля получены."

# ---------- ОПРЕДЕЛЕНИЕ IP СЕРВЕРА ----------
log_step "Определение IP адреса сервера"
SERVER_IP=$(curl -s ifconfig.me)
if [[ -z "$SERVER_IP" ]]; then
    SERVER_IP=$(hostname -I | awk '{print $1}')
fi
if [[ -z "$SERVER_IP" ]]; then
    log_error "Не удалось определить IP сервера."
    exit 1
fi
log_success "IP сервера: $SERVER_IP"

# ---------- ОПРЕДЕЛЕНИЕ СТРАНЫ ПО IP ----------
log_step "Определение страны по IP"
COUNTRY_DATA=$(curl -s "http://ip-api.com/json/$SERVER_IP?fields=country,countryCode")
if [[ -z "$COUNTRY_DATA" ]]; then
    log_warning "Не удалось получить данные о стране, буду использовать код страны из ноды (если есть)."
    COUNTRY_NAME=""
    COUNTRY_CODE=""
else
    COUNTRY_CODE=$(echo "$COUNTRY_DATA" | jq -r '.countryCode')
    COUNTRY_NAME=$(echo "$COUNTRY_DATA" | jq -r '.country')
    if [[ "$COUNTRY_CODE" == "null" ]]; then COUNTRY_CODE=""; fi
    if [[ "$COUNTRY_NAME" == "null" ]]; then COUNTRY_NAME=""; fi
fi

# Функция для преобразования двухбуквенного кода страны в эмодзи-флаг
country_code_to_flag() {
    local code="$1"
    local flag=""
    if [[ ${#code} -eq 2 ]]; then
        # Коды региональных индикаторов: A=0x1F1E6, B=0x1F1E7, ...
        local first=$(printf "\\U$(printf '%x' $((0x1F1E6 + $(printf '%d' "'${code:0:1}") - 65)) )")
        local second=$(printf "\\U$(printf '%x' $((0x1F1E6 + $(printf '%d' "'${code:1:1}") - 65)) )")
        flag="${first}${second}"
    else
        flag=""
    fi
    echo "$flag"
}

# ---------- ПОРТ В ЗАВИСИМОСТИ ОТ ПАНЕЛИ ----------
case "$Panel" in
    test)     NODE_PORT=9871 ;;
    ghost)    NODE_PORT=9872 ;;
    freesurf) NODE_PORT=9873 ;;
    *)
        log_error "Неизвестная панель: $Panel"
        exit 1
        ;;
esac
log_info "Порт ноды: $NODE_PORT"

# ---------- СОЗДАНИЕ НОДЫ ----------
log_step "Создание ноды через API"
NODE_NAME="${Panel}${LOCATION}.8rmdgz.ru"
NODE_URL="$API_URL/nodes"

# Формируем массив UUID инбаундов для передачи в ноду
INBOUND_UUIDS=$(echo "$INBOUNDS_JSON" | jq -r '.[].uuid')
mapfile -t INBOUND_ARRAY <<< "$INBOUND_UUIDS"

if [[ -n "$COUNTRY_CODE" ]]; then
    NODE_COUNTRY_CODE="$COUNTRY_CODE"
else
    NODE_COUNTRY_CODE="XX"
fi

CREATE_NODE_JSON=$(jq -n \
    --arg name "$NODE_NAME" \
    --arg address "$SERVER_IP" \
    --argjson port "$NODE_PORT" \
    --arg profileUuid "$PROFILE_UUID" \
    --argjson inbounds "$(printf '%s\n' "${INBOUND_ARRAY[@]}" | jq -R . | jq -s .)" \
    --arg country "$NODE_COUNTRY_CODE" \
    '{
        name: $name,
        address: $address,
        port: $port,
        countryCode: $country,
        configProfile: {
            activeConfigProfileUuid: $profileUuid,
            activeInbounds: $inbounds
        },
        isTrafficTrackingActive: false,
        consumptionMultiplier: 1.0
    }')

log_request "POST $NODE_URL с именем ноды $NODE_NAME"
response=$(curl -s -w "%{http_code}" -X POST "$NODE_URL" \
    -H "Authorization: Bearer $API_TOKEN" \
    -H "Content-Type: application/json" \
    -d "$CREATE_NODE_JSON" 2>&1)
http_code="${response: -3}"
body="${response%???}"
log_response "HTTP код: $http_code"
log_response "Тело ответа: $body"

if [[ "$http_code" != "201" && "$http_code" != "200" ]]; then
    log_error "Ошибка при создании ноды (код $http_code)."
    exit 1
fi

NODE_UUID=$(echo "$body" | jq -r '.response.uuid')
NODE_COUNTRY_CODE_FROM_RESPONSE=$(echo "$body" | jq -r '.response.countryCode')
if [[ -n "$NODE_COUNTRY_CODE_FROM_RESPONSE" && "$NODE_COUNTRY_CODE_FROM_RESPONSE" != "null" ]]; then
    NODE_COUNTRY_CODE="$NODE_COUNTRY_CODE_FROM_RESPONSE"
fi
log_success "Нода '$NODE_NAME' создана, UUID: $NODE_UUID, код страны: $NODE_COUNTRY_CODE"

# ---------- ФОРМИРОВАНИЕ БАЗОВОГО НАЗВАНИЯ СТРАНЫ С ЦИФРАМИ ----------
if [[ -n "$COUNTRY_NAME" ]]; then
    FULL_COUNTRY_NAME="$COUNTRY_NAME"
else
    FULL_COUNTRY_NAME="$NODE_COUNTRY_CODE"
fi

FLAG=$(country_code_to_flag "$NODE_COUNTRY_CODE")
if [[ -z "$FLAG" ]]; then
    FLAG="🏳️"
fi

LOCATION_DIGITS=$(echo "$LOCATION" | grep -oE '[0-9]+$')
if [[ -z "$LOCATION_DIGITS" ]]; then
    LOCATION_DIGITS=""
fi

BASE_REMARK="${FLAG} ${FULL_COUNTRY_NAME}${LOCATION_DIGITS}"

# ---------- ПОИСК UUID ИНБАУНДОВ ----------
REALITY_INBOUND_UUID=$(echo "$INBOUNDS_JSON" | jq -r '.[] | select(.tag | endswith("_vless_tcp")) | .uuid')
XHTTP_INBOUND_UUID=$(echo "$INBOUNDS_JSON" | jq -r '.[] | select(.tag | endswith("_vless_xhttp")) | .uuid')

if [[ -z "$REALITY_INBOUND_UUID" || "$REALITY_INBOUND_UUID" == "null" ]]; then
    log_error "Не удалось найти inbound с тегом, оканчивающимся на '_vless_tcp'"
    exit 1
fi
log_success "UUID reality inbound: $REALITY_INBOUND_UUID"

if [[ -z "$XHTTP_INBOUND_UUID" || "$XHTTP_INBOUND_UUID" == "null" ]]; then
    log_error "Не удалось найти inbound с тегом, оканчивающимся на '_vless_xhttp'"
    exit 1
fi
log_success "UUID xhttp inbound: $XHTTP_INBOUND_UUID"

# ---------- ОБЩИЕ ДАННЫЕ ДЛЯ ХОСТОВ ----------
HOST_ADDRESS="${Panel}${LOCATION}.8rmdgz.ru"
SNI="$HOST_ADDRESS"

# ---------- СОЗДАНИЕ ХОСТА REALITY ----------
log_step "Создание reality хоста"
REMARK_REALITY="${BASE_REMARK} (Reality)"
HOSTS_URL="$API_URL/hosts"
CREATE_HOST_REALITY_JSON=$(jq -n \
    --arg inboundProfileUuid "$PROFILE_UUID" \
    --arg inboundUuid "$REALITY_INBOUND_UUID" \
    --arg remark "$REMARK_REALITY" \
    --arg address "$HOST_ADDRESS" \
    --argjson port 443 \
    --arg sni "$SNI" \
    --arg nodeUuid "$NODE_UUID" \
    '{
        inbound: {
            configProfileUuid: $inboundProfileUuid,
            configProfileInboundUuid: $inboundUuid
        },
        remark: $remark,
        address: $address,
        port: $port,
        sni: $sni,
        nodes: [$nodeUuid],
        isDisabled: false
    }')

log_request "POST $HOSTS_URL (reality)"
response=$(curl -s -w "%{http_code}" -X POST "$HOSTS_URL" \
    -H "Authorization: Bearer $API_TOKEN" \
    -H "Content-Type: application/json" \
    -d "$CREATE_HOST_REALITY_JSON" 2>&1)
http_code="${response: -3}"
body="${response%???}"
log_response "HTTP код: $http_code"
log_response "Тело ответа: $body"

if [[ "$http_code" == "201" || "$http_code" == "200" ]]; then
    log_success "Хост reality '$REMARK_REALITY' успешно создан."
else
    log_error "Ошибка при создании хоста reality (код $http_code)."
    exit 1
fi

# ---------- СОЗДАНИЕ ХОСТА XHTTP ----------
log_step "Создание xhttp хоста"
REMARK_XHTTP="${BASE_REMARK} (xHTTP)"

# Дополнительные параметры xHTTP (extra) как в задании
XHTTP_EXTRA=$(cat <<'EOF'
{
  "xmux": {
    "cMaxReuseTimes": 0,
    "maxConcurrency": "16-32",
    "maxConnections": 0,
    "hKeepAlivePeriod": 0,
    "hMaxRequestTimes": "600-900",
    "hMaxReusableSecs": "1800-3000"
  },
  "noGRPCHeader": false,
  "xPaddingBytes": "100-1000",
  "scMaxBufferedPosts": 30,
  "scMaxEachPostBytes": 1000000,
  "scMinPostsIntervalMs": 30,
  "scStreamUpServerSecs": "20-80"
}
EOF
)

CREATE_HOST_XHTTP_JSON=$(jq -n \
    --arg inboundProfileUuid "$PROFILE_UUID" \
    --arg inboundUuid "$XHTTP_INBOUND_UUID" \
    --arg remark "$REMARK_XHTTP" \
    --arg address "$HOST_ADDRESS" \
    --argjson port 443 \
    --arg path "/xhttp/" \
    --arg sni "$SNI" \
    --arg host "$HOST_ADDRESS" \
    --arg nodeUuid "$NODE_UUID" \
    --argjson extra "$XHTTP_EXTRA" \
    '{
        inbound: {
            configProfileUuid: $inboundProfileUuid,
            configProfileInboundUuid: $inboundUuid
        },
        remark: $remark,
        address: $address,
        port: $port,
        path: $path,
        sni: $sni,
        host: $host,
        alpn: "h2,http/1.1",
        fingerprint: "chrome",
        securityLayer: "TLS",
        xHttpExtraParams: $extra,
        nodes: [$nodeUuid],
        isDisabled: false
    }')

log_request "POST $HOSTS_URL (xhttp)"
response=$(curl -s -w "%{http_code}" -X POST "$HOSTS_URL" \
    -H "Authorization: Bearer $API_TOKEN" \
    -H "Content-Type: application/json" \
    -d "$CREATE_HOST_XHTTP_JSON" 2>&1)
http_code="${response: -3}"
body="${response%???}"
log_response "HTTP код: $http_code"
log_response "Тело ответа: $body"

if [[ "$http_code" == "201" || "$http_code" == "200" ]]; then
    log_success "Хост xhttp '$REMARK_XHTTP' успешно создан."
else
    log_error "Ошибка при создании хоста xhttp (код $http_code)."
    exit 1
fi

log_success "Модуль configure_remnanode.sh выполнен"
exit 0
