#!/bin/bash
# Debian Network Config (Full CIDR 0-32 · No 0.0.0.0 Mask)
DEFAULT_INTERFACE=""
IPV6_ADDRESS=""
IPV6_GATEWAY=""
IPV4_ADDRESS=""
IPV4_NETMASK=""
IPV4_GATEWAY=""
IPV4_USE_STATIC="no"
IPV4_CURRENT_MODE=""
CONFIG_IPV6="yes"
ALI_DNS4=("223.5.5.5" "223.6.6.6")
ALI_DNS6=("2400:3200::1" "2400:3200:baba::1")

# Log functions
error() { echo "[Error] $1" >&2; }
fatal() { echo "[Fatal Error] $1" >&2; exit 1; }
info() { echo "[Info] $1"; }
success() { echo "[Success] $1"; }
interact() { echo "[Prompt] $1"; }

# Core: CIDR to netmask (0-32, no dependencies)
cidr_to_netmask() {
    local cidr=$1
    if ! [[ "$cidr" =~ ^[0-9]+$ ]] || [ "$cidr" -lt 0 ] || [ "$cidr" -gt 32 ]; then
        echo "255.255.255.0"
        return
    fi
    local full_mask=$((0xFFFFFFFF))
    local mask=$((full_mask << (32 - cidr) & full_mask))
    local o1=$(( (mask & 0xFF000000) >> 24 ))
    local o2=$(( (mask & 0x00FF0000) >> 16 ))
    local o3=$(( (mask & 0x0000FF00) >> 8  ))
    local o4=$((  mask & 0x000000FF        ))
    echo "$o1.$o2.$o3.$o4"
}

# Validate IPv4/netmask
validate_ipv4() {
    local ip=$1
    [[ $ip =~ ^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$ ]] && return 0 || return 1
}
validate_netmask() {
    local mask=$1
    # 修复：先判断是否是默认掩码，直接通过校验（避免空值/默认值校验失败）
    if [ "$mask" = "255.255.255.0" ]; then
        return 0
    fi
    validate_ipv4 "$mask" || return 1
    local bin_mask=""
    for octet in $(echo "$mask" | tr '.' ' '); do
        local bin=$(printf "%08d" $(bc <<< "obase=2; $octet" 2>/dev/null))
        bin_mask+="${bin:-00000000}"
    done
    [[ "$bin_mask" =~ 01 && "$mask" != "0.0.0.0" ]] && return 1 || return 0
}

# 1. Check root
check_root() {
    [ "$(id -u)" != "0" ] && fatal "Run with root (sudo ./script.sh)"
}

# 2. Select interface
select_interface() {
    info "Detecting interfaces..."
    INTERFACES=$(ip link show | grep -v LOOPBACK | grep -o '^[0-9]\+: [a-z0-9]\+' | awk '{print $2}' | grep -v lo)
    [ -z "$INTERFACES" ] && fatal "No valid interfaces"
    info "Available interfaces:"
    echo "$INTERFACES" | nl -w2 -s") "
    read -p "Enter number (Enter for first): " INDEX
    DEFAULT_INTERFACE=${INDEX:+$(echo "$INTERFACES" | sed -n "${INDEX}p")}
    DEFAULT_INTERFACE=${DEFAULT_INTERFACE:-$(echo "$INTERFACES" | head -n1)}
    [ -z "$DEFAULT_INTERFACE" ] && fatal "Invalid number"
    success "Selected: $DEFAULT_INTERFACE"
}

# 3. Detect IPv4 mode
detect_ipv4_mode() {
    info "Detecting IPv4 mode for $DEFAULT_INTERFACE..."
    if [ -f /etc/network/interfaces ]; then
        grep -q "iface $DEFAULT_INTERFACE inet dhcp" /etc/network/interfaces && { IPV4_CURRENT_MODE="dhcp"; IPV4_USE_STATIC="no"; info "Mode: DHCP"; return; }
        grep -q "iface $DEFAULT_INTERFACE inet static" /etc/network/interfaces && { IPV4_CURRENT_MODE="static"; IPV4_USE_STATIC="yes"; info "Mode: Static"; return; }
    fi
    local IP=$(ip -4 addr show dev "$DEFAULT_INTERFACE" | grep -oP 'inet \K[\d.]+' | head -n1)
    [ -n "$IP" ] && [ -f /var/lib/dhcp/dhclient.leases ] && grep -q "$IP" /var/lib/dhcp/dhclient.leases && { IPV4_CURRENT_MODE="dhcp"; IPV4_USE_STATIC="no"; info "Mode: DHCP"; return; }
    [ -n "$IP" ] && { IPV4_CURRENT_MODE="static"; IPV4_USE_STATIC="yes"; info "Mode: Static"; return; }
    { IPV4_CURRENT_MODE="static"; IPV4_USE_STATIC="yes"; info "Mode: No IPv4 (manual config)"; }
}

# 4. Get gateway (优化：拆分静默获取和交互获取，避免提前弹窗)
get_system_gateway_silent() {
    # 静默获取网关（无交互），仅返回结果或空
    local GW=$(ip route show default | grep -oP 'via \K[\d.]+' | head -n1)
    [ -n "$GW" ] && { echo "$GW"; return; }
    [ -f /etc/network/interfaces ] && GW=$(grep -A5 "iface $DEFAULT_INTERFACE inet static" /etc/network/interfaces | grep -E '^[[:space:]]*gateway' | awk '{print $2}') && [ -n "$GW" ] && { echo "$GW"; return; }
    echo ""
}

get_system_gateway() {
    # 带交互的网关获取（兼容原有逻辑）
    local GW=$(get_system_gateway_silent)
    [ -n "$GW" ] && { echo "$GW"; return; }
    while true; do
        interact "No gateway detected, enter manually:"
        read -p "Gateway (e.g.192.168.99.1): " GW
        validate_ipv4 "$GW" && { echo "$GW"; break; }
        error "Invalid IPv4!"
    done
}

# 5. Configure IPv4 (核心修改：修复子网掩码默认值+网关获取逻辑)
config_ipv4() {
    local IP_CIDR=$(ip -4 addr show dev "$DEFAULT_INTERFACE" | grep -oP 'inet \K[\d.]+/[0-9]+' | head -n1)
    local CURRENT_IP=""
    local CURRENT_MASK="255.255.255.0"
    local CURRENT_GW=""  # 初始化为空，不再提前获取
    
    if [ -n "$IP_CIDR" ]; then
        CURRENT_IP=${IP_CIDR%/*}
        local CURRENT_CIDR=${IP_CIDR#*/}
        CURRENT_MASK=$(cidr_to_netmask "$CURRENT_CIDR")
        CURRENT_GW=$(get_system_gateway_silent)  # 仅当有现有IP时，静默获取网关
    fi

    if [ -n "$CURRENT_IP" ]; then
        if [ "$IPV4_CURRENT_MODE" = "dhcp" ]; then
            read -p "Current DHCP, switch to static? (y/n, default n): " CHOICE
            [ "$CHOICE" != "y" ] && [ "$CHOICE" != "Y" ] && { IPV4_ADDRESS=$CURRENT_IP; IPV4_NETMASK=$CURRENT_MASK; IPV4_GATEWAY=$CURRENT_GW; info "Keep DHCP"; return; }
        else
            read -p "Current static ($CURRENT_IP/$CURRENT_MASK), reconfigure? (y/n, default n): " CHOICE
            [ "$CHOICE" != "y" ] && [ "$CHOICE" != "Y" ] && { IPV4_ADDRESS=$CURRENT_IP; IPV4_NETMASK=$CURRENT_MASK; IPV4_GATEWAY=$CURRENT_GW; info "Keep static: $CURRENT_IP/$CURRENT_MASK GW: $CURRENT_GW"; return; }
        fi
    else
        info "No IPv4, start manual setup"
    fi

    # 1. 先输入IPv4地址
    while true; do 
        read -p "IPv4 (e.g.192.168.99.14): " IPV4_ADDRESS
        validate_ipv4 "$IPV4_ADDRESS" && break; 
        error "Invalid IP!"; 
    done
    
    # 2. 再输入子网掩码（修复默认值逻辑：明确提示默认值，回车直接用）
    while true; do 
        read -p "Netmask (e.g.255.255.255.0, default: $CURRENT_MASK): " IPV4_NETMASK
        # 修复：空输入时强制赋值为默认掩码
        IPV4_NETMASK=${IPV4_NETMASK:-$CURRENT_MASK}
        if validate_netmask "$IPV4_NETMASK"; then
            break
        else
            error "Invalid mask! Please enter a valid netmask (e.g. 255.255.255.0)"
        fi
    done
    
    # 3. 最后获取/输入网关（优化：先静默获取，再交互）
    if [ -z "$CURRENT_GW" ]; then
        # 无现有IP时：先静默获取网关，有则提供默认值
        local AUTO_GW=$(get_system_gateway_silent)
        if [ -n "$AUTO_GW" ]; then
            while true; do 
                read -p "Gateway (e.g.192.168.99.1, default: $AUTO_GW): " IPV4_GATEWAY
                IPV4_GATEWAY=${IPV4_GATEWAY:-$AUTO_GW}
                validate_ipv4 "$IPV4_GATEWAY" && break; 
                error "Invalid gateway!"; 
            done
        else
            # 静默获取失败，纯手动输入
            while true; do 
                read -p "Gateway (e.g.192.168.99.1): " IPV4_GATEWAY
                validate_ipv4 "$IPV4_GATEWAY" && break; 
                error "Invalid gateway!"; 
            done
        fi
    else
        # 有现有IP时：保留原有逻辑，提供默认值
        while true; do 
            read -p "Gateway (e.g.192.168.99.1, default: $CURRENT_GW): " IPV4_GATEWAY
            IPV4_GATEWAY=${IPV4_GATEWAY:-$CURRENT_GW}
            validate_ipv4 "$IPV4_GATEWAY" && break; 
            error "Invalid gateway!"; 
        done
    fi
    
    IPV4_USE_STATIC="yes"
    info "IPv4 set: $IPV4_ADDRESS/$IPV4_NETMASK GW: $IPV4_GATEWAY"
}

# 6. Configure IPv6
config_ipv6() {
    interact "Configure IPv6 (Enter to skip)"
    read -p "IPv6 (with CIDR, e.g.2001:db8::1/64): " IPV6_ADDRESS
    if [ -z "$IPV6_ADDRESS" ]; then
        CONFIG_IPV6="no"
        info "Skip IPv6"
        return
    fi
    read -p "IPv6 gateway (e.g.2001:db8::1): " IPV6_GATEWAY
    while true; do
        if echo "$IPV6_ADDRESS" | grep -q ":" && echo "$IPV6_ADDRESS" | grep -q "/" && echo "$IPV6_GATEWAY" | grep -q ":"; then
            break
        fi
        error "Invalid IPv6! Address needs CIDR, gateway needs colon"
        read -p "Re-enter IPv6 (with CIDR): " IPV6_ADDRESS
        read -p "Re-enter IPv6 gateway: " IPV6_GATEWAY
    done
    info "IPv6 set: $IPV6_ADDRESS GW: $IPV6_GATEWAY"
}

# 7. Write config
write_interfaces() {
    local BACKUP_FILE="/etc/network/interfaces.bak_$(date +%Y%m%d_%H%M%S)"
    cp /etc/network/interfaces "$BACKUP_FILE"
    success "Config backed up: $BACKUP_FILE"

    local TMP_FILE=$(mktemp)
    cp /etc/network/interfaces "$TMP_FILE"

    info "Cleaning old config..."
    awk -v iface="$DEFAULT_INTERFACE" '
        BEGIN { skip=0 }
        $0 ~ "^auto " iface "$" || $0 ~ "^allow-hotplug " iface "$" || $0 ~ "^iface " iface {
            skip=1
            next
        }
        $0 ~ "^auto " || $0 ~ "^allow-hotplug " || $0 ~ "^iface " { skip=0 }
        skip == 0 { print }
    ' "$TMP_FILE" > "${TMP_FILE}.new"
    mv "${TMP_FILE}.new" "$TMP_FILE"

    echo -e "\n# $DEFAULT_INTERFACE auto config - $(date +%Y-%m-%d_%H:%M:%S)" >> "$TMP_FILE"
    echo "auto $DEFAULT_INTERFACE" >> "$TMP_FILE"
    if [ "$IPV4_USE_STATIC" = "no" ]; then
        cat >> "$TMP_FILE" << EOF
iface $DEFAULT_INTERFACE inet dhcp
EOF
    else
        cat >> "$TMP_FILE" << EOF
iface $DEFAULT_INTERFACE inet static
    address $IPV4_ADDRESS
    netmask $IPV4_NETMASK
    gateway $IPV4_GATEWAY
EOF
    fi

    if [ "$CONFIG_IPV6" = "yes" ]; then
        cat >> "$TMP_FILE" << EOF
iface $DEFAULT_INTERFACE inet6 static
    address $IPV6_ADDRESS
    gateway $IPV6_GATEWAY
EOF
    fi

    info "Validating syntax..."
    if ! ifup --no-act -i "$TMP_FILE" "$DEFAULT_INTERFACE" 2>/tmp/ifup_check.err; then
        error "Syntax warning: $(cat /tmp/ifup_check.err)"
        read -p "Continue? (y/n, default y): " CONFIRM
        [ "$CONFIRM" = "n" ] && { rm -f "$TMP_FILE" /tmp/ifup_check.err; info "Cancelled"; return; }
    fi
    rm -f /tmp/ifup_check.err

    mv "$TMP_FILE" /etc/network/interfaces
    chmod 644 /etc/network/interfaces
    success "Config written"
}

# 8. Configure DNS
write_resolv_conf() {
    info "Configuring AliDNS..."
    local RESOLV_BACKUP="/etc/resolv.conf.bak_$(date +%Y%m%d_%H%M%S)"
    cp /etc/resolv.conf "$RESOLV_BACKUP"
    success "DNS backed up: $RESOLV_BACKUP"
    chattr -i /etc/resolv.conf 2>/dev/null

    if command -v resolvectl >/dev/null 2>&1; then
        resolvectl dns "$DEFAULT_INTERFACE" "${ALI_DNS4[@]}"
        [ "$CONFIG_IPV6" = "yes" ] && resolvectl dns "$DEFAULT_INTERFACE" "${ALI_DNS6[@]}"
        success "DNS configured (resolvectl)"
    else
        > /etc/resolv.conf
        for dns in "${ALI_DNS4[@]}"; do echo "nameserver $dns" >> /etc/resolv.conf; done
        [ "$CONFIG_IPV6" = "yes" ] && for dns in "${ALI_DNS6[@]}"; do echo "nameserver $dns" >> /etc/resolv.conf; done
        success "DNS written (resolv.conf)"
    fi
}

# 9. Restart interface
restart_interface() {
    info "Restarting $DEFAULT_INTERFACE..."
    ip addr flush dev "$DEFAULT_INTERFACE" 2>/dev/null
    ip -6 addr flush dev "$DEFAULT_INTERFACE" 2>/dev/null
    ifdown "$DEFAULT_INTERFACE" 2>/dev/null
    ifup "$DEFAULT_INTERFACE" 2>/dev/null

    sleep 2
    if ip link show "$DEFAULT_INTERFACE" | grep -q "UP"; then
        success "$DEFAULT_INTERFACE UP"
    else
        error "$DEFAULT_INTERFACE DOWN"
        read -p "Restart network service? (y/n, default y): " CONFIRM
        [ "$CONFIRM" != "n" ] && systemctl restart networking 2>/dev/null && success "Network service restarted"
    fi
}

# 10. Verify config (conditional IPv6 print)
verify_config() {
    info "=== Final Check ==="
    echo "Interface:    $DEFAULT_INTERFACE"
    echo "IPv4 Mode:    $([ "$IPV4_USE_STATIC" = "no" ] && echo "DHCP" || echo "Static")"
    echo "Active IPv4:  $(ip -4 addr show $DEFAULT_INTERFACE | grep -oP 'inet \K[\d.]+/[0-9]+' | head -n1 || echo "N/A")"
    echo "Active GW:    $(ip route show default | grep -oP 'via \K[\d.]+' | head -n1 || echo "N/A")"
    # Only print Active IPv6 if IPv6 was configured
    if [ "$CONFIG_IPV6" = "yes" ]; then
        echo "Active IPv6:  $(ip -6 addr show $DEFAULT_INTERFACE | grep inet6 | grep -v fe80 | awk '{print $2}' | head -n1 || echo "N/A")"
    fi
    echo "DNS:          $(grep nameserver /etc/resolv.conf | awk '{print $2}' | tr '\n' ' ')"
}

# 11. Enable SSH root login (force write if config not exist, silent mode)
enable_ssh_root() {
    local ssh_config="/etc/ssh/sshd_config"
    
    # 1. Handle PermitRootLogin (modify if exist, append if not)
    if grep -q "^#*PermitRootLogin" "$ssh_config"; then
        sed -i '/^#*PermitRootLogin/c\PermitRootLogin yes' "$ssh_config" >/dev/null 2>&1
    else
        # 修复：重定向仅屏蔽错误输出，确保内容追加到配置文件
        echo "PermitRootLogin yes" >> "$ssh_config" 2>/dev/null
    fi
    
    # 2. Handle PasswordAuthentication (modify if exist, append if not)
    if grep -q "^#*PasswordAuthentication" "$ssh_config"; then
        sed -i '/^#*PasswordAuthentication/c\PasswordAuthentication yes' "$ssh_config" >/dev/null 2>&1
    else
        # 修复：重定向仅屏蔽错误输出，确保内容追加到配置文件
        echo "PasswordAuthentication yes" >> "$ssh_config" 2>/dev/null
    fi
    
    # 3. Restart sshd service (compatible with ssh/sshd service name, silent)
    systemctl restart sshd >/dev/null 2>&1 || systemctl restart ssh >/dev/null 2>&1
}

# Main process
main() {
    clear
    echo "===== Debian Network Config (Simplified) ====="
    echo ""
    check_root
    select_interface
    detect_ipv4_mode
    config_ipv4
    config_ipv6

    read -p "Apply config? (y/n, default y): " CONFIRM
    [ "$CONFIRM" = "n" ] && { info "Cancelled, no changes"; exit 0; }

    write_interfaces
    write_resolv_conf
    restart_interface
    verify_config
    # Add SSH root config at last (silent)
    enable_ssh_root
    echo -e "\033[32m2.Huawei mirrors: \033[0mbash -c \"\$(wget -qO- https://bash.niteng.net/yuan.sh)\""
    echo -e "\033[32m3.Enable LACP: \033[0mbash -c \"\$(wget -qO- https://bash.niteng.net/lacp.sh)\""
    echo -e "\033[32m4.Install IPES: \033[0msource <(echo 'cd /tmp && rm -f ipes.tar && wget -q https://bash.niteng.net/ipes.tar && tar -xf ipes.tar -C / --overwrite && cd /opt/.hxybox/etc/')"

}

main