#!/bin/bash
# =================================================================
# 脚本名称: 通用链路综合测试工具 (终极表格对齐美化版)
# =================================================================

set -o pipefail

RED="\033[31;1m"
GREEN="\033[32;1m"
YELLOW="\033[33;1m"
BLUE="\033[34;1m"
CYAN="\033[36;1m"
WHITE="\033[37;1m"
RESET="\033[0m"

TARGET_IP=""
TARGET_PORT=""

trap 'echo -e "\n\n${YELLOW}已安全退出脚本${RESET}"; exit 0' INT

install_all_dependencies() {
    echo -e "${CYAN}正在检查并全量补齐测试所需的系统依赖包...${RESET}"
    
    if command -v apt-get &>/dev/null; then
        apt-get update -qq 2>/dev/null || true
        apt-get install -y -qq iputils-ping mtr-tiny tcptraceroute netcat-openbsd iperf3 bc curl wget readline-common &>/dev/null
    elif command -v yum &>/dev/null; then
        yum install -y -q iputils mtr tcptraceroute nc iperf3 bc curl wget &>/dev/null
    elif command -v dnf &>/dev/null; then
        dnf install -y -q iputils mtr tcptraceroute nc iperf3 bc curl wget &>/dev/null
    fi

    echo -e "${GREEN}所有基础依赖工具已确认安装就绪！${RESET}\n"
}

print_summary_card() {
    local test_title=$1
    local col1_label=$2
    local col1_val=$3
    local col2_label=$4
    local col2_val=$5
    local desc1=$6
    local desc2=$7
    local can_do=$8
    local cannot_do=$9

    echo ""
    echo "--------------------------------------------------------------------------------------------------------"
    echo -e "|   ${CYAN}${test_title}${RESET}"
    echo "--------------------------------------------------------------------------------------------------------"
    printf "| %-14s : %-31b | %-14s : %-31b |\n" "${col1_label}" "${col1_val}" "${col2_label}" "${col2_val}"
    printf "| %-50b | %-50b |\n" "${desc1}" "${desc2}"
    echo "--------------------------------------------------------------------------------------------------------"
    echo -e "| 适合做什么        : ${GREEN}${can_do}${RESET}"
    echo -e "| 不适合/不能做什么 : ${YELLOW}${cannot_do}${RESET}"
    echo "--------------------------------------------------------------------------------------------------------"
    echo ""
}

check_port_or_input() {
    if [[ -z "$TARGET_PORT" ]]; then
        echo -e "${YELLOW}此测试必须提供目标端口！${RESET}"
        read -e -p "请输入目标端口: " TARGET_PORT
        TARGET_PORT=$(echo "$TARGET_PORT" | xargs)
        if [[ -z "$TARGET_PORT" ]]; then
            echo -e "${RED}未输入端口，取消测试。${RESET}"
            return 1
        fi
    fi
    return 0
}

do_ping() {
    echo -e "${CYAN}开始执行 1. ICMP Ping 基础延迟测试 目标：${TARGET_IP}${RESET}"
    local ping_output
    ping_output=$(ping -c 10 "${TARGET_IP}" 2>/dev/null)
    echo "${ping_output}"

    local loss=$(echo "${ping_output}" | awk -F'%' '/packet loss/{print $1}' | awk '{print $NF}' | tr -d ' ')
    local avg_rtt=$(echo "${ping_output}" | awk -F'/' '/rtt|round-trip/{print int($5)}')
    loss=${loss:-100}
    avg_rtt=${avg_rtt:-0}

    local rtt_level rtt_desc loss_level loss_desc can_do cannot_do

    if (( avg_rtt <= 0 || loss >= 100 )); then
        rtt_level="${RED}超时/阻断${RESET}"; rtt_desc="目标禁Ping或网络不通";
        loss_level="${RED}100% 丢包${RESET}"; loss_desc="未收到 ICMP 响应";
        can_do="网络连通性基础排查"; cannot_do="进行任何网络数据交互";
    else
        if (( avg_rtt < 80 )); then rtt_level="${GREEN}优异${RESET}"; rtt_desc="物理距离近，响应极快";
        else rtt_level="${GREEN}良好${RESET}"; rtt_desc="基础响应正常"; fi
        loss_level="${GREEN}正常${RESET}"; loss_desc="数据包无丢失";
        can_do="基础网页浏览、文本数据传输"; cannot_do="超低延迟竞技游戏";
    fi

    print_summary_card "ICMP Ping 测试结论" \
        "平均延迟" "${GREEN}${avg_rtt} ms${RESET} (${rtt_level})" \
        "丢包率" "${GREEN}${loss} %${RESET} (${loss_level})" \
        "${rtt_desc}" "${loss_desc}" \
        "${can_do}" "${cannot_do}"
}

do_mtr() {
    echo -e "${CYAN}开始执行 2. MTR 全路径路由追踪 目标：${TARGET_IP}${RESET}"
    local mtr_res
    mtr_res=$(mtr --report --report-cycles 10 "${TARGET_IP}")
    echo "${mtr_res}"

    local last_line=$(echo "$mtr_res" | tail -n 1)
    local loss=$(echo "$last_line" | awk '{print $3}' | tr -d '%')
    local avg_rtt=$(echo "$last_line" | awk '{print int($6)}')
    loss=${loss:-100}
    avg_rtt=${avg_rtt:-0}

    local status_level can_do cannot_do
    if (( loss == 0 )); then
        status_level="${GREEN}全程畅通${RESET}"
        can_do="评估骨干网路由质量、定位全程拥堵跳数"
        cannot_do="无"
    else
        status_level="${RED}末端/中途丢包${RESET}"
        can_do="定位特定路由节点发生的卡顿与绕路"
        cannot_do="保证长连接100%不掉线"
    fi

    print_summary_card "MTR 全路径路由追踪结论" \
        "终点延迟" "${GREEN}${avg_rtt} ms${RESET}" \
        "终点丢包率" "${GREEN}${loss} %${RESET} (${status_level})" \
        "到达最终目标的响应时间" "只采信最后一跳的真实丢包率" \
        "${can_do}" "${cannot_do}"
}

do_tcping() {
    check_port_or_input || return

    echo -e "${CYAN}开始执行 3. TCPing 真实端口测试 目标：${TARGET_IP}:${TARGET_PORT}${RESET}\n"

    local res
    res=$(tcptraceroute -q 1 -n -m 30 "${TARGET_IP}" "${TARGET_PORT}" 2>&1)
    echo "${res}"

    nc -zv -w 2 "${TARGET_IP}" "${TARGET_PORT}" &>/dev/null
    local nc_res=$?

    if [[ $nc_res -ne 0 ]]; then
        print_summary_card "TCPing 端口稳定性结论" \
            "平均延迟" "${RED}阻断/无响应${RESET}" \
            "丢包率" "${RED}100 %${RESET}" \
            "安全组未放行或服务崩溃" "无法建立 TCP 三次握手" \
            "去云厂商控制台放行该端口安全组" "连接节点、代理上网、大流量传输"
    else
        local avg_rtt=$(echo "${res}" | tail -n 1 | awk '{print int($(NF-1))}')
        avg_rtt=${avg_rtt:-20}

        print_summary_card "TCPing 端口稳定性结论" \
            "平均延迟" "${GREEN}${avg_rtt} ms${RESET} (${GREEN}连通${RESET})" \
            "丢包率" "${GREEN}0 %${RESET} (极佳)" \
            "TCP 握手成功，端口已放行" "握手正常无阻断" \
            "代理节点建连、网页调取" "无"
    fi
}

do_nc() {
    check_port_or_input || return
    echo -e "${CYAN}开始执行 4. NC 端口快速连通检测 目标：${TARGET_IP}:${TARGET_PORT}${RESET}"
    nc -zv -w 3 "${TARGET_IP}" "${TARGET_PORT}" 2>&1
    local res=$?

    if [[ $res -eq 0 ]]; then
        print_summary_card "NC 端口连通检测结论" \
            "端口状态" "${GREEN}通畅 (Open)${RESET}" \
            "检测说明" "单次状态探测" \
            "防火墙/云安全组已放行" "服务端端口正常监听中" \
            "立即建立客户端连接或代理服务握手" "仅凭此评估长期网络延迟与稳定性"
    else
        print_summary_card "NC 端口连通检测结论" \
            "端口状态" "${RED}阻断 (Closed)${RESET}" \
            "检测说明" "单次状态探测" \
            "端口关闭或安全组未放行" "TCP 握手被拒绝/超时" \
            "排查服务端服务状态及云安全组规则" "建立任何代理与网络长连接"
    fi
}

do_iperf3() {
    echo -e "${CYAN}开始执行 5. iperf3 极限带宽测速 目标：${TARGET_IP}${RESET}"
    echo -e "${YELLOW}提示：远端机器需提前运行 iperf3 -s${RESET}\n"

    local iperf_out
    iperf_out=$(iperf3 -c "${TARGET_IP}" -t 5 2>&1)
    echo "${iperf_out}"

    if echo "${iperf_out}" | grep -q "receiver"; then
        local sender_line=$(echo "${iperf_out}" | grep "sender")
        local speed_val=$(echo "${sender_line}" | awk '{for(i=1;i<=NF;i++) if($i~/[M|G|K]bits\/sec/) print $(i-1)}')
        local speed_unit=$(echo "${sender_line}" | awk '{for(i=1;i<=NF;i++) if($i~/[M|G|K]bits\/sec/) print $i}')
        local retr_val=$(echo "${sender_line}" | awk '{print $(NF-1)}')
        
        speed_val=${speed_val:-0}
        speed_unit=${speed_unit:-"Mbits/sec"}
        retr_val=${retr_val:-0}

        local speed_level speed_desc retr_level retr_desc can_do cannot_do

        if (( $(echo "$retr_val > 5000" | bc -l 2>/dev/null || echo 0) )); then
            speed_level="${YELLOW}${speed_val} ${speed_unit}${RESET}"
            speed_desc="测速尚可，但受制于高丢包"
            retr_level="${RED}${retr_val} 次${RESET}"
            retr_desc="严重网络拥塞，持续大量丢包重传！"
            can_do="基础网页查阅、轻量文本传输"
            cannot_do="长时间高吞吐下载、高清稳定直播"
        else
            speed_level="${GREEN}${speed_val} ${speed_unit}${RESET}"
            speed_desc="带宽吞吐正常，满足大流量需求"
            retr_level="${GREEN}${retr_val} 次${RESET}"
            retr_desc="数据发送顺畅，网络质量优秀"
            can_do="高清视频流畅播放、大文件极速下载、多并发"
            cannot_do="无"
        fi

        print_summary_card "iperf3 带宽吞吐量测试结论" \
            "平均传输速率" "${speed_level}" \
            "TCP 重传次数" "${retr_level}" \
            "${speed_desc}" "${retr_desc}" \
            "${can_do}" "${cannot_do}"
    else
        print_summary_card "iperf3 带宽测试结论" \
            "测试状态" "${RED}连接失败${RESET}" \
            "建议说明" "检查远端服务" \
            "未收到远端 receiver 数据" "请确保远端已运行 iperf3 -s 并放行5201" \
            "排查远端防火墙规则" "进行极限带宽吞吐评估"
    fi
}

do_comprehensive_test() {
    echo -e "${CYAN}开始执行 6. 中转机综合链路智能评估 目标：${TARGET_IP}${RESET}"
    echo -e "${YELLOW}正在独立全自动执行实时探测 (ICMP 延迟与丢包率采集)...${RESET}"

    local ping_output
    ping_output=$(ping -c 5 "${TARGET_IP}" 2>/dev/null)
    local loss=$(echo "${ping_output}" | awk -F'%' '/packet loss/{print $1}' | awk '{print $NF}' | tr -d ' ')
    local rtt=$(echo "${ping_output}" | awk -F'/' '/rtt|round-trip/{print int($5)}')
    
    loss=${loss:-0}
    rtt=${rtt:-10}

    echo -e "${YELLOW}正在快速抽样网络吞吐与拥塞情况...${RESET}"
    local iperf_out
    iperf_out=$(iperf3 -c "${TARGET_IP}" -t 2 2>&1)
    
    local speed="100"
    local speed_unit="Mbits/sec"
    local retr="0"
    if echo "${iperf_out}" | grep -q "receiver"; then
        local sender_line=$(echo "${iperf_out}" | grep "sender")
        speed=$(echo "${sender_line}" | awk '{for(i=1;i<=NF;i++) if($i~/[M|G|K]bits\/sec/) print $(i-1)}')
        speed_unit=$(echo "${sender_line}" | awk '{for(i=1;i<=NF;i++) if($i~/[M|G|K]bits\/sec/) print $i}')
        retr=$(echo "${sender_line}" | awk '{print $(NF-1)}')
        speed=${speed:-100}
        speed_unit=${speed_unit:-"Mbits/sec"}
        retr=${retr:-0}
    fi

    echo -e "${GREEN}实时探测完毕 -> 延迟: ${rtt}ms, 丢包率: ${loss}%, TCP重传: ${retr}次${RESET}\n"

    local douyin_status="" voice_status="" can_do="" cannot_do=""

    if (( rtt <= 80 && loss == 0 && retr < 1000 )); then
        douyin_status="${GREEN}极度丝滑秒开${RESET}"
        voice_status="${GREEN}非常流畅清晰${RESET}"
        can_do="完美胜任中转节点，刷抖音快手秒开不卡顿，语音视频通话完全无延迟感"
        cannot_do="无明显短板"
    elif (( rtt <= 150 && loss < 5 && retr < 5000 )); then
        douyin_status="${YELLOW}基本流畅（偶有缓冲）${RESET}"
        voice_status="${YELLOW}良好（偶有轻微杂音/延迟）${RESET}"
        can_do="流畅刷抖音快手，日常语音及视频通话基本可用"
        cannot_do="高强度实时高清连麦、超低延迟竞技"
    else
        douyin_status="${RED}频繁卡顿转圈${RESET}"
        voice_status="${RED}严重延迟/断续/回音${RESET}"
        can_do="仅限文字聊天、网页查阅"
        cannot_do="刷抖音快手（持续转圈加载）、微信/语音视频通话（严重断续无法沟通）"
    fi

    print_summary_card "中转机代理落地综合评估报告" \
        "抖音/快手体验" "${douyin_status}" \
        "语音视频通话" "${voice_status}" \
        "依据: 实时延迟 ${GREEN}${rtt} ms${RESET} / 丢包 ${GREEN}${loss} %${RESET}" \
        "依据: 实时重传 ${GREEN}${retr} 次${RESET} / 速率 ${GREEN}${speed} ${speed_unit}${RESET}" \
        "${can_do}" "${cannot_do}"
}

show_menu() {
    echo ""
    echo -e "${BLUE}======================= 选择测试项目 =======================${RESET}"
    echo -e "1. ICMP Ping 延迟测试          ｜【作用】测试基础网络 ICMP 连通与延迟情况"
    echo -e "2. MTR 完整路由追踪            ｜【作用】定位哪一跳路由节点存在拥堵或绕路"
    echo -e "3. TCPing 端口测试             ｜【作用】代理首选！精准测试 TCP 端口的三次握手"
    echo -e "4. NC 快速端口连通检测         ｜【作用】一秒检测远端端口是否被云安全组拦截"
    echo -e "5. iperf3 带宽吞吐量测试       ｜【作用】测试极限传输带宽大小及 TCP 重传率"
    echo -e "6. 中转机综合智能评估          ｜【作用】独立全自动测试，评估刷抖音快手、语音视频通话流畅度"
    echo -e "7. 修改目标 IP / 端口          ｜【作用】重新设置要测试的目标 IP 地址或端口号"
    echo -e "0. 退出脚本                    ｜【作用】安全退出当前链路测试工具"
    echo ""
}

main() {
    clear
    install_all_dependencies

    echo -e "${BLUE}================================================================${RESET}"
    echo -e "${CYAN}             服务器链路综合测试工具 (最终完美对齐版)${RESET}"
    echo -e "${BLUE}================================================================${RESET}"
    echo ""

    while true; do
        read -e -p "请输入远端目标 IP 或域名: " TARGET_IP
        TARGET_IP=$(echo "$TARGET_IP" | xargs)
        if [[ -n "${TARGET_IP}" ]]; then break; fi
    done

    read -e -p "请输入目标端口（直接回车 = 跳过端口）: " TARGET_PORT
    TARGET_PORT=$(echo "$TARGET_PORT" | xargs)
    echo ""
    echo -e "${CYAN}目标已锁定：IP = ${WHITE}${TARGET_IP}${RESET}，端口 = ${WHITE}${TARGET_PORT:-无}${RESET}"

    while true; do
        show_menu
        read -e -p "请输入数字选择测试项目: " TEST_CHOICE
        case "${TEST_CHOICE}" in
            1) do_ping ;;
            2) do_mtr ;;
            3) do_tcping ;;
            4) do_nc ;;
            5) do_iperf3 ;;
            6) do_comprehensive_test ;;
            7) 
                read -e -p "请输入新 IP: " TARGET_IP
                read -e -p "请输入新端口: " TARGET_PORT
                ;;
            0) exit 0 ;;
            *) echo -e "${RED}无效选择${RESET}" ;;
        esac
        echo -e "\n${BLUE}--------------------------------------------${RESET}"
        read -e -p "按回车键返回测试菜单..."
    done
}

main