#!/usr/bin/env bash
# Cloudflare Anycast Pro Speedtest & Auto Push Tool (Linux / macOS)
# [Features]
# 1. 动态生成 Cloudflare 官方多网段采样池 + 实时 DNS 动态探测
# 2. 强制使用 --noproxy '*' 绕过代理
# 3. 真实 SNI + TLS 端到端探测
# 4. 自动提取 Cloudflare Colo 并翻译为中文机房地区
# 5. 测速后支持一键推送至服务器

set -e

DOMAIN="cf.630828.xyz"
PUSH_API_URL="https://cf.630828.xyz/api/push_preferred_ip"

# Colo 机房代码中英文映射函数
get_colo_name() {
    local code="${1^^}"
    case "$code" in
        "HKG") echo "HKG - 中国香港 (Hong Kong)" ;;
        "TPE") echo "TPE - 中国台湾台北 (Taipei)" ;;
        "KHH") echo "KHH - 中国台湾高雄 (Kaohsiung)" ;;
        "NRT") echo "NRT - 日本东京 (Tokyo)" ;;
        "KIX") echo "KIX - 日本大阪 (Osaka)" ;;
        "ICN") echo "ICN - 韩国首尔 (Seoul)" ;;
        "SIN") echo "SIN - 新加坡 (Singapore)" ;;
        "BKK") echo "BKK - 泰国曼谷 (Bangkok)" ;;
        "KUL") echo "KUL - 马来西亚吉隆坡 (Kuala Lumpur)" ;;
        "SJC") echo "SJC - 美国圣何塞 (San Jose)" ;;
        "LAX") echo "LAX - 美国洛杉矶 (Los Angeles)" ;;
        "SFO") echo "SFO - 美国旧金山 (San Francisco)" ;;
        "SEA") echo "SEA - 美国西雅图 (Seattle)" ;;
        "FRA") echo "FRA - 德国法兰克福 (Frankfurt)" ;;
        "LHR") echo "LHR - 英国伦敦 (London)" ;;
        "")    echo "未知机房" ;;
        *)     echo "$code - 海外机房" ;;
    esac
}

# 动态构建全量候选 IP 池
build_candidate_pool() {
    local pool=()

    # 官方 104.16.0.0/12 段采样
    for s in $(seq 16 27); do
        pool+=("104.$s.0.1" "104.$s.64.1" "104.$s.128.1" "104.$s.192.1")
    done

    # 官方 172.64.0.0/13 段采样
    for s in $(seq 64 71); do
        pool+=("172.$s.0.1" "172.$s.128.1")
    done

    # 官方 162.158/159 段采样
    for t in 0 64 128 192 208 212; do
        pool+=("162.158.$t.1" "162.159.$t.1")
    done

    # 经典优质节点
    local classic=(
        "104.16.24.1" "104.16.160.1" "104.17.160.1" "104.18.32.1" "104.18.160.1"
        "104.19.64.1" "104.19.160.1" "104.20.0.1" "104.22.160.1" "172.67.160.1"
        "198.41.192.1" "198.41.214.1" "198.41.215.1" "104.16.0.1" "162.159.192.1"
        "162.159.193.1" "162.159.194.1" "162.159.195.1" "162.159.208.1" "162.159.209.1"
        "103.21.244.1" "108.162.192.1" "141.101.64.1" "188.114.96.1"
    )
    pool+=("${classic[@]}")

    # DNS 动态解析
    local dns_ips
    dns_ips=$(dig +short A "$DOMAIN" 2>/dev/null || nslookup "$DOMAIN" 2>/dev/null | awk '/^Address: / { print $2 }' || true)
    if [ -n "$dns_ips" ]; then
        for ip in $dns_ips; do
            [[ "$ip" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]] && pool+=("$ip")
        done
    fi

    # 去重并排序
    printf "%s\n" "${pool[@]}" | sort -u
}

# 单次探针函数 (SNI+TLS)
probe_ip() {
    local ip="$1"
    local resolve="${DOMAIN}:443:${ip}"
    local format="%{http_code}|%{time_connect}|%{time_appconnect}|%{time_total}"

    local res
    res=$(curl --noproxy '*' -4 -sS --connect-timeout 2 --max-time 3 \
        --resolve "$resolve" -w "$format" "https://${DOMAIN}/cdn-cgi/trace?_t=$(date +%s%N)" 2>/dev/null || echo "")

    local code=$(echo "$res" | awk -F'|' '{print $1}')
    if [[ "$code" =~ ^(200|400|301|302)$ ]]; then
        local total_sec=$(echo "$res" | awk -F'|' '{print $4}')
        local total_ms=$(awk -v t="$total_sec" 'BEGIN {printf "%.1f", t * 1000}')
        local colo=$(echo "$res" | grep -o 'colo=[A-Z0-9]*' | head -n1 | cut -d= -f2 || echo "CF")
        [ -z "$colo" ] && colo="CF"
        echo "$total_ms|$colo"
    else
        echo "FAIL"
    fi
}

main_speedtest() {
    clear
    echo "============================================================"
    echo "  Cloudflare 优选 IP 智能多维测速与自动推送工具 (Linux/Mac)  "
    echo "============================================================"
    echo " 特性: 动态全量IP池 · 强制绕过代理 · SNI真实握手 · 机房归属识别"
    echo ""

    echo "📡 正在动态构建全网段候选 IP 池..."
    mapfile -t CANDIDATES < <(build_candidate_pool)
    local total_count=${#CANDIDATES[@]}
    echo "✅ 候选 IP 采样完成，共生成 $total_count 个测速节点。"
    echo ""

    echo "【阶段 1/3】全量候选池端到端快速初筛..."
    local S1_FILE=$(mktemp)
    local idx=0
    for ip in "${CANDIDATES[@]}"; do
        idx=$((idx + 1))
        local out=$(probe_ip "$ip")
        if [ "$out" != "FAIL" ]; then
            local ms=$(echo "$out" | cut -d'|' -f1)
            local colo=$(echo "$out" | cut -d'|' -f2)
            echo "$ms $ip $colo" >> "$S1_FILE"
            printf "\r\033[K[%d/%d] \033[32m[OK]\033[0m IP: %-15s  延迟: %6s ms  机房: %s" "$idx" "$total_count" "$ip" "$ms" "$colo"
        else
            printf "\r\033[K[%d/%d] \033[31m[✕]\033[0m  IP: %-15s  超时/丢包" "$idx" "$total_count" "$ip"
        fi
    done
    echo ""

    if [ ! -s "$S1_FILE" ]; then
        echo -e "\n\033[31m❌ 本地网络环境下未能连通任何 Cloudflare 节点。\033[0m"
        rm -f "$S1_FILE"
        exit 1
    fi

    # 阶段 2: 选前 10 名进行 5 轮复测
    echo -e "\n【阶段 2/3】Top 10 精英节点 5 轮稳定性复测..."
    local S2_FILE=$(mktemp)
    local rank10=0
    while read -r _s1ms ip colo; do
        rank10=$((rank10 + 1))
        local tot_ms=0
        local succ=0
        local cur_colo="$colo"
        for r in 1 2 3 4 5; do
            local res=$(probe_ip "$ip")
            if [ "$res" != "FAIL" ]; then
                local ms=$(echo "$res" | cut -d'|' -f1)
                local cl=$(echo "$res" | cut -d'|' -f2)
                [ -n "$cl" ] && [ "$cl" != "CF" ] && cur_colo="$cl"
                tot_ms=$(awk -v a="$tot_ms" -v b="$ms" 'BEGIN {print a + b}')
                succ=$((succ + 1))
            fi
        done
        if [ "$succ" -gt 0 ]; then
            local avg=$(awk -v t="$tot_ms" -v c="$succ" 'BEGIN {printf "%.1f", t / c}')
            echo "$avg $ip $cur_colo $succ" >> "$S2_FILE"
            printf " [%d/10] \033[32m[复测入围]\033[0m IP: %-15s  平均: %6s ms  成功率: %d/5  机房: %s\n" "$rank10" "$ip" "$avg" "$succ" "$cur_colo"
        fi
    done < <(sort -n -k1 "$S1_FILE" | head -n 10)
    rm -f "$S1_FILE"

    # 阶段 3: 选前 3 名进行 10 轮终极决战
    echo -e "\n【阶段 3/3】Top 3 终极决战 10 轮高频打分..."
    local FINAL_FILE=$(mktemp)
    local top3_count=0
    while read -r _s2avg ip colo succ; do
        top3_count=$((top3_count + 1))
        local lats=()
        local cur_colo="$colo"
        for r in $(seq 1 10); do
            local res=$(probe_ip "$ip")
            if [ "$res" != "FAIL" ]; then
                local ms=$(echo "$res" | cut -d'|' -f1)
                local cl=$(echo "$res" | cut -d'|' -f2)
                [ -n "$cl" ] && [ "$cl" != "CF" ] && cur_colo="$cl"
                lats+=("$ms")
            fi
        done
        if [ "${#lats[@]}" -gt 0 ]; then
            # 计算平均与抖动
            local stats=$(printf "%s\n" "${lats[@]}" | sort -n | awk '
                BEGIN { min=99999; max=0; sum=0; count=0 }
                {
                    val=$1;
                    if(val<min) min=val;
                    if(val>max) max=val;
                    sum+=val;
                    arr[count]=val;
                    count++;
                }
                END {
                    avg = sum / count;
                    med = arr[int(count/2)];
                    jit = max - min;
                    printf "%.1f %.1f %.1f %d", avg, med, jit, count;
                }
            ')
            local avg=$(echo "$stats" | cut -d' ' -f1)
            local med=$(echo "$stats" | cut -d' ' -f2)
            local jit=$(echo "$stats" | cut -d' ' -f3)
            local runs=$(echo "$stats" | cut -d' ' -f4)
            echo "$med $ip $cur_colo $avg $jit $runs" >> "$FINAL_FILE"
        fi
    done < <(sort -n -k1 "$S2_FILE" | head -n 3)
    rm -f "$S2_FILE"

    echo ""
    echo "============================================================"
    echo " 🏆 测速完成！最优 IP 决胜排行榜 (含真实机房归属):"
    echo "============================================================"
    printf "%-6s %-16s %-26s %-10s %-10s %-10s\n" "排名" "优选 IP" "机房与归属地区" "中位数延迟" "抖动" "连通率"
    echo "------------------------------------------------------------"

    local rank=1
    local BEST_IP=""
    local BEST_COLO=""
    local BEST_MED=""
    local BEST_JIT=""

    while read -r med ip colo avg jit runs; do
        local colo_name=$(get_colo_name "$colo")
        if [ "$rank" -eq 1 ]; then
            BEST_IP="$ip"
            BEST_COLO="$colo_name"
            BEST_MED="$med"
            BEST_JIT="$jit"
        fi
        printf "%-6s %-16s %-26s %-10s %-10s %-10s\n" "#$rank" "$ip" "$colo_name" "${med} ms" "${jit} ms" "${runs}/10"
        rank=$((rank + 1))
    done < <(sort -n -k1 "$FINAL_FILE")
    rm -f "$FINAL_FILE"

    echo "============================================================"
    echo -e "🔥 本地网络综合最优推荐: \033[32m$BEST_IP\033[0m"
    echo -e "📍 接入机房及地区:       \033[36m$BEST_COLO\033[0m"
    echo -e "⚡ 稳态中位数延迟:       \033[32m${BEST_MED} ms\033[0m (网络抖动: ${BEST_JIT} ms)"
    echo "============================================================"

    # 推送引导交互
    while true; do
        echo ""
        echo "【推送操作引导】"
        echo " [1] 一键将最优 IP ($BEST_IP | $BEST_COLO) 推送至服务器"
        echo " [2] 自定义输入要推送的 IP"
        echo " [3] 重新全量测速"
        echo " [0] 退出脚本"
        echo ""
        read -p "请选择操作模式 (默认: 1): " choice
        choice=${choice:-1}

        case "$choice" in
            0)
                echo "已退出。"
                exit 0
                ;;
            3)
                main_speedtest
                return
                ;;
            1)
                TARGET_IP="$BEST_IP"
                ;;
            2)
                read -p "请输入要推送的 Cloudflare IP: " TARGET_IP
                if [ -z "$TARGET_IP" ]; then
                    echo -e "\033[33m警告: IP 不能为空！\033[0m"
                    continue
                fi
                ;;
            *)
                echo -e "\033[33m无效选择，请重新输入。\033[0m"
                continue
                ;;
        esac

        read -s -p "请输入推送操作口令: " PUSH_PWD
        echo ""
        if [ -z "$PUSH_PWD" ]; then
            echo -e "\033[31m错误: 口令不能为空！\033[0m"
            continue
        fi

        echo -e "\n⏳ 正在向服务器推送 IP: $TARGET_IP ..."
        local payload=$(printf '{"ip":"%s","password":"%s"}' "$TARGET_IP" "$PUSH_PWD")
        local resp=$(curl -s -X POST "$PUSH_API_URL" \
            -H "Content-Type: application/json" \
            -d "$payload" \
            --connect-timeout 10)

        local success=$(echo "$resp" | grep -o '"success":true' || true)
        local msg=$(echo "$resp" | sed -n 's/.*"msg":"\([^"]*\)".*/\1/p')

        if [ -n "$success" ]; then
            echo "============================================================"
            echo -e "🎉 \033[32m[推送成功] ${msg:-已更新 Cloudflare 与 VPS 配置}\033[0m"
            echo -e "当前线上生效 IP: \033[32m$TARGET_IP\033[0m"
            echo "============================================================"
            break
        else
            echo "============================================================"
            echo -e "❌ \033[31m[推送失败] ${msg:-口令错误或服务器异常}\033[0m"
            echo "请检查口令后重试，或选择重新设置。"
            echo "============================================================"
        fi
    done
}

main_speedtest
