#!/usr/bin/env bash
set -Eeuo pipefail

export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$PATH"

# =============================
# SOCKS5 basic config
# =============================
socks_port="23456"
socks_user="root"
socks_pass="wawacloud"
main_gw="192.168.0.1"
output_file="/root/socks5"
xray_bin="/usr/local/bin/xray"
xray_config="/etc/xray/serve.toml"
xray_service="/etc/systemd/system/xray.service"
xray_download_url="http://wawaok.cn/static/xray"
sysctl_config="/etc/sysctl.d/99-Huawei12.conf"
iptables_rules="/root/iptables.Huawei12.rules"
routing_script="/usr/local/sbin/Huawei12-routing.sh"
routing_service="/etc/systemd/system/Huawei12-routing.service"
iptables_service="/etc/systemd/system/Huawei12-iptables.service"

# Interface list: eth0 ~ eth11
interfaces=(eth0 eth1 eth2 eth3 eth4 eth5 eth6 eth7 eth8 eth9 eth10 eth11)

log() {
    echo "[Huawei12] $*"
}

die() {
    echo "[Huawei12][ERROR] $*" >&2
    exit 1
}

require_root() {
    [[ "${EUID}" -eq 0 ]] || die "Please run this script as root"
}

require_commands() {
    local missing=()
    local packages=()
    local unique_packages=()
    local cmd
    local pkg

    for cmd in ip iptables iptables-save iptables-restore wget curl systemctl sysctl awk chmod mkdir tee; do
        command -v "$cmd" >/dev/null 2>&1 || missing+=("$cmd")
    done

    if ((${#missing[@]} == 0)); then
        return
    fi

    log "Missing required commands: ${missing[*]}"

    if ! command -v apt-get >/dev/null 2>&1; then
        die "apt-get not found; please install missing commands manually"
    fi

    for cmd in "${missing[@]}"; do
        case "$cmd" in
            ip) packages+=(iproute2) ;;
            iptables | iptables-save | iptables-restore) packages+=(iptables) ;;
            wget) packages+=(wget) ;;
            curl) packages+=(curl) ;;
            sysctl) packages+=(procps) ;;
            awk) packages+=(mawk) ;;
            systemctl) packages+=(systemd) ;;
            chmod | mkdir | tee) packages+=(coreutils) ;;
        esac
    done

    for pkg in "${packages[@]}"; do
        [[ " ${unique_packages[*]} " == *" $pkg "* ]] || unique_packages+=("$pkg")
    done

    log "Installing Debian packages: ${unique_packages[*]}"
    export DEBIAN_FRONTEND=noninteractive
    apt-get update --allow-releaseinfo-change
    apt-get install -y "${unique_packages[@]}"

    for cmd in "${missing[@]}"; do
        command -v "$cmd" >/dev/null 2>&1 || die "Command still missing after install: $cmd"
    done
}

add_iptables_rule() {
    if ! iptables -C "$@" >/dev/null 2>&1; then
        iptables -A "$@"
    fi
}

cleanup_policy_rules() {
    local ip_addr="$1"
    local table_id="$2"

    while ip rule del from "$ip_addr" table "$table_id" >/dev/null 2>&1; do
        :
    done
}

install_persistence_services() {
    log "Installing boot persistence services"

    cat <<EOF > "$iptables_service"
[Unit]
Description=Restore Huawei12 iptables rules
DefaultDependencies=no
Before=network-pre.target
Wants=network-pre.target

[Service]
Type=oneshot
ExecStart=/bin/sh -c 'test -s "$iptables_rules" && /usr/sbin/iptables-restore < "$iptables_rules" || true'
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
EOF

    cat <<'EOF' > "$routing_script"
#!/usr/bin/env bash
set -Eeuo pipefail

export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$PATH"

main_gw="192.168.0.1"

get_interface_ip() {
    local dev="$1"

    ip -o -4 addr show dev "$dev" 2>/dev/null |
        awk '{split($4, a, "/"); if (a[1] ~ /^192\.168\.0\.[0-9]+$/) {print a[1]; exit}}'
}

cleanup_policy_rules() {
    local ip_addr="$1"
    local table_id="$2"

    while ip rule del from "$ip_addr" table "$table_id" >/dev/null 2>&1; do
        :
    done
}

for i in {1..11}; do
    dev="eth$i"
    table_id=$((100 + i))
    ip_addr="$(get_interface_ip "$dev")"

    [[ -z "$ip_addr" ]] && continue

    cleanup_policy_rules "$ip_addr" "$table_id"
    ip route flush table "$table_id" || true
    ip rule add from "$ip_addr" table "$table_id"
    ip route add default via "$main_gw" dev "$dev" src "$ip_addr" table "$table_id"
done

ip route flush cache || true
EOF

    chmod +x "$routing_script"

    cat <<EOF > "$routing_service"
[Unit]
Description=Restore Huawei12 policy routing
After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
ExecStart=$routing_script
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
EOF

    systemctl daemon-reload
    systemctl enable Huawei12-iptables.service Huawei12-routing.service
}

enable_udp_forwarding() {
    log "Applying network stability tuning"

    cat <<EOF > "$sysctl_config"
net.ipv4.ip_forward=1
net.ipv4.tcp_keepalive_time=60
net.ipv4.tcp_keepalive_intvl=10
net.ipv4.tcp_keepalive_probes=6
net.ipv4.ip_local_port_range=10000 65000
net.ipv4.udp_rmem_min=8192
net.ipv4.udp_wmem_min=8192
net.core.rmem_max=67108864
net.core.wmem_max=67108864
net.core.netdev_max_backlog=250000
net.netfilter.nf_conntrack_udp_timeout=120
net.netfilter.nf_conntrack_udp_timeout_stream=300
EOF

    while IFS= read -r line; do
        [[ -z "$line" || "$line" == \#* ]] && continue
        sysctl -w "$line" >/dev/null 2>&1 || log "Skip unsupported sysctl: $line"
    done < "$sysctl_config"
}

get_interface_ip() {
    local dev="$1"

    ip -o -4 addr show dev "$dev" 2>/dev/null |
        awk '{split($4, a, "/"); if (a[1] ~ /^192\.168\.0\.[0-9]+$/) {print a[1]; exit}}'
}

require_root
require_commands
enable_udp_forwarding

log "Checking interface IP addresses"
declare -A ip_map
for dev in "${interfaces[@]}"; do
    ip_addr="$(get_interface_ip "$dev")"
    if [[ -z "$ip_addr" ]]; then
        log "Skip $dev: no 192.168.0.x IPv4 address found"
        continue
    fi

    ip_map["$dev"]="$ip_addr"
    log "$dev => $ip_addr"
done

if ((${#ip_map[@]} == 0)); then
    die "No usable 192.168.0.x interface address found"
fi

# =============================
# Allow SOCKS5 port
# =============================
log "Configuring iptables for port $socks_port"
for dev in "${!ip_map[@]}"; do
    add_iptables_rule INPUT -i "$dev" -p tcp --dport "$socks_port" -j ACCEPT
    add_iptables_rule INPUT -i "$dev" -p udp --dport "$socks_port" -j ACCEPT
    add_iptables_rule OUTPUT -o "$dev" -p tcp --sport "$socks_port" -j ACCEPT
    add_iptables_rule OUTPUT -o "$dev" -p udp --sport "$socks_port" -j ACCEPT
    add_iptables_rule INPUT -i "$dev" -p udp -j ACCEPT
    add_iptables_rule OUTPUT -o "$dev" -p udp -j ACCEPT
    add_iptables_rule FORWARD -i "$dev" -p udp -j ACCEPT
    add_iptables_rule FORWARD -o "$dev" -p udp -j ACCEPT
done

iptables-save > "$iptables_rules"

# =============================
# Policy routing: eth1 ~ eth11
# =============================
log "Configuring policy routing"
for i in {1..11}; do
    dev="eth$i"
    table_id=$((100 + i))
    ip_addr="${ip_map[$dev]:-}"

    [[ -z "$ip_addr" ]] && continue

    cleanup_policy_rules "$ip_addr" "$table_id"
    ip route flush table "$table_id" || true

    log "$dev => $ip_addr, table $table_id"
    ip rule add from "$ip_addr" table "$table_id"
    ip route add default via "$main_gw" dev "$dev" src "$ip_addr" table "$table_id"
done

ip route flush cache || true

install_persistence_services

# =============================
# Install Xray binary
# =============================
log "Downloading Xray to $xray_bin"
wget -O "$xray_bin" "$xray_download_url"
chmod +x "$xray_bin"

log "Writing systemd service"
cat <<EOF > "$xray_service"
[Unit]
Description=The Xray Proxy Server
After=network-online.target Huawei12-iptables.service Huawei12-routing.service
Wants=network-online.target Huawei12-iptables.service Huawei12-routing.service
StartLimitIntervalSec=0

[Service]
ExecStart=$xray_bin -c $xray_config
ExecStop=/bin/kill -s QUIT \$MAINPID
Restart=always
RestartSec=3s
LimitNOFILE=1048576
LimitNPROC=1048576

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable xray

# =============================
# Write Xray config
# =============================
log "Generating Xray config: $xray_config"
mkdir -p /etc/xray
: > "$xray_config"

index=1
for dev in "${interfaces[@]}"; do
    ip_addr="${ip_map[$dev]:-}"
    [[ -z "$ip_addr" ]] && continue
    tag="tag$index"

    cat <<EOF >> "$xray_config"
[[inbounds]]
listen = "$ip_addr"
port = $socks_port
protocol = "socks"
tag = "$tag"

[inbounds.settings]
auth = "password"
udp = true
ip = "$ip_addr"

[[inbounds.settings.accounts]]
user = "$socks_user"
pass = "$socks_pass"

[[routing.rules]]
type = "field"
inboundTag = "$tag"
outboundTag = "$tag"

[[outbounds]]
sendThrough = "$ip_addr"
protocol = "freedom"
tag = "$tag"

EOF

    ((index++))
done

log "Restarting Xray service"
systemctl restart xray

# =============================
# Output public exit IP information
# =============================
log "Checking public exit IPs and writing $output_file"
: > "$output_file"

for dev in "${interfaces[@]}"; do
    ip_addr="${ip_map[$dev]:-}"
    [[ -z "$ip_addr" ]] && continue

    result="$(curl -fsS --connect-timeout 8 --max-time 15 --interface "$ip_addr" http://whatismyip.akamai.com || true)"
    if [[ -z "$result" ]]; then
        result="check_failed($ip_addr)"
    fi

    echo "$result/$socks_port/$socks_user/$socks_pass" | tee -a "$output_file"
done

echo "============================================"
echo "12-interface SOCKS5 deployment completed; eth0 keeps the SSH exit route"
echo "Proxy information saved to $output_file"
