#!/bin/sh
# MeduzaVPN Keenetic (Entware / OPKG) & Linux Router Installer
# Installs:
#   - meduzavpnd (full daemon: MeduzaVPN ULTRA, AmneziaWG 3.1, Hysteria 2, VLESS 2.0, WireGuard, OpenVPN)
#   - meduzavpn  (CLI utility)
#   - meduzavpn-webui (Router Web UI on port :2222, similar to awg-manager)
#
# One-line install in Keenetic Entware SSH:
#   opkg update && wget -qO- https://meduzacore.com/download/keenetic-install.sh | sh

set -e

CDN_BASE="${MEDUZAVPN_CDN:-https://meduzavpn-builds.fra1.digitaloceanspaces.com/latest/routers}"
WEBUI_PORT="${MEDUZAVPN_WEBUI_PORT:-2222}"

echo "================================================================"
echo "  MeduzaVPN Router Installer (Keenetic Entware OPKG + WebUI :2222)"
echo "  Protocols: ULTRA • AmneziaWG 3.1 • Hysteria 2 • VLESS 2.0 • WG"
echo "================================================================"

# 1. Detect Entware (/opt) vs standard root
if [ -d /opt/etc ]; then
    PREFIX="/opt"
    SBINDIR="/opt/sbin"
    BINDIR="/opt/bin"
    ETCDIR="/opt/etc/meduzavpn"
    RUNDIR="/opt/var/run/meduzavpn"
    LOGDIR="/opt/var/log"
    INITDIR="/opt/etc/init.d"
    IS_ENTWARE=1
else
    PREFIX="/usr"
    SBINDIR="/usr/sbin"
    BINDIR="/usr/bin"
    ETCDIR="/etc/meduzavpn"
    RUNDIR="/run/meduzavpn"
    LOGDIR="/var/log"
    INITDIR="/etc/init.d"
    IS_ENTWARE=0
fi

# 2. Detect CPU architecture (mipsle, mips, arm, arm64)
detect_arch() {
    if command -v opkg >/dev/null 2>&1; then
        OPKG_ARCH="$(opkg print-architecture 2>/dev/null | awk '{print $2}' | tail -n 1)"
        case "$OPKG_ARCH" in
            *mipsel*|*mipsle*) echo "mipsle"; return ;;
            *mips*)            echo "mips"; return ;;
            *aarch64*|*arm64*) echo "arm64"; return ;;
            *arm*)             echo "arm"; return ;;
        esac
    fi
    UNAME_M="$(uname -m 2>/dev/null || echo unknown)"
    case "$UNAME_M" in
        mipsel|mipsle) echo "mipsle"; return ;;
        mips)
            if grep -qi "little endian" /proc/cpuinfo 2>/dev/null; then
                echo "mipsle"; return
            fi
            # Check ELF endianness byte (byte 6: 01 = little-endian, 02 = big-endian)
            END_BYTE="$(dd if=/bin/sh bs=1 skip=5 count=1 2>/dev/null | od -An -tx1 | tr -d ' \n')"
            if [ "$END_BYTE" = "01" ]; then
                echo "mipsle"; return
            fi
            echo "mips"; return
            ;;
        aarch64|arm64) echo "arm64"; return ;;
        armv7*|armv8*|arm*) echo "arm"; return ;;
        *)
            echo "unsupported:$UNAME_M"
            ;;
    esac
}

ARCH="$(detect_arch)"
case "$ARCH" in
    mipsle|mips|arm|arm64)
        echo "[1/6] Архитектура роутера определена: $ARCH (префикс: $PREFIX)"
        ;;
    *)
        echo "Ошибка: неподдерживаемая архитектура процессора ($ARCH)."
        echo "Поддерживаются роутеры на базе mipsle, mips, arm и arm64."
        exit 1
        ;;
esac

# 3. Install required Entware / OPKG packages
if command -v opkg >/dev/null 2>&1; then
    echo "[2/6] Проверка системных пакетов через opkg..."
    opkg update >/dev/null 2>&1 || true
    for pkg in ca-bundle ca-certificates ip-full iptables; do
        opkg install "$pkg" >/dev/null 2>&1 || true
    done
else
    echo "[2/6] Менеджер пакетов opkg не найден, продолжаем установку бинарных файлов..."
fi

# Ensure /dev/net/tun exists
if [ ! -e /dev/net/tun ]; then
    mkdir -p /dev/net 2>/dev/null || true
    mknod /dev/net/tun c 10 200 2>/dev/null || true
    chmod 666 /dev/net/tun 2>/dev/null || true
fi

mkdir -p "$SBINDIR" "$BINDIR" "$ETCDIR" "$RUNDIR" "$LOGDIR" "$INITDIR"
chmod 700 "$ETCDIR" "$RUNDIR" 2>/dev/null || true

# 4. Download router tarball and Web UI binary
TMPDIR="$(mktemp -d /tmp/meduzavpn-install.XXXXXX 2>/dev/null || echo /tmp/meduzavpn-install)"
mkdir -p "$TMPDIR"
cleanup() {
    rm -rf "$TMPDIR"
}
trap cleanup EXIT

fetch_file() {
    URL="$1"
    DEST="$2"
    if command -v curl >/dev/null 2>&1; then
        curl -fsSL --connect-timeout 15 --max-time 180 -o "$DEST" "$URL"
    elif command -v wget >/dev/null 2>&1; then
        wget -q -O "$DEST" "$URL"
    elif command -v uclient-fetch >/dev/null 2>&1; then
        uclient-fetch -q -O "$DEST" "$URL"
    else
        echo "Ошибка: не найден wget, curl или uclient-fetch."
        exit 1
    fi
}

TARBALL_URL="${CDN_BASE}/meduzavpn-router-${ARCH}.tar.gz"
WEBUI_URL="${CDN_BASE}/meduzavpn-webui-${ARCH}"

echo "[3/6] Скачивание ядра MeduzaVPN (${ARCH})..."
fetch_file "$TARBALL_URL" "$TMPDIR/meduzavpn-router.tar.gz"

echo "[4/6] Скачивание веб-интерфейса управления meduzavpn-webui (:2222)..."
fetch_file "$WEBUI_URL" "$TMPDIR/meduzavpn-webui"

# Stop running services before replacing binaries
if [ -x "$INITDIR/S99meduzavpn-webui" ]; then
    "$INITDIR/S99meduzavpn-webui" stop >/dev/null 2>&1 || true
fi
if [ -x "$INITDIR/S99meduzavpnd" ]; then
    "$INITDIR/S99meduzavpnd" stop >/dev/null 2>&1 || true
fi
killall meduzavpn-webui >/dev/null 2>&1 || true
killall meduzavpnd >/dev/null 2>&1 || true

echo "[5/6] Установка компонентов в $SBINDIR и $BINDIR..."
tar -xzf "$TMPDIR/meduzavpn-router.tar.gz" -C "$TMPDIR"
EXTRACT_DIR="$(find "$TMPDIR" -maxdepth 2 -type f -name meduzavpnd -exec dirname {} \; | head -n 1)"
if [ -z "$EXTRACT_DIR" ]; then
    echo "Ошибка: не удалось распаковать архив meduzavpn-router-${ARCH}.tar.gz"
    exit 1
fi

cp -f "$EXTRACT_DIR/meduzavpnd" "$SBINDIR/meduzavpnd"
cp -f "$EXTRACT_DIR/meduzavpnd-lite" "$SBINDIR/meduzavpnd-lite" 2>/dev/null || true
cp -f "$EXTRACT_DIR/meduzavpn" "$SBINDIR/meduzavpn.bin"
cp -f "$TMPDIR/meduzavpn-webui" "$SBINDIR/meduzavpn-webui"
chmod 755 "$SBINDIR/meduzavpnd" "$SBINDIR/meduzavpn.bin" "$SBINDIR/meduzavpn-webui"
chmod 755 "$SBINDIR/meduzavpnd-lite" 2>/dev/null || true

# Create CLI wrapper so `meduzavpn` works out of the box in Entware SSH
cat > "$BINDIR/meduzavpn" <<EOF
#!/bin/sh
export PATH="$SBINDIR:$BINDIR:/usr/sbin:/usr/bin:/sbin:/bin:\$PATH"
if [ -f /opt/etc/ssl/certs/ca-certificates.crt ] && [ -z "\$SSL_CERT_FILE" ]; then
    export SSL_CERT_FILE="/opt/etc/ssl/certs/ca-certificates.crt"
fi
export MEDUZAVPN_CONFIG="\${MEDUZAVPN_CONFIG:-$ETCDIR/config.json}"
export MEDUZAVPN_SOCKET="\${MEDUZAVPN_SOCKET:-$RUNDIR/control.sock}"
export MEDUZAVPN_HOME="\${MEDUZAVPN_HOME:-$ETCDIR}"
exec "$SBINDIR/meduzavpn.bin" "\$@"
EOF
chmod 755 "$BINDIR/meduzavpn"

# Create default config.json if not present
if [ ! -f "$ETCDIR/config.json" ]; then
    cat > "$ETCDIR/config.json" <<EOF
{
  "auto_connect": true,
  "socket": "$RUNDIR/control.sock"
}
EOF
    chmod 600 "$ETCDIR/config.json"
fi

# 5. Create Keenetic NDM netfilter hook & Entware init scripts
if [ "$IS_ENTWARE" = "1" ]; then
    mkdir -p /opt/etc/ndm/netfilter.d 2>/dev/null || true
    cat > /opt/etc/ndm/netfilter.d/100-meduzavpn.sh <<'EOF'
#!/bin/sh
export PATH="/opt/sbin:/opt/bin:/usr/sbin:/usr/bin:/sbin:/bin:$PATH"
[ "$table" != "filter" ] && [ "$table" != "nat" ] && [ "$table" != "mangle" ] && [ -n "$table" ] && exit 0
if ip link show 2>/dev/null | grep -q "meduza"; then
    iptables -t nat -C POSTROUTING -o meduza+ -j MASQUERADE 2>/dev/null || \
        iptables -t nat -A POSTROUTING -o meduza+ -j MASQUERADE 2>/dev/null || true
    iptables -C FORWARD -i br0 -o meduza+ -j ACCEPT 2>/dev/null || \
        iptables -I FORWARD 1 -i br0 -o meduza+ -j ACCEPT 2>/dev/null || true
    iptables -C FORWARD -i meduza+ -o br0 -m state --state RELATED,ESTABLISHED -j ACCEPT 2>/dev/null || \
        iptables -I FORWARD 2 -i meduza+ -o br0 -m state --state RELATED,ESTABLISHED -j ACCEPT 2>/dev/null || true
    iptables -t mangle -C FORWARD -p tcp --tcp-flags SYN,RST SYN -o meduza+ -j TCPMSS --clamp-mss-to-pmtu 2>/dev/null || \
        iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -o meduza+ -j TCPMSS --clamp-mss-to-pmtu 2>/dev/null || true
fi
EOF
    chmod 755 /opt/etc/ndm/netfilter.d/100-meduzavpn.sh
fi

cat > "$INITDIR/S99meduzavpnd" <<EOF
#!/bin/sh
export PATH="$SBINDIR:$BINDIR:/usr/sbin:/usr/bin:/sbin:/bin:\$PATH"
if [ -f /opt/etc/ssl/certs/ca-certificates.crt ]; then
    export SSL_CERT_FILE="/opt/etc/ssl/certs/ca-certificates.crt"
fi
DAEMON="$SBINDIR/meduzavpnd"
CONFIG="$ETCDIR/config.json"
SOCKET="$RUNDIR/control.sock"
STATEDIR="$ETCDIR"
PIDFILE="$RUNDIR/meduzavpnd.pid"
LOGFILE="$LOGDIR/meduzavpnd.log"

start() {
    mkdir -p "$RUNDIR" "$ETCDIR" "$LOGDIR"
    if [ -f "\$PIDFILE" ] && kill -0 "\$(cat "\$PIDFILE" 2>/dev/null)" 2>/dev/null; then
        echo "meduzavpnd is already running."
        return 0
    fi
    rm -f "\$SOCKET"
    echo "Starting meduzavpnd..."
    "\$DAEMON" -config "\$CONFIG" -socket "\$SOCKET" -state-dir "\$STATEDIR" >>"\$LOGFILE" 2>&1 &
    echo \$! > "\$PIDFILE"
    sleep 1
    if [ -x /opt/etc/ndm/netfilter.d/100-meduzavpn.sh ]; then
        /opt/etc/ndm/netfilter.d/100-meduzavpn.sh >/dev/null 2>&1 || true
    fi
}

stop() {
    if [ -f "\$PIDFILE" ]; then
        PID="\$(cat "\$PIDFILE" 2>/dev/null)"
        if [ -n "\$PID" ] && kill -0 "\$PID" 2>/dev/null; then
            echo "Stopping meduzavpnd..."
            kill "\$PID" 2>/dev/null || true
            sleep 1
        fi
        rm -f "\$PIDFILE"
    fi
    killall meduzavpnd 2>/dev/null || true
    rm -f "\$SOCKET"
}

case "\$1" in
    start)   start ;;
    stop)    stop ;;
    restart) stop; start ;;
    status)
        if [ -f "\$PIDFILE" ] && kill -0 "\$(cat "\$PIDFILE" 2>/dev/null)" 2>/dev/null; then
            echo "meduzavpnd is running (PID \$(cat "\$PIDFILE"))."
        else
            echo "meduzavpnd is stopped."
            exit 1
        fi
        ;;
    *)
        echo "Usage: \$0 {start|stop|restart|status}"
        exit 1
        ;;
esac
EOF
chmod 755 "$INITDIR/S99meduzavpnd"

cat > "$INITDIR/S99meduzavpn-webui" <<EOF
#!/bin/sh
export PATH="$SBINDIR:$BINDIR:/usr/sbin:/usr/bin:/sbin:/bin:\$PATH"
if [ -f /opt/etc/ssl/certs/ca-certificates.crt ]; then
    export SSL_CERT_FILE="/opt/etc/ssl/certs/ca-certificates.crt"
fi
WEBUI="$SBINDIR/meduzavpn-webui"
CONFIG="$ETCDIR/config.json"
SOCKET="$RUNDIR/control.sock"
STATEDIR="$ETCDIR"
INIT_SCRIPT="$INITDIR/S99meduzavpnd"
PIDFILE="$RUNDIR/meduzavpn-webui.pid"
LOGFILE="$LOGDIR/meduzavpn-webui.log"
LISTEN=":${WEBUI_PORT}"

start() {
    mkdir -p "$RUNDIR" "$ETCDIR" "$LOGDIR"
    if [ -f "\$PIDFILE" ] && kill -0 "\$(cat "\$PIDFILE" 2>/dev/null)" 2>/dev/null; then
        echo "meduzavpn-webui is already running."
        return 0
    fi
    echo "Starting meduzavpn-webui on \$LISTEN..."
    "\$WEBUI" -listen "\$LISTEN" -config "\$CONFIG" -socket "\$SOCKET" -state-dir "\$STATEDIR" -init-script "\$INIT_SCRIPT" >>"\$LOGFILE" 2>&1 &
    echo \$! > "\$PIDFILE"
}

stop() {
    if [ -f "\$PIDFILE" ]; then
        PID="\$(cat "\$PIDFILE" 2>/dev/null)"
        if [ -n "\$PID" ] && kill -0 "\$PID" 2>/dev/null; then
            echo "Stopping meduzavpn-webui..."
            kill "\$PID" 2>/dev/null || true
        fi
        rm -f "\$PIDFILE"
    fi
    killall meduzavpn-webui 2>/dev/null || true
}

case "\$1" in
    start)   start ;;
    stop)    stop ;;
    restart) stop; start ;;
    status)
        if [ -f "\$PIDFILE" ] && kill -0 "\$(cat "\$PIDFILE" 2>/dev/null)" 2>/dev/null; then
            echo "meduzavpn-webui is running (PID \$(cat "\$PIDFILE"))."
        else
            echo "meduzavpn-webui is stopped."
            exit 1
        fi
        ;;
    *)
        echo "Usage: \$0 {start|stop|restart|status}"
        exit 1
        ;;
esac
EOF
chmod 755 "$INITDIR/S99meduzavpn-webui"

# 6. Start daemon and Web UI
echo "[6/6] Запуск служб meduzavpnd и meduzavpn-webui..."
"$INITDIR/S99meduzavpnd" restart
"$INITDIR/S99meduzavpn-webui" restart

ROUTER_IP="$(ip -4 addr show br0 2>/dev/null | awk '/inet / {split($2,a,"/"); print a[1]; exit}')"
if [ -z "$ROUTER_IP" ]; then
    ROUTER_IP="192.168.1.1"
fi

echo ""
echo "================================================================"
echo "  MeduzaVPN успешно установлен на роутер!"
echo "================================================================"
echo "  Веб-панель управления (по аналогии с awg-manager):"
echo "    http://${ROUTER_IP}:${WEBUI_PORT}"
echo ""
echo "  В веб-панели доступны:"
echo "    • Вход по QR-коду / 8-значному коду или добавление URL-подписки"
echo "    • Выбор протокола: MeduzaVPN ULTRA, AmneziaWG 3.1 (meduza),"
echo "      Hysteria 2, VLESS 2.0 Reality, WireGuard, OpenVPN"
echo "    • Раздельная маршрутизация по доменам, странам (.RU напрямую,"
echo "      YouTube/Instagram/Telegram/Discord через VPN) и подсетям"
echo "    • Маршрутизация отдельных устройств домашней сети (LAN)"
echo ""
echo "  Управление из терминала SSH:"
echo "    meduzavpn login --qr                  # Вход по QR-коду"
echo "    meduzavpn connect --protocol ultra    # Подключить ULTRA"
echo "    meduzavpn connect --protocol meduza   # Подключить AmneziaWG 3.1"
echo "    meduzavpn status                      # Проверить статус"
echo "================================================================"
