#!/usr/bin/env bash
# ============================================================
# DNS 全局配置脚本（含 IPv6 禁用 + 有线网卡静态 IP）
# 功能:
#   1. 全局固定 DNS（深圳电信）
#   2. 全局禁用 IPv6（sysctl + GRUB + NM）
#   3. 有线网卡支持用户输入静态 IP
# 用法: sudo bash dns_setup.sh
# ============================================================

set -euo pipefail

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'

DNS_SERVERS="202.96.128.143 202.96.128.68 202.96.134.133 202.96.128.86 202.96.128.166"
GRUB_FILE="/etc/default/grub"
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
NOW_TS=$(date +%Y%m%d%H%M%S)

echo "========================================"
echo "   DNS 全局配置 + IPv6 禁用脚本"
echo "========================================"
echo ""

# 检查 root
if [[ $EUID -ne 0 ]]; then
    echo -e "${RED}[错误] 请使用 sudo 运行此脚本${NC}"
    exit 1
fi

# ──────────────────────────────────────────
# 步骤 1: 配置 systemd-resolved 全局 DNS
# ──────────────────────────────────────────
echo "==> 步骤 1/6: 配置 systemd-resolved 全局 DNS"

if [[ ! -f /etc/systemd/resolved.conf.bak ]]; then
    cp /etc/systemd/resolved.conf /etc/systemd/resolved.conf.bak
    echo -e "${GREEN}[备份] /etc/systemd/resolved.conf → resolved.conf.bak${NC}"
fi

cat > /etc/systemd/resolved.conf <<EOF
# systemd-resolved 配置文件
# 由 dns_setup.sh 生成 (${TIMESTAMP})
# 备份: /etc/systemd/resolved.conf.bak

[Resolve]
DNS=${DNS_SERVERS}
LLMNR=no
MulticastDNS=no
DNSSEC=no
DNSOverTLS=no
Cache=yes
EOF

echo -e "${GREEN}[完成] 全局 DNS: ${DNS_SERVERS}${NC}"

# ──────────────────────────────────────────
# 步骤 2: sysctl 全局禁用 IPv6
# ──────────────────────────────────────────
echo ""
echo "==> 步骤 2/6: sysctl 全局禁用 IPv6"

cat > /etc/sysctl.d/99-disable-ipv6.conf <<EOF
# 全局禁用 IPv6
# 由 dns_setup.sh 生成 (${TIMESTAMP})
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1
EOF

sysctl --system &>/dev/null
echo -e "${GREEN}[完成] IPv6 已全局禁用 (sysctl)${NC}"

if [[ "$(cat /proc/sys/net/ipv6/conf/all/disable_ipv6)" == "1" ]]; then
    echo -e "${GREEN}[验证] /proc/sys/net/ipv6/conf/all/disable_ipv6 = 1 ✓${NC}"
fi

# ──────────────────────────────────────────
# 步骤 3: GRUB 内核参数禁用 IPv6
# ──────────────────────────────────────────
echo ""
echo "==> 步骤 3/6: GRUB 内核参数禁用 IPv6"

if grep -q "ipv6.disable=1" "$GRUB_FILE" 2>/dev/null; then
    echo "[跳过] GRUB 已包含 ipv6.disable=1"
else
    cp "$GRUB_FILE" "${GRUB_FILE}.bak.${NOW_TS}"
    sed -i 's/^GRUB_CMDLINE_LINUX_DEFAULT="\(.*\)"/GRUB_CMDLINE_LINUX_DEFAULT="\1 ipv6.disable=1"/' "$GRUB_FILE"
    sed -i 's/^GRUB_CMDLINE_LINUX="\(.*\)"/GRUB_CMDLINE_LINUX="\1 ipv6.disable=1"/' "$GRUB_FILE"
    update-grub &>/dev/null || grub2-mkconfig -o /boot/grub2/grub.cfg &>/dev/null
    echo -e "${GREEN}[完成] GRUB 内核参数已添加 ipv6.disable=1${NC}"
    echo -e "${YELLOW}[提示] GRUB 修改需重启后生效${NC}"
fi

# ──────────────────────────────────────────
# 步骤 4: 有线网卡静态 IP 配置（含重复检测与清理）
# ──────────────────────────────────────────
echo ""
echo "==> 步骤 4/6: 有线网卡检测与静态 IP 配置"
echo ""

# 收集所有有线网卡连接，按接口分组
declare -A IFACE_CONNS  # 接口 -> "uuid|cname|uuid|cname|..." (用换行分隔多个)
while IFS= read -r uuid; do
    ctype=$(nmcli -t -f connection.type connection show uuid "$uuid" 2>/dev/null | cut -d: -f2-)
    cname=$(nmcli -t -f connection.id connection show uuid "$uuid" 2>/dev/null | cut -d: -f2-)
    iface=$(nmcli -t -f connection.interface-name connection show uuid "$uuid" 2>/dev/null | cut -d: -f2-)
    if [[ "$ctype" == "802-3-ethernet" ]]; then
        if [[ -n "${IFACE_CONNS[$iface]:-}" ]]; then
            IFACE_CONNS[$iface]="${IFACE_CONNS[$iface]}
$uuid|$cname"
        else
            IFACE_CONNS[$iface]="$uuid|$cname"
        fi
    fi
done < <(nmcli -t -f UUID connection show 2>/dev/null)

if [[ ${#IFACE_CONNS[@]} -eq 0 ]]; then
    echo "  未检测到有线网卡连接，跳过。"
else
    NETPLAN_DIR="/etc/netplan"

    for iface in "${!IFACE_CONNS[@]}"; do
        # 解析该接口的所有连接
        mapfile -t entries <<< "${IFACE_CONNS[$iface]}"

        if [[ ${#entries[@]} -gt 1 ]]; then
            echo ""
            echo -e "  ${YELLOW}══════════════════════════════════════${NC}"
            echo -e "  ${YELLOW}  检测到接口 [$iface] 有 ${#entries[@]} 个重复连接${NC}"
            echo -e "  ${YELLOW}══════════════════════════════════════${NC}"

            # 找出活跃连接（有 IP 的）
            active_entry=""
            stale_uuids=()
            for e in "${entries[@]}"; do
                IFS='|' read -r euuid ecname <<< "$e"
                eip=$(ip -4 addr show "$iface" 2>/dev/null | grep -oP 'inet \K[\d.]+/[\d]+' | head -1)
                estate=$(nmcli -t -f GENERAL.STATE connection show uuid "$euuid" 2>/dev/null | cut -d: -f2-)

                echo ""
                echo "    [$ecname]  UUID: $euuid"
                echo "    当前 NM 状态: ${estate:-未知}"

                if [[ -n "$eip" ]]; then
                    # 检查该连接的 IP 是否匹配接口 IP
                    conn_ip=$(nmcli -t -f IP4.ADDRESS connection show uuid "$euuid" 2>/dev/null | cut -d: -f2- | head -1 | cut -d'/' -f1 | cut -d' ' -f1)
                    iface_ip=$(echo "$eip" | cut -d'/' -f1)
                    if [[ "$conn_ip" == "$iface_ip" ]] || [[ "$estate" == "activated" ]]; then
                        active_entry="$e"
                        echo -e "    ${GREEN}◎ 活跃（当前使用中）${NC}"
                    else
                        stale_uuids+=("$euuid")
                        echo -e "    ${YELLOW}⊙ 残留/非活跃${NC}"
                    fi
                else
                    stale_uuids+=("$euuid")
                    echo -e "    ${YELLOW}⊙ 无 IP，疑似残留${NC}"
                fi
            done

            # 若未明确找到活跃连接，保留第一个，其余标记为残留
            if [[ -z "$active_entry" ]]; then
                active_entry="${entries[0]}"
                stale_uuids=()
                for ((i=1; i<${#entries[@]}; i++)); do
                    IFS='|' read -r suuid scname <<< "${entries[$i]}"
                    stale_uuids+=("$suuid")
                done
            fi

            # 清理残留连接
            if [[ ${#stale_uuids[@]} -gt 0 ]]; then
                echo ""
                echo -e "    ${YELLOW}将自动清理 ${#stale_uuids[@]} 个残留连接:${NC}"
                for suuid in "${stale_uuids[@]}"; do
                    sname=$(nmcli -t -f connection.id connection show uuid "$suuid" 2>/dev/null | cut -d: -f2-)
                    echo "      - $sname ($suuid)"
                done

                read -r -p "    确认清理？[Y/n] " do_clean
                if [[ ! "$do_clean" =~ ^[Nn]$ ]]; then
                    for suuid in "${stale_uuids[@]}"; do
                        sname=$(nmcli -t -f connection.id connection show uuid "$suuid" 2>/dev/null | cut -d: -f2-)
                        nmcli connection delete "$suuid" 2>/dev/null || true
                        rm -f "${NETPLAN_DIR}/90-NM-${suuid}.yaml"
                        echo -e "    ${GREEN}✓ 已删除: $sname${NC}"
                    done
                else
                    echo "    已跳过清理。"
                fi
            fi

            # 更新 entries 为仅保留活跃连接
            entries=("$active_entry")
        fi

        # 对每个保留的有线连接，配置静态 IP
        for e in "${entries[@]}"; do
            IFS='|' read -r uuid cname <<< "$e"

            echo ""
            echo "────────────────────────────────────────"
            echo "  有线网卡: $cname"
            echo "  接口名:   $iface"
            echo "  UUID:     $uuid"
            echo ""

            # 获取当前 IP 信息
            cur_ip=""
            cur_gw=""
            if [[ -n "$iface" ]] && ip addr show "$iface" &>/dev/null; then
                cur_ip=$(ip -4 addr show "$iface" 2>/dev/null | grep -oP 'inet \K[\d.]+/[\d]+' | head -1)
                cur_gw=$(ip -4 route show default dev "$iface" 2>/dev/null | awk '{print $3}' | head -1)
            fi

            echo "  当前状态:"
            echo "    IP 地址: ${cur_ip:-未获取}"
            echo "    网关:    ${cur_gw:-未获取}"
            echo ""

            # 询问用户
            read -r -p "  是否为此网卡设置静态 IP？[y/N] " set_static
            if [[ ! "$set_static" =~ ^[Yy]$ ]]; then
                echo -e "    ${YELLOW}⊙ 跳过静态 IP，仅固定 DNS${NC}"

                cur_method=$(nmcli -t -f ipv4.method connection show uuid "$uuid" 2>/dev/null | cut -d: -f2-)
                if [[ "$cur_method" == "link-local" ]]; then
                    echo -e "    ${YELLOW}⊙ method=link-local，切换到 auto 以支持 DNS${NC}"
                    nmcli connection modify "$uuid" ipv4.method auto
                fi
                nmcli connection modify "$uuid" ipv4.ignore-auto-dns yes
                nmcli connection modify "$uuid" ipv4.dns "${DNS_SERVERS// /,}"
                nmcli connection modify "$uuid" ipv6.method disabled
                continue
            fi

            # 输入静态 IP
            while true; do
                read -r -p "  请输入静态 IP 地址 (格式: x.x.x.x/yy): " static_ip
                if [[ "$static_ip" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/[0-9]+$ ]]; then
                    break
                fi
                echo -e "    ${RED}格式错误，示例: 192.168.1.90/24${NC}"
            done

            # 输入网关
            read -r -p "  请输入网关地址 (回车使用检测值 ${cur_gw:-无}): " static_gw
            if [[ -z "$static_gw" ]]; then
                static_gw="$cur_gw"
            fi
            if [[ -z "$static_gw" ]]; then
                echo -e "    ${RED}[错误] 网关不能为空${NC}"
                continue
            fi

            echo ""
            echo "  即将应用以下配置:"
            echo "    连接名:  $cname"
            echo "    接口:    $iface"
            echo "    IP:      $static_ip"
            echo "    网关:    $static_gw"
            echo "    DNS:     $(echo "$DNS_SERVERS" | tr ' ' ',')"
            echo "    IPv6:    禁用"
            echo ""

            read -r -p "  确认应用？[Y/n] " confirm
            if [[ "$confirm" =~ ^[Nn]$ ]]; then
                echo -e "    ${YELLOW}⊙ 已取消${NC}"
                continue
            fi

            # ── 应用 NM 配置 ──
            nmcli connection modify "$uuid" \
                ipv4.method manual \
                ipv4.addresses "$static_ip" \
                ipv4.gateway "$static_gw" \
                ipv4.dns "${DNS_SERVERS// /,}" \
                ipv6.method disabled

            echo -e "  ${GREEN}✓ NM 配置已写入${NC}"

            # ── 同步 netplan ──
            NETPLAN_FILE="${NETPLAN_DIR}/90-NM-${uuid}.yaml"

            if [[ -d "$NETPLAN_DIR" ]]; then
                [[ ! -d "${NETPLAN_DIR}.bak" ]] && cp -r "$NETPLAN_DIR" "${NETPLAN_DIR}.bak"

                cat > "$NETPLAN_FILE" <<NETEOF
network:
  version: 2
  ethernets:
    ${iface}:
      renderer: NetworkManager
      match: {}
      dhcp4: false
      addresses:
        - "${static_ip}"
      routes:
        - to: "0.0.0.0/0"
          via: "${static_gw}"
      nameservers:
        addresses:
$(for dns in $DNS_SERVERS; do echo "          - ${dns}"; done)
      networkmanager:
        uuid: "${uuid}"
        name: "${cname}"
        passthrough:
          ipv6.method: "disabled"
NETEOF

                echo -e "  ${GREEN}✓ netplan 配置已同步 → ${NETPLAN_FILE}${NC}"

                if netplan generate 2>/dev/null; then
                    echo -e "  ${GREEN}✓ netplan 语法检查通过${NC}"
                else
                    echo -e "  ${YELLOW}⚠ netplan 语法检查有警告，请手动确认${NC}"
                fi
            fi

            echo ""
        done
    done
fi

# ──────────────────────────────────────────
# 步骤 5: 配置 NetworkManager 其余连接
# ──────────────────────────────────────────
echo ""
echo "==> 步骤 5/6: 配置其余 NetworkManager 连接 (WiFi 等)"

for conn in $(nmcli -t -f UUID connection show 2>/dev/null); do
    ctype=$(nmcli -t -f connection.type connection show uuid "$conn" 2>/dev/null | cut -d: -f2-)
    cname=$(nmcli -t -f connection.id connection show uuid "$conn" 2>/dev/null | cut -d: -f2-)

    # 跳过回环
    if [[ "$ctype" == "loopback" ]]; then
        nmcli connection modify "$conn" ipv6.method auto 2>/dev/null || true
        echo "  $cname → ${YELLOW}⊙ 回环，跳过${NC}"
        continue
    fi

    # 有线网卡已在步骤 4 处理
    if [[ "$ctype" == "802-3-ethernet" ]]; then
        echo "  $cname → ${YELLOW}⊙ 有线网卡，已在步骤 4 处理${NC}"
        continue
    fi

    # WiFi 等：固定 DNS + 禁用 IPv6
    cur_method=$(nmcli -t -f ipv4.method connection show uuid "$conn" 2>/dev/null | cut -d: -f2-)
    if [[ "$cur_method" == "link-local" ]]; then
        nmcli connection modify "$conn" ipv4.method auto
    fi

    nmcli connection modify "$conn" ipv4.ignore-auto-dns yes
    nmcli connection modify "$conn" ipv4.dns "${DNS_SERVERS// /,}"
    nmcli connection modify "$conn" ipv6.method disabled

    echo "  $cname (类型: $ctype) → ${GREEN}✓ DNS 固定 / IPv6 禁用${NC}"
done

# ──────────────────────────────────────────
# 步骤 6: 重启服务
# ──────────────────────────────────────────
echo ""
echo "==> 步骤 6/6: 重启服务"

systemctl restart systemd-resolved
echo -e "${GREEN}[完成] systemd-resolved 已重启${NC}"

# ──────────────────────────────────────────
# 状态汇总
# ──────────────────────────────────────────
echo ""
echo "========================================"
echo "           当前状态汇总"
echo "========================================"

echo ""
echo "--- DNS 状态 ---"
resolvectl status 2>&1 || true

echo ""
echo "--- IPv6 状态 ---"
echo "sysctl disable_ipv6: $(cat /proc/sys/net/ipv6/conf/all/disable_ipv6 2>/dev/null || echo 'unknown')"
ip -6 addr show 2>/dev/null | grep "inet6" || echo "(无 IPv6 地址)"

echo ""
echo "--- DNS 解析验证 ---"
for domain in baidu.com qq.com; do
    result=$(resolvectl query "$domain" 2>&1 || true)
    echo "  $domain → $(echo "$result" | head -3)"
done

echo ""
echo -e "${GREEN}全部配置完成！${NC}"
echo ""
echo -e "${YELLOW}提示: GRUB 修改需重启后完全生效。${NC}"
echo -e "${YELLOW}      DNS / IPv6 变动需重连网络后生效。${NC}"
