#!/bin/bash
# from
# https://github.com/oneclickvirt/pve
# 2025.08.14

########## 预设部分输出和部分中间变量

_red() { echo -e "\033[31m\033[01m$@\033[0m"; }
_green() { echo -e "\033[32m\033[01m$@\033[0m"; }
_yellow() { echo -e "\033[33m\033[01m$@\033[0m"; }
_blue() { echo -e "\033[36m\033[01m$@\033[0m"; }
reading() { read -rp "$(_green "$1")" "$2"; }
export DEBIAN_FRONTEND=noninteractive
utf8_locale=$(locale -a 2>/dev/null | grep -i -m 1 -E "UTF-8|utf8")
if [[ -z "$utf8_locale" ]]; then
    echo "No UTF-8 locale found"
else
    export LC_ALL="$utf8_locale"
    export LANG="$utf8_locale"
    export LANGUAGE="$utf8_locale"
    echo "Locale set to $utf8_locale"
fi
rm -rf /usr/local/bin/build_backend_pve.txt

check_cdn() {
    local o_url=$1
    local shuffled_cdn_urls=($(shuf -e "${cdn_urls[@]}")) # 打乱数组顺序
    for cdn_url in "${shuffled_cdn_urls[@]}"; do
        if curl -4 -sL -k "$cdn_url$o_url" --max-time 6 | grep -q "success" >/dev/null 2>&1; then
            export cdn_success_url="$cdn_url"
            return
        fi
        sleep 0.5
    done
    export cdn_success_url=""
}

check_cdn_file() {
    check_cdn "https://raw.githubusercontent.com/spiritLHLS/ecs/main/back/test"
    if [ -n "$cdn_success_url" ]; then
        _yellow "CDN available, using CDN"
    else
        _yellow "No CDN available, no use CDN"
    fi
}

get_system_arch() {
    local sysarch="$(uname -m)"
    if [ "${sysarch}" = "unknown" ] || [ "${sysarch}" = "" ]; then
        local sysarch="$(arch)"
    fi
    # 根据架构信息设置系统位数并下载文件,其余 * 包括了 x86_64
    case "${sysarch}" in
    "i386" | "i686" | "x86_64")
        system_arch="x86"
        ;;
    "armv7l" | "armv8" | "armv8l" | "aarch64")
        system_arch="arm"
        ;;
    *)
        system_arch=""
        ;;
    esac
}

check_interface() {
    if [ -z "$interface_2" ]; then
        interface=${interface_1}
        return
    elif [ -n "$interface_1" ] && [ -n "$interface_2" ]; then
        if ! grep -q "$interface_1" "/etc/network/interfaces" && ! grep -q "$interface_2" "/etc/network/interfaces" && [ -f "/etc/network/interfaces.d/50-cloud-init" ]; then
            if grep -q "$interface_1" "/etc/network/interfaces.d/50-cloud-init" || grep -q "$interface_2" "/etc/network/interfaces.d/50-cloud-init"; then
                if ! grep -q "$interface_1" "/etc/network/interfaces.d/50-cloud-init" && grep -q "$interface_2" "/etc/network/interfaces.d/50-cloud-init"; then
                    interface=${interface_2}
                    return
                elif ! grep -q "$interface_2" "/etc/network/interfaces.d/50-cloud-init" && grep -q "$interface_1" "/etc/network/interfaces.d/50-cloud-init"; then
                    interface=${interface_1}
                    return
                fi
            fi
        fi
        if grep -q "$interface_1" "/etc/network/interfaces"; then
            interface=${interface_1}
            return
        elif grep -q "$interface_2" "/etc/network/interfaces"; then
            interface=${interface_2}
            return
        else
            interfaces_list=$(ip addr show | awk '/^[0-9]+: [^lo]/ {print $2}' | cut -d ':' -f 1)
            interface=""
            for iface in $interfaces_list; do
                if [[ "$iface" = "$interface_1" || "$iface" = "$interface_2" ]]; then
                    interface="$iface"
                fi
            done
            if [ -z "$interface" ]; then
                interface="eth0"
            fi
            return
        fi
    else
        interface="eth0"
        return
    fi
    _red "Physical interface not found, exit execution"
    _red "找不到物理接口，退出执行"
    exit 1
}

update_sysctl() {
    sysctl_config="$1"  # 格式: key=value
    key="${sysctl_config%%=*}"
    value="${sysctl_config#*=}"
    # 目标配置文件（systemd 方式）
    custom_conf="/etc/sysctl.d/99-custom.conf"
    mkdir -p /etc/sysctl.d
    # 检查 /etc/sysctl.conf 是否存在并且在系统加载路径中
    use_etc_sysctl_conf=false
    if [ -f /etc/sysctl.conf ]; then
        if grep -q "/etc/sysctl.conf" /etc/sysctl.d/README* 2>/dev/null || \
           grep -q "/etc/sysctl.conf" /lib/systemd/system/sysctl.service 2>/dev/null; then
            use_etc_sysctl_conf=true
        fi
    fi
    # 更新 /etc/sysctl.d/99-custom.conf
    if grep -q "^$sysctl_config" "$custom_conf" 2>/dev/null; then
        : # 已经有正确配置，跳过
    elif grep -q "^#$sysctl_config" "$custom_conf" 2>/dev/null; then
        sed -i "s/^#$sysctl_config/$sysctl_config/" "$custom_conf"
    elif grep -q "^$key" "$custom_conf" 2>/dev/null; then
        sed -i "s|^$key.*|$sysctl_config|" "$custom_conf"
    else
        echo "$sysctl_config" >> "$custom_conf"
    fi
    # 如果系统还在用 /etc/sysctl.conf，也同步更新
    if [ "$use_etc_sysctl_conf" = true ]; then
        if grep -q "^$sysctl_config" /etc/sysctl.conf; then
            : # 已经有正确配置
        elif grep -q "^#$sysctl_config" /etc/sysctl.conf; then
            sed -i "s/^#$sysctl_config/$sysctl_config/" /etc/sysctl.conf
        elif grep -q "^$key" /etc/sysctl.conf; then
            sed -i "s|^$key.*|$sysctl_config|" /etc/sysctl.conf
        else
            echo "$sysctl_config" >> /etc/sysctl.conf
        fi
    fi
    sysctl -w "$key=$value" >/dev/null 2>&1
}

remove_duplicate_lines() {
    chattr -i "$1"
    # 预处理：去除行尾空格和制表符
    sed -i 's/[ \t]*$//' "$1"
    # 去除重复行并跳过空行和注释行
    if [ -f "$1" ]; then
        awk '{ line = $0; gsub(/^[ \t]+/, "", line); gsub(/[ \t]+/, " ", line); if (!NF || !seen[line]++) print $0 }' "$1" >"$1.tmp" && mv -f "$1.tmp" "$1"
    fi
    chattr +i "$1"
}

is_private_ipv6() {
    local address=$1
    local temp="0"
    # 输入为空
    if [[ ! -n $address ]]; then
        temp="1"
    fi
    # 输入不含:符号
    if [[ -n $address && $address != *":"* ]]; then
        temp="2"
    fi
    # 检查IPv6地址是否以fe80开头（链接本地地址）
    if [[ $address == fe80:* ]]; then
        temp="3"
    fi
    # 检查IPv6地址是否以fc00或fd00开头（唯一本地地址）
    if [[ $address == fc00:* || $address == fd00:* ]]; then
        temp="4"
    fi
    # 检查IPv6地址是否以2001:db8开头（文档前缀）
    if [[ $address == 2001:db8* ]]; then
        temp="5"
    fi
    # 检查IPv6地址是否以::1开头（环回地址）
    if [[ $address == ::1 ]]; then
        temp="6"
    fi
    # 检查IPv6地址是否以::ffff:开头（IPv4映射地址）
    if [[ $address == ::ffff:* ]]; then
        temp="7"
    fi
    # 检查IPv6地址是否以2002:开头（6to4隧道地址）
    if [[ $address == 2002:* ]]; then
        temp="8"
    fi
    # 检查IPv6地址是否以2001:开头（Teredo隧道地址）
    if [[ $address == 2001:* ]]; then
        temp="9"
    fi
    if [ "$temp" -gt 0 ]; then
        # 非公网情况
        return 0
    else
        # 其他情况为公网地址
        return 1
    fi
}

check_ipv6() {
    IPV6=$(ip -6 addr show | grep global | awk '{print length, $2}' | sort -nr | head -n 1 | awk '{print $2}' | cut -d '/' -f1)
    if [ ! -f /usr/local/bin/pve_last_ipv6 ] || [ ! -s /usr/local/bin/pve_last_ipv6 ] || [ "$(sed -e '/^[[:space:]]*$/d' /usr/local/bin/pve_last_ipv6)" = "" ]; then
        ipv6_list=$(ip -6 addr show | grep global | awk '{print length, $2}' | sort -nr | awk '{print $2}')
        line_count=$(echo "$ipv6_list" | wc -l)
        if [ "$line_count" -ge 2 ]; then
            # 获取最后一行的内容
            last_ipv6=$(echo "$ipv6_list" | tail -n 1)
            # 切分最后一个:之前的内容
            last_ipv6_prefix="${last_ipv6%:*}:"
            # 与${ipv6_gateway}比较是否相同
            if [ "${last_ipv6_prefix}" = "${ipv6_gateway%:*}:" ]; then
                echo $last_ipv6 >/usr/local/bin/pve_last_ipv6
            fi
            _green "The local machine is bound to more than one IPV6 address"
            _green "本机绑定了不止一个IPV6地址"
        fi
    fi

    if is_private_ipv6 "$IPV6"; then # 由于是内网IPV6地址，需要通过API获取外网地址
        IPV6=""
        API_NET=("ipv6.ip.sb" "https://ipget.net" "ipv6.ping0.cc" "https://api.my-ip.io/ip" "https://ipv6.icanhazip.com")
        for p in "${API_NET[@]}"; do
            response=$(curl -sLk6m8 "$p" | tr -d '[:space:]')
            if [ $? -eq 0 ] && ! (echo "$response" | grep -q "error"); then
                IPV6="$response"
                break
            fi
            sleep 1
        done
    fi
    echo $IPV6 >/usr/local/bin/pve_check_ipv6
}

########## 查询信息

# 安装必要工具
install_required_tools() {
    local tools=("lshw" "ipcalc" "sipcalc" "ovs-vsctl:openvswitch-switch" "crontab:cron")
    for tool in "${tools[@]}"; do
        local cmd="${tool%%:*}"
        local pkg="${tool#*:}"
        if [[ "$pkg" == "$cmd" ]]; then pkg="$cmd"; fi

        if ! command -v "$cmd" >/dev/null 2>&1; then
            apt-get install -y "$pkg"
        fi
    done
    apt-get install -y net-tools
}

# 请求IPV6网络以加载配置
request_ipv6() {
    curl -m 5 ipv6.ip.sb || curl -m 5 ipv6.ip.sb
}

# 检测物理接口和MAC地址
detect_network_interfaces() {
    interface_1=$(lshw -C network | awk '/logical name:/{print $3}' | sed -n '1p')
    interface_2=$(lshw -C network | awk '/logical name:/{print $3}' | sed -n '2p')
    check_interface

    if [ ! -f /usr/local/bin/pve_mac_address ] || [ ! -s /usr/local/bin/pve_mac_address ] || [ "$(sed -e '/^[[:space:]]*$/d' /usr/local/bin/pve_mac_address)" = "" ]; then
        mac_address=$(ip -o link show dev ${interface} | awk '{print $17}')
        echo "$mac_address" >/usr/local/bin/pve_mac_address
    fi
    mac_address=$(cat /usr/local/bin/pve_mac_address)

    setup_persistent_net_link
}

# 设置持久化网络接口名称
setup_persistent_net_link() {
    if [ ! -f /etc/systemd/network/10-persistent-net.link ]; then
        echo '[Match]' >/etc/systemd/network/10-persistent-net.link
        echo "MACAddress=${mac_address}" >>/etc/systemd/network/10-persistent-net.link
        echo "" >>/etc/systemd/network/10-persistent-net.link
        echo '[Link]' >>/etc/systemd/network/10-persistent-net.link
        echo "Name=${interface}" >>/etc/systemd/network/10-persistent-net.link
        /etc/init.d/udev force-reload
    fi
}

# 检测HE隧道配置
detect_he_tunnel() {
    status_he=false
    if grep -q "he-ipv6" /etc/network/interfaces; then
        wget ${cdn_success_url}https://raw.githubusercontent.com/oneclickvirt/6in4/main/covert.sh -O /root/covert.sh
        chmod 777 covert.sh
        ./covert.sh
        sleep 1
        status_he=true
        chattr -i /etc/network/interfaces
        temp_config=$(awk '/auto he-ipv6/{flag=1; print $0; next} flag && flag++<10' /etc/network/interfaces)
        sed -i '/^auto he-ipv6/,/^$/d' /etc/network/interfaces
        chattr +i /etc/network/interfaces
        ipv6_address=$(echo "$temp_config" | awk '/address/ {print $2}')
        ipv6_gateway=$(echo "$temp_config" | awk '/gateway/ {print $2}')
        ipv6_prefixlen=$(ifconfig he-ipv6 | grep -oP 'prefixlen \K\d+' | head -n 1)
        target_mask=${ipv6_prefixlen}
        ((target_mask += 8 - ($target_mask % 8)))
        echo "$target_mask" >/usr/local/bin/pve_ipv6_prefixlen
        ipv6_subnet_2=$(sipcalc --v6split=${target_mask} ${ipv6_gateway}/${ipv6_prefixlen} | awk '/Network/{n++} n==2' | awk '{print $3}' | grep -v '^$')
        ipv6_subnet_2_without_last_segment="${ipv6_subnet_2%:*}:"
        new_subnet="${ipv6_subnet_2_without_last_segment}1/${target_mask}"
        echo ${ipv6_subnet_2_without_last_segment}1 >/usr/local/bin/pve_check_ipv6
        echo $ipv6_gateway >/usr/local/bin/pve_ipv6_gateway
    else
        detect_existing_ipv6_config
    fi

    check_fe80_gateway
}

# 检测已有的IPV6配置
detect_existing_ipv6_config() {
    if [ -f /usr/local/bin/pve_ipv6_prefixlen ]; then
        ipv6_prefixlen=$(cat /usr/local/bin/pve_ipv6_prefixlen)
    fi
    if [ -f /usr/local/bin/pve_ipv6_gateway ]; then
        ipv6_gateway=$(cat /usr/local/bin/pve_ipv6_gateway)
    fi
    if [ -f /usr/local/bin/pve_check_ipv6 ]; then
        ipv6_address=$(cat /usr/local/bin/pve_check_ipv6)
        ipv6_address_without_last_segment="${ipv6_address%:*}:"
        reconfigure_ipv6_address
    fi
}

# 重新配置IPV6地址
reconfigure_ipv6_address() {
    if [[ $ipv6_address != *:: && $ipv6_address_without_last_segment != *:: ]]; then
        ipv6_address=$(sipcalc -i ${ipv6_address}/${ipv6_prefixlen} | grep "Subnet prefix (masked)" | cut -d ' ' -f 4 | cut -d '/' -f 1 | sed 's/:0:0:0:0:/::/' | sed 's/:0:0:0:/::/')
        ipv6_address="${ipv6_address%:*}:1"
        if [ "$ipv6_address" == "$ipv6_gateway" ]; then
            ipv6_address="${ipv6_address%:*}:2"
        fi
        ipv6_address_without_last_segment="${ipv6_address%:*}:"
        if ping -c 1 -6 -W 3 $ipv6_address >/dev/null 2>&1; then
            check_ipv6
            ipv6_address=$(cat /usr/local/bin/pve_check_ipv6)
            echo "${ipv6_address}" >/usr/local/bin/pve_check_ipv6
            ipv6_address_without_last_segment="${ipv6_address%:*}:"
        fi
    elif [[ $ipv6_address == *:: ]]; then
        ipv6_address="${ipv6_address}1"
        if [ "$ipv6_address" == "$ipv6_gateway" ]; then
            ipv6_address="${ipv6_address%:*}:2"
        fi
        ipv6_address_without_last_segment="${ipv6_address%:*}:"
        echo "${ipv6_address}" >/usr/local/bin/pve_check_ipv6
    fi
}

# 检查fe80类型网关
check_fe80_gateway() {
    if [[ $ipv6_gateway == fe80* ]]; then
        ipv6_gateway_fe80="Y"
    else
        ipv6_gateway_fe80="N"
    fi
    fe80_address=$(cat /usr/local/bin/pve_fe80_address)
}

# 配置文件重试下载，避免网络原因导致配置失败
download_with_retry() {
    local url="$1"
    local output="$2"
    local max_attempts=5
    local attempt=1
    local delay=1
    while [ $attempt -le $max_attempts ]; do
        wget -q "$url" -O "$output" && return 0
        echo "Download failed: $url, try $attempt, wait $delay seconds and retry..."
        echo "下载失败：$url，尝试第 $attempt 次，等待 $delay 秒后重试..."
        sleep $delay
        attempt=$((attempt + 1))
        delay=$((delay * 2))
        [ $delay -gt 30 ] && delay=30
    done
    red "Download failed: $url, maximum number of attempts exceeded ($max_attempts)"
    red "下载失败：$url，超过最大尝试次数 ($max_attempts)"
    return 1
}

# 配置ndpresponder守护进程
install_ndpresponder() {
    appended_file="/usr/local/bin/pve_appended_content.txt"
    if [ -n "$ipv6_address" ] && [ -n "$ipv6_prefixlen" ] && [ -n "$ipv6_gateway" ] && [ ! -s "$appended_file" ]; then
        if [ -f /usr/local/bin/pve_maximum_subset ] && [ "$(cat /usr/local/bin/pve_maximum_subset)" = false ]; then
            _blue "No install ndpresponder"
        elif [ "$system_arch" = "x86" ] || [ "$system_arch" = "x86_64" ]; then
            download_with_retry "${cdn_success_url}https://github.com/oneclickvirt/pve/releases/download/ndpresponder_x86/ndpresponder" "/usr/local/bin/ndpresponder" || return 1
            download_with_retry "${cdn_success_url}https://raw.githubusercontent.com/oneclickvirt/pve/main/extra_scripts/ndpresponder.service" "/etc/systemd/system/ndpresponder.service" || return 1
            chmod 755 /usr/local/bin/ndpresponder
            chmod 644 /etc/systemd/system/ndpresponder.service
        elif [ "$system_arch" = "arm" ]; then
            download_with_retry "${cdn_success_url}https://github.com/oneclickvirt/pve/releases/download/ndpresponder_aarch64/ndpresponder" "/usr/local/bin/ndpresponder" || return 1
            download_with_retry "${cdn_success_url}https://raw.githubusercontent.com/oneclickvirt/pve/main/extra_scripts/ndpresponder.service" "/etc/systemd/system/ndpresponder.service" || return 1
            chmod 755 /usr/local/bin/ndpresponder
            chmod 644 /etc/systemd/system/ndpresponder.service
        fi
    fi
}

# 检测IPV4相关信息
detect_ipv4_info() {
    if [ -f /usr/local/bin/pve_ipv4_address ]; then
        ipv4_address=$(cat /usr/local/bin/pve_ipv4_address)
    else
        ipv4_address=$(ip addr show | awk '/inet .*global/ && !/inet6/ {print $2}' | sed -n '1p')
        echo "$ipv4_address" >/usr/local/bin/pve_ipv4_address
    fi

    if [ -f /usr/local/bin/pve_ipv4_gateway ]; then
        ipv4_gateway=$(cat /usr/local/bin/pve_ipv4_gateway)
    else
        ipv4_gateway=$(ip route | awk '/default/ {print $3}' | sed -n '1p')
        echo "$ipv4_gateway" >/usr/local/bin/pve_ipv4_gateway
    fi

    if [ -f /usr/local/bin/pve_ipv4_subnet ]; then
        ipv4_subnet=$(cat /usr/local/bin/pve_ipv4_subnet)
    else
        ipv4_subnet=$(ipcalc -n "$ipv4_address" | grep -oP 'Netmask:\s+\K.*' | awk '{print $1}')
        echo "$ipv4_subnet" >/usr/local/bin/pve_ipv4_subnet
    fi
}

# 备份和修复网络配置文件
prepare_network_interfaces() {
    if [ ! -f /etc/network/interfaces.bak ]; then
        cp /etc/network/interfaces /etc/network/interfaces.bak
    fi
    # 修正部分网络设置重复的错误
    if [[ -f "/etc/network/interfaces.d/50-cloud-init" && -f "/etc/network/interfaces" ]]; then
        if grep -q "auto lo" "/etc/network/interfaces.d/50-cloud-init" && grep -q "iface lo inet loopback" "/etc/network/interfaces.d/50-cloud-init" && grep -q "auto lo" "/etc/network/interfaces" && grep -q "iface lo inet loopback" "/etc/network/interfaces"; then
            chattr -i /etc/network/interfaces.d/50-cloud-init
            sed -i '/auto lo/d' "/etc/network/interfaces.d/50-cloud-init"
            sed -i '/iface lo inet loopback/d' "/etc/network/interfaces.d/50-cloud-init"
            chattr +i /etc/network/interfaces.d/50-cloud-init
        fi
    fi
    if [ -f "/etc/network/interfaces.new" ]; then
        chattr -i /etc/network/interfaces.new
        rm -rf /etc/network/interfaces.new
    fi
    chattr -i /etc/network/interfaces
    check_loopback_config
}

# 检查回环接口配置
check_loopback_config() {
    if ! grep -q "auto lo" /etc/network/interfaces; then
        _blue "Can not find 'auto lo' in /etc/network/interfaces"
        exit 1
    fi
    if ! grep -q "iface lo inet loopback" /etc/network/interfaces; then
        _blue "Can not find 'iface lo inet loopback' in /etc/network/interfaces"
        exit 1
    fi
}

# 配置vmbr0网桥
configure_vmbr0() {
    chattr -i /etc/network/interfaces
    if grep -q "vmbr0" "/etc/network/interfaces"; then
        _blue "vmbr0 already exists in /etc/network/interfaces"
        _blue "vmbr0 已存在在 /etc/network/interfaces"
    else
        # 根据不同情况添加vmbr0配置
        if [ -z "$ipv6_address" ] || [ -z "$ipv6_prefixlen" ] || [ -z "$ipv6_gateway" ] && [ ! -f /usr/local/bin/pve_last_ipv6 ]; then
            # 无IPV6地址情况
            add_vmbr0_ipv4_only
        elif [ -f /usr/local/bin/pve_slaac_status ] && [ $(cat /usr/local/bin/pve_maximum_subset) = false ] && [ ! -f /usr/local/bin/pve_last_ipv6 ]; then
            # 有IPV6地址，只有一个IPV6地址且后续仅使用一个IPV6地址，存在slaac机制
            add_vmbr0_with_slaac
        elif [ -f /usr/local/bin/pve_last_ipv6 ]; then
            # 有IPV6地址，不只一个IPV6地址，一个用作网关，一个用作实际地址
            add_vmbr0_with_dual_ipv6
        else
            # 有IPV6地址，只有一个IPV6地址，但后续使用最大IPV6子网范围
            add_vmbr0_with_single_ipv6
        fi
    fi
    # 如果不是fe80类型网关，添加fe80地址删除命令
    if [[ "${ipv6_gateway_fe80}" == "N" ]]; then
        chattr -i /etc/network/interfaces
        echo "    up ip addr del $fe80_address dev $interface" >>/etc/network/interfaces
        remove_duplicate_lines "/etc/network/interfaces"
        chattr -i /etc/network/interfaces
    fi
    # 如果IPV6地址是写死附加上的，这块附加回vmbr0，方便后续使用ip6tables进行转发
    appended_file="/usr/local/bin/pve_appended_content.txt"
    if [ -s "$appended_file" ]; then
        chattr -i /etc/network/interfaces
        sed -E 's/(# control-alias) [^[:space:]]+/\1 vmbr0/g; s/(iface) [^[:space:]]+/\1 vmbr0/g' "$appended_file" | sudo tee -a /etc/network/interfaces > /dev/null
        # 如果需要配DNAT/SNAT的V6转发，那么fe80加白就没必要了，需要注释掉
        sed -i '/^[[:space:]]*up ip addr del fe80/s/^/#/' /etc/network/interfaces
        grep -Fxq 'post-up echo 1 > /proc/sys/net/ipv6/conf/vmbr0/proxy_ndp' /etc/network/interfaces || echo 'post-up echo 1 > /proc/sys/net/ipv6/conf/vmbr0/proxy_ndp' >> /etc/network/interfaces
    fi
}

# 仅添加IPV4配置的vmbr0
add_vmbr0_ipv4_only() {
    cat <<EOF | sudo tee -a /etc/network/interfaces
auto vmbr0
iface vmbr0 inet static
    address $ipv4_address
    gateway $ipv4_gateway
    bridge_ports $interface
    bridge_stp off
    bridge_fd 0
EOF
}

# 添加带SLAAC的vmbr0
add_vmbr0_with_slaac() {
    cat <<EOF | sudo tee -a /etc/network/interfaces
auto vmbr0
iface vmbr0 inet static
    address $ipv4_address
    gateway $ipv4_gateway
    bridge_ports $interface
    bridge_stp off
    bridge_fd 0

iface vmbr0 inet6 auto
    bridge_ports $interface
EOF
}

# 添加带双IPV6地址的vmbr0
add_vmbr0_with_dual_ipv6() {
    last_ipv6=$(cat /usr/local/bin/pve_last_ipv6)
    cat <<EOF | sudo tee -a /etc/network/interfaces
auto vmbr0
iface vmbr0 inet static
    address $ipv4_address
    gateway $ipv4_gateway
    bridge_ports $interface
    bridge_stp off
    bridge_fd 0

iface vmbr0 inet6 static
    address ${last_ipv6}
    gateway ${ipv6_gateway}

iface vmbr0 inet6 static
    address ${ipv6_address}/128
EOF
}

# 添加带单IPV6地址的vmbr0
add_vmbr0_with_single_ipv6() {
    cat <<EOF | sudo tee -a /etc/network/interfaces
auto vmbr0
iface vmbr0 inet static
    address $ipv4_address
    gateway $ipv4_gateway
    bridge_ports $interface
    bridge_stp off
    bridge_fd 0

iface vmbr0 inet6 static
    address ${ipv6_address}/128
    gateway ${ipv6_gateway}
EOF
}

# 配置vmbr1网桥
configure_vmbr1() {
    if grep -q "vmbr1" /etc/network/interfaces; then
        _blue "vmbr1 already exists in /etc/network/interfaces"
        _blue "vmbr1 已存在在 /etc/network/interfaces"
    elif [ -f "/usr/local/bin/iface_auto.txt" ]; then
        add_vmbr1_with_accept_ra
    elif [ -z "$ipv6_address" ] || [ -z "$ipv6_prefixlen" ] || [ -z "$ipv6_gateway" ] || [ "$status_he" = true ]; then
        add_vmbr1_ipv4_only
    else
        add_vmbr1_with_ipv6
    fi
}

# 添加带RA接受的vmbr1
add_vmbr1_with_accept_ra() {
    cat <<EOF | sudo tee -a /etc/network/interfaces
auto vmbr1
iface vmbr1 inet static
    address 172.16.1.1
    netmask 255.255.255.0
    bridge_ports none
    bridge_stp off
    bridge_fd 0
    post-up echo 1 > /proc/sys/net/ipv4/ip_forward
    post-up echo 1 > /proc/sys/net/ipv4/conf/vmbr1/proxy_arp
    post-up iptables -t nat -A POSTROUTING -s '172.16.1.0/24' -o vmbr0 -j MASQUERADE
    post-down iptables -t nat -D POSTROUTING -s '172.16.1.0/24' -o vmbr0 -j MASQUERADE

pre-up echo 2 > /proc/sys/net/ipv6/conf/vmbr0/accept_ra
EOF
}

# 仅添加IPV4配置的vmbr1
add_vmbr1_ipv4_only() {
    cat <<EOF | sudo tee -a /etc/network/interfaces
auto vmbr1
iface vmbr1 inet static
    address 172.16.1.1
    netmask 255.255.255.0
    bridge_ports none
    bridge_stp off
    bridge_fd 0
    post-up echo 1 > /proc/sys/net/ipv4/ip_forward
    post-up echo 1 > /proc/sys/net/ipv4/conf/vmbr1/proxy_arp
    post-up iptables -t nat -A POSTROUTING -s '172.16.1.0/24' -o vmbr0 -j MASQUERADE
    post-down iptables -t nat -D POSTROUTING -s '172.16.1.0/24' -o vmbr0 -j MASQUERADE
EOF
}

# 添加带IPV6配置的vmbr1
add_vmbr1_with_ipv6() {
    cat <<EOF | sudo tee -a /etc/network/interfaces
auto vmbr1
iface vmbr1 inet static
    address 172.16.1.1
    netmask 255.255.255.0
    bridge_ports none
    bridge_stp off
    bridge_fd 0
    post-up echo 1 > /proc/sys/net/ipv4/ip_forward
    post-up echo 1 > /proc/sys/net/ipv4/conf/vmbr1/proxy_arp
    post-up iptables -t nat -A POSTROUTING -s '172.16.1.0/24' -o vmbr0 -j MASQUERADE
    post-down iptables -t nat -D POSTROUTING -s '172.16.1.0/24' -o vmbr0 -j MASQUERADE

iface vmbr1 inet6 static
    address 2001:db8:1::1/64
    post-up sysctl -w net.ipv6.conf.all.forwarding=1
    post-up ip6tables -t nat -A POSTROUTING -s 2001:db8:1::/64 -o vmbr0 -j MASQUERADE
    post-down sysctl -w net.ipv6.conf.all.forwarding=0
    post-down ip6tables -t nat -D POSTROUTING -s 2001:db8:1::/64 -o vmbr0 -j MASQUERADE
EOF
}

# 配置vmbr2网桥（如果需要）
configure_vmbr2() {
    appended_file="/usr/local/bin/pve_appended_content.txt"
    if [ -n "$ipv6_prefixlen" ] && [ "$((ipv6_prefixlen))" -le 112 ] && [ ! -s "$appended_file" ]; then
        if grep -q "vmbr2" /etc/network/interfaces; then
            _blue "vmbr2 already exists in /etc/network/interfaces"
            _blue "vmbr2 已存在在 /etc/network/interfaces"
        elif [ -f /usr/local/bin/pve_maximum_subset ] && [ $(cat /usr/local/bin/pve_maximum_subset) = false ]; then
            _blue "No set vmbr2"
        elif [ "$status_he" = true ]; then
            configure_vmbr2_with_he_tunnel
        elif [ ! -z "$ipv6_address" ] && [ ! -z "$ipv6_prefixlen" ] && [ ! -z "$ipv6_gateway" ] && [ ! -z "$ipv6_address_without_last_segment" ]; then
            configure_vmbr2_with_ipv6_subnet
        else
            rm -rf /etc/systemd/system/ndpresponder.service
        fi
    elif [ -s "$appended_file" ]; then
        tmp_script="/usr/local/bin/check_ipv6.sh"
        echo '#!/bin/bash' > "$tmp_script"
        echo "" >> "$tmp_script"
        counter=0
        grep -Po '(?<=address )[\da-fA-F:]+(?=/64)' "$appended_file" | while read -r ip; do
            delay=$((counter * 6))
            echo "sleep $delay; curl --interface $ip -6 -s https://ifconfig.co &" >> "$tmp_script"
            counter=$((counter + 1))
        done
        echo "wait" >> "$tmp_script"
        chmod +x "$tmp_script"
        (crontab -l 2>/dev/null; echo "*/15 * * * * bash $tmp_script") | sort -u | crontab -
    else
        rm -rf /etc/systemd/system/ndpresponder.service
    fi
}

# 为HE隧道配置vmbr2
configure_vmbr2_with_he_tunnel() {
    chattr -i /etc/network/interfaces
    sudo tee -a /etc/network/interfaces <<EOF

${temp_config}
EOF
    cat <<EOF | sudo tee -a /etc/network/interfaces

auto vmbr2
iface vmbr2 inet6 static
    address ${new_subnet}
    bridge_ports none
    bridge_stp off
    bridge_fd 0
EOF
    if [ -f "/usr/local/bin/ndpresponder" ]; then
        new_exec_start="ExecStart=/usr/local/bin/ndpresponder -i he-ipv6 -n ${new_subnet}"
        file_path="/etc/systemd/system/ndpresponder.service"
        line_number=6
        sed -i "${line_number}s|.*|${new_exec_start}|" "$file_path"
    fi
    configure_ipv6_forwarding
}

# 为IPV6子网配置vmbr2
configure_vmbr2_with_ipv6_subnet() {
    appended_file="/usr/local/bin/pve_appended_content.txt"
    if [ ! -s "$appended_file" ] && [ -f "/usr/local/bin/ndpresponder" ]; then
        cat <<EOF | sudo tee -a /etc/network/interfaces
auto vmbr2
iface vmbr2 inet6 static
    address ${ipv6_address}/${ipv6_prefixlen}
    bridge_ports none
    bridge_stp off
    bridge_fd 0
EOF
        new_exec_start="ExecStart=/usr/local/bin/ndpresponder -i vmbr0 -n ${ipv6_address_without_last_segment}0/${ipv6_prefixlen}"
        file_path="/etc/systemd/system/ndpresponder.service"
        line_number=6
        sudo sed -i "${line_number}s|.*|${new_exec_start}|" "$file_path"
        echo '*/2 * * * * curl -m 6 -s ipv6.ip.sb && curl -m 6 -s ipv6.ip.sb' | crontab -
    fi
    configure_ipv6_forwarding
}


# 配置IPV6转发设置
configure_ipv6_forwarding() {
    update_sysctl "net.ipv6.conf.all.forwarding=1"
    update_sysctl "net.ipv6.conf.all.proxy_ndp=1"
    update_sysctl "net.ipv6.conf.default.proxy_ndp=1"
    update_sysctl "net.ipv6.conf.vmbr0.proxy_ndp=1"
    update_sysctl "net.ipv6.conf.vmbr1.proxy_ndp=1"
    update_sysctl "net.ipv6.conf.vmbr2.proxy_ndp=1"
}

# 安装并配置IPtables
setup_iptables() {
    apt-get install -y iptables iptables-persistent
    iptables -t nat -A POSTROUTING -j MASQUERADE
    update_sysctl "net.ipv4.ip_forward=1"
    ${sysctl_path} -p
}

restart_network_services() {
    service networking restart
    systemctl restart networking.service
    sleep 3
    ifreload -ad
    iptables-save | awk '{if($1=="COMMIT"){delete x}}$1=="-A"?!x[$0]++:1' | iptables-restore
}

setup_ndpresponder() {
    if [ -f "/usr/local/bin/ndpresponder" ] && [ -f "/etc/systemd/system/ndpresponder.service" ]; then
        echo "Found ndpresponder binary and service file, setting up..."
        systemctl daemon-reload
        systemctl enable ndpresponder.service
        systemctl start ndpresponder.service
        systemctl status ndpresponder.service 2>/dev/null
        return 0
    else
        echo "ndpresponder binary or service file not found."
        return 1
    fi
}

backup_and_clean_interfaces() {
    if [ ! -f /etc/network/interfaces_nat.bak ]; then
        cp /etc/network/interfaces /etc/network/interfaces_nat.bak
        chattr -i /etc/network/interfaces
        input_file="/etc/network/interfaces"
        output_file="/etc/network/interfaces.tmp"
        start_pattern="iface lo inet loopback"
        end_pattern="auto vmbr0"
        delete_lines=0
        while IFS= read -r line; do
            if [[ $line == *"$start_pattern"* ]]; then
                delete_lines=1
            fi
            if [ $delete_lines -eq 0 ] || [[ $line == *"$start_pattern"* ]] || [[ $line == *"$end_pattern"* ]]; then
                echo "$line" >>"$output_file"
            fi
            if [[ $line == *"$end_pattern"* ]]; then
                delete_lines=0
            fi
        done <"$input_file"
        mv "$output_file" "$input_file"
        chattr +i /etc/network/interfaces
    fi
}

clean_cache_files() {
    if [ -f "/etc/network/interfaces.new" ]; then
        chattr -i /etc/network/interfaces.new
        rm -rf /etc/network/interfaces.new
    fi
}

check_ndpresponder_status() {
    appended_file="/usr/local/bin/pve_appended_content.txt"
    if [ ! -s "$appended_file" ]; then
        service_status=$(systemctl is-active ndpresponder.service)
        if [[ "$service_status" == "active" || "$service_status" == "activating" ]]; then
            _green "The ndpresponder service started successfully and is running, and the host can open a service with a separate IPV6 address."
            _green "ndpresponder服务启动成功且正在运行，宿主机可开设带独立IPV6地址的服务。"
        else
            if grep -q "vmbr2" /etc/network/interfaces; then
                _green "Please perform reboot to reboot the server to load the IPV6 configuration, otherwise IPV6 is not available"
                _green "请执行 reboot 重启服务器以加载IPV6配置，否则IPV6不可用"
            else
                _green "The status of the ndpresponder service is abnormal and the host can not open a service with a separate IPV6 address."
                _green "ndpresponder服务状态异常，宿主机不可开设带独立IPV6地址的服务。"
            fi
        fi
    elif [ -s "$appended_file" ]; then
        _green "Additional IPv6 addresses exist for mapping by NAT, and the host can open services with separate IPV6 addresses."
        _green "存在额外的IPv6地址可供NAT进行映射，宿主机可开设带独立IPV6地址的服务。"
    fi
}

install_required_tools
request_ipv6
cdn_urls=("https://cdn0.spiritlhl.top/" "http://cdn3.spiritlhl.net/" "http://cdn1.spiritlhl.net/" "https://ghproxy.com/" "http://cdn2.spiritlhl.net/")
check_cdn_file
get_system_arch
sysctl_path=$(which sysctl)
detect_network_interfaces
detect_he_tunnel
install_ndpresponder
detect_ipv4_info
prepare_network_interfaces
configure_vmbr0
configure_vmbr1
configure_vmbr2
chattr +i /etc/network/interfaces
rm -rf /usr/local/bin/iface_auto.txt
setup_iptables
restart_network_services
setup_ndpresponder
backup_and_clean_interfaces
clean_cache_files
systemctl start check-dns.service
sleep 3
check_ndpresponder_status
sleep 1
_green "It is recommended to restart the server once to apply the new configuration."
_green "强烈推荐重启一次服务器，以应用新配置，避免配置不生效的问题。"
_green "you can test open a virtual machine or container to see if the actual network has been applied successfully"
_green "你可以测试开一个虚拟机或者容器看看就知道是不是实际网络已应用成功了"
