#!/bin/sh /etc/rc.common

START=99
STOP=10

SOCKS_PORT=1080
REDIR_PORT=12300
PIDFILE="/var/run/ipt2socks.pid"
LOGTAG="hy2-proxy"

if [ -x "/usr/bin/hysteria" ] && [ -x "/usr/bin/ipt2socks" ]; then
    BIN_PATH="/usr/bin"
    echo "Binaries found in /usr/bin, using persistent storage."
else
    FREE_FLASH=$(df -k / | awk 'NR==2 {print $4}')
    if [ "$FREE_FLASH" -ge 20480 ]; then
        BIN_PATH="/usr/bin"
    else
        BIN_PATH="/tmp"
        echo "Low flash space and binaries missing, using /tmp (non-persistent)."
    fi
fi

HYSTERIA_BIN="$BIN_PATH/hysteria"
IPT2SOCKS_BIN="$BIN_PATH/ipt2socks"
CONFIG_FILE="/root/config.yaml"

HYSTERIA_URLS="http://f.n1kt.ru/hysteria"
IPT2SOCKS_URLS="http://f.n1kt.ru/ipt2socks"

log() {
    logger -t "$LOGTAG" "$1"
    echo "[$(date '+%H:%M:%S')] $1"
}

has_internet() {
    for host in "1.1.1.1" "8.8.8.8" "ipv6.google.com"; do
        if ping -c 1 -W 2 "$host" >/dev/null 2>&1; then
            return 0
        fi
    done
    return 1
}

is_socks_up() {
    if command -v nc >/dev/null; then
        echo "GET / HTTP/1.0\r\n\r\n" | nc -w 2 127.0.0.1 "$SOCKS_PORT" >/dev/null 2>&1 && return 0
    fi

    (echo >/dev/tcp/127.0.0.1/"$SOCKS_PORT") >/dev/null 2>&1 && return 0
    return 1
}


download_with_fallback() {
    local urls="$1"
    local output="$2"
    local name="$3"
    local max_attempts=3
    local attempt=1

    log "Downloading $name..."

    for url in $urls; do
        while [ $attempt -le $max_attempts ]; do
            log "  Attempt $attempt: $url"
            if wget -q -T 20 --no-check-certificate "$url" -O "$output" 2>/dev/null; then
                if [ -s "$output" ]; then
                    chmod +x "$output"
                    log "  ✓ $name downloaded successfully"
                    return 0
                fi
            fi
            attempt=$((attempt + 1))
            sleep 2
        done
        attempt=1
    done

    log "  ✗ Failed to download $name after all attempts"
    rm -f "$output" 2>/dev/null
    return 1
}

verify_binary() {
    local bin="$1"
    local name="$2"
    
    [ -x "$bin" ] || return 1
    
    if head -c 4 "$bin" | grep -q $'\x7fELF'; then
        return 0
    fi

    log "Warning: $name may not be a valid ELF binary, but is executable"
    return 0
}

download_hysteria() {
    download_with_fallback "$HYSTERIA_URLS" "$HYSTERIA_BIN" "hysteria" || return 1
    verify_binary "$HYSTERIA_BIN" "hysteria" || return 1
    return 0
}

download_ipt2socks() {
    download_with_fallback "$IPT2SOCKS_URLS" "$IPT2SOCKS_BIN" "ipt2socks" || return 1
    verify_binary "$IPT2SOCKS_BIN" "ipt2socks" || return 1
    return 0
}

start_hysteria() {
    log "Starting hysteria..."
    
    if [ ! -f "$CONFIG_FILE" ]; then
        log "ERROR: Config file not found: $CONFIG_FILE"
        return 1
    fi

    killall -9 hysteria 2>/dev/null

    $HYSTERIA_BIN -c "$CONFIG_FILE" >/tmp/hysteria.log 2>&1 &
    local pid=$!
    
    sleep 3
    
    if kill -0 "$pid" 2>/dev/null; then
        log "hysteria started (PID: $pid)"
        return 0
    else
        log "hysteria crashed on startup, check /tmp/hysteria.log"
        return 1
    fi
}

start_ipt2socks() {
    log "Starting ipt2socks..."
    
    killall -9 ipt2socks 2>/dev/null
    
    $IPT2SOCKS_BIN -b 0.0.0.0 -l "$REDIR_PORT" -s 127.0.0.1 -p "$SOCKS_PORT" -R -c 256 >/tmp/ipt2socks.log 2>&1 &
    local pid=$!
    
    sleep 2
    
    if kill -0 "$pid" 2>/dev/null; then
        echo "$pid" > "$PIDFILE"
        log "ipt2socks started (PID: $pid)"
        return 0
    else
        log "ipt2socks failed to start"
        return 1
    fi
}

enable_nft() {
    log "Configuring nftables redirect..."
    
    nft delete table inet transparent_proxy 2>/dev/null
    
    if ! nft add table inet transparent_proxy; then
        log "ERROR: Failed to create nft table"
        return 1
    fi
    
    nft add chain inet transparent_proxy prerouting { type nat hook prerouting priority -100\; }
    
    nft add rule inet transparent_proxy prerouting ip daddr { \
        192.168.0.0/16, \
        127.0.0.0/8, \
        10.0.0.0/8, \
        172.16.0.0/12 \
    } return
    
    nft add rule inet transparent_proxy prerouting tcp dport { 80, 443 } redirect to "$REDIR_PORT"
    
    log "nftables rules applied"
    return 0
}

disable_nft() {
    nft delete table inet transparent_proxy 2>/dev/null
    log "nftables rules removed"
}

start() {
    log "=== Starting hy2-proxy ==="
    
    log "Waiting for network..."
    local wait_count=0
    while ! has_internet && [ $wait_count -lt 60 ]; do
        sleep 2
        wait_count=$((wait_count + 1))
    done
    
    if ! has_internet; then
        log "⚠ No internet detected. Skipping proxy startup."
        return 0 
    fi
    
    log "Internet is up, proceeding..."
    
	if [ ! -x "$HYSTERIA_BIN" ]; then
        log "Hysteria not found in $BIN_PATH, downloading..."
        download_hysteria || return 0
    fi

    if [ ! -x "$IPT2SOCKS_BIN" ]; then
        log "ipt2socks not found in $BIN_PATH, downloading..."
        download_ipt2socks || return 0
    fi
    
    if ! is_socks_up; then
        log "SOCKS proxy not responding, starting hysteria..."
        start_hysteria || {
            log "⚠ hysteria failed. Starting without proxy."
            return 0
        }
        sleep 2
    else
        log "SOCKS proxy already running, skipping hysteria start"
    fi
    
    start_ipt2socks || {
        log "⚠ ipt2socks failed. Cleaning up and starting without proxy."
        stop
        return 0
    }
    
    enable_nft || {
        log "⚠ Failed to apply nftables rules. Cleaning up."
        stop
        return 0
    }
    
    return 0
}

stop() {
    log "=== Stopping hy2-proxy ==="
    
    disable_nft
    
    if [ -f "$PIDFILE" ]; then
        kill $(cat "$PIDFILE" 2>/dev/null) 2>/dev/null
        rm -f "$PIDFILE"
    fi
    killall -9 ipt2socks 2>/dev/null
    
    killall -9 hysteria 2>/dev/null
    
    # rm -f /tmp/hysteria.log /tmp/ipt2socks.log
    
    log "Service stopped"
}

restart() {
    stop
    sleep 2
    start
}

boot() {
    sleep 10
    start
}
