#!/bin/bash
#
# proxy-check.sh - 代理流量与身份暴露综合检测脚本 (Claude 专用版 v2.0)
# 融合了网络底层排查 (DNS/TUN/ENV/ASN) 与业务层风控检测 (Claude连通性/身份泄露)

set -u

[[ "$(uname)" == "Darwin" ]] || { echo "This script requires macOS."; exit 1; }

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color

# 结果变量 (全局变量，供各函数共享)
EXIT_IP=""
EXIT_LOCATION=""
EXIT_COUNTRY=""
CLAUDE_ACCESSIBLE=false
CLAUDE_SEES_CN=false
IPINFO_RESPONSE=""

# 检测结果 (供 final_report 使用)
DNS_RESULT=0
TUN_RESULT=0
ENV_RESULT=0
FIX_SUGGESTIONS=()

print_header() {
    echo -e "\n${CYAN}========================================${NC}"
    echo -e "${CYAN} $1 ${NC}"
    echo -e "${CYAN}========================================${NC}"
}

check_exit_ip() {
    echo -e "\n[1/7] 检测出口 IP 位置(多源校验)..."
    
    local sources=(
        "https://ipinfo.io/json"
        "https://api.ip.sb/geoip"
        "https://ifconfig.me/all.json"
    )
    
    local ip_results=()
    local country_results=()
    local city_results=()
    local success=0
    
    for url in "${sources[@]}"; do
        echo -n "      查询 $url ... "
        local response
        response=$(curl -s --connect-timeout 5 --max-time 10 "$url" 2>/dev/null)

        # Cache the first successful ipinfo.io response for reuse in check_asn()
        if [ -z "$IPINFO_RESPONSE" ] && [ "$url" = "https://ipinfo.io/json" ] && [ -n "$response" ]; then
            IPINFO_RESPONSE="$response"
        fi

        if [ -n "$response" ] && echo "$response" | grep -q "{"; then
            local ip city country
            ip=$(echo "$response" | python3 -c "import sys,json; print(json.load(sys.stdin).get('ip',''))" 2>/dev/null)
            city=$(echo "$response" | python3 -c "import sys,json; print(json.load(sys.stdin).get('city',''))" 2>/dev/null)
            country=$(echo "$response" | python3 -c "import sys,json; print(json.load(sys.stdin).get('country',''))" 2>/dev/null)
            
            if [ -n "$ip" ]; then
                ip_results+=("$ip")
                country_results+=("$country")
                city_results+=("$city")
                echo "$ip ($city, $country)"
                ((success++))
            else
                echo "解析失败"
            fi
        else
            echo "请求失败"
        fi
    done
    
    # 一致性校验
    if [ $success -ge 2 ]; then
        local unique_ips
        unique_ips=$(printf '%s\n' "${ip_results[@]}" | sort -u | wc -l | tr -d ' ')
        if [ "$unique_ips" -eq 1 ]; then
            EXIT_IP="${ip_results[0]}"
            EXIT_COUNTRY="${country_results[0]}"
            EXIT_LOCATION="${city_results[0]}, ${country_results[0]}"
            echo -e "      ${GREEN}→ 多源 IP 一致: $EXIT_IP${NC}"
        else
            echo -e "      ${YELLOW}→ 警告: 多源 IP 不一致，可能被劫持${NC}"
            EXIT_IP="${ip_results[0]}"
            EXIT_COUNTRY="${country_results[0]}"
            EXIT_LOCATION="${city_results[0]}, ${country_results[0]}"
        fi
    elif [ $success -eq 1 ]; then
        EXIT_IP="${ip_results[0]}"
        EXIT_COUNTRY="${country_results[0]}"
        EXIT_LOCATION="${city_results[0]}, ${country_results[0]}"
        echo -e "      ${YELLOW}→ 仅单源成功，结果可信度较低${NC}"
    else
        EXIT_LOCATION="未知"
    fi
    
    if [ "$EXIT_COUNTRY" = "CN" ]; then
        echo -e "      ${RED}→ 出口是中国大陆，流量未代理${NC}"
        echo -e "      ${YELLOW}  💡 修复建议: 请检查代理软件是否开启，并切换到非中国大陆节点。${NC}"
        FIX_SUGGESTIONS+=("请检查代理软件是否开启，并切换到非中国大陆节点。")
        return 1
    elif [ -n "$EXIT_IP" ]; then
        echo -e "      ${GREEN}→ 出口是非中国大陆节点${NC}"
        return 0
    else
        echo -e "      ${RED}→ 无法获取出口 IP${NC}"
        echo -e "      ${YELLOW}  💡 修复建议: 请检查本机网络连接，或代理软件是否拦截了正常外网请求。${NC}"
        FIX_SUGGESTIONS+=("请检查本机网络连接，或代理软件是否拦截了正常外网请求。")
        return 1
    fi
}

check_dns_leak() {
    echo -e "\n[2/7] 检测 DNS 泄露..."
    
    local dns_servers
    dns_servers=$(scutil --dns 2>/dev/null | grep 'nameserver\[[0-9]*\]' | awk '{print $3}' | sort -u | head -5)
    
    echo "      当前 DNS 服务器:"
    if [ -z "$dns_servers" ]; then
        echo "        (无法获取)"
    else
        echo "$dns_servers" | while read -r dns; do
            echo "        - $dns"
        done
    fi
    
    if echo "$dns_servers" | grep -qE "114\.114|223\.5\.5|223\.6\.6|119\.29\.29|180\.76\.76"; then
        echo -e "      ${RED}→ 检测到中国大陆 DNS，存在严重泄露风险${NC}"
        echo -e "      ${YELLOW}  💡 修复建议: 进入 macOS 设置 -> 网络 -> Wi-Fi -> 详细信息 -> DNS，删除国内 DNS，留空或改为 8.8.8.8。${NC}"
        FIX_SUGGESTIONS+=("进入 macOS 设置 -> 网络 -> Wi-Fi -> 详细信息 -> DNS，删除国内 DNS，留空或改为 8.8.8.8。")
        DNS_RESULT=1
        return 1
    elif echo "$dns_servers" | grep -qE "198\.18\.|127\.0\.0\.1|172\.19\."; then
        echo -e "      ${GREEN}→ 检测到代理软件接管的 Fake-IP/本地 DNS${NC}"
        DNS_RESULT=0
        return 0
    elif echo "$dns_servers" | grep -qE "^(192\.168\.|10\.|172\.(1[6-9]|2[0-9]|3[0-1])\.)"; then
        echo -e "      ${YELLOW}→ 检测到路由器网关 DNS (如果不透明代理则易泄露)${NC}"
        echo -e "      ${YELLOW}  💡 修复建议: 如果路由器无翻墙功能，建议将电脑 DNS 手动指定为 8.8.8.8，防止局域网劫持。${NC}"
        FIX_SUGGESTIONS+=("如果路由器无翻墙功能，建议将电脑 DNS 手动指定为 8.8.8.8，防止局域网劫持。")
        DNS_RESULT=1
        return 1
    else
        echo -e "      ${GREEN}→ DNS 看起来非国内公共 DNS${NC}"
        DNS_RESULT=0
        return 0
    fi
}

check_tun_route() {
    echo -e "\n[3/7] 检测 TUN 模式与路由..."
    
    local tun_detected=false
    local route_via_tun=false
    
    if ifconfig 2>/dev/null | grep -q "utun"; then
        echo -e "      ${GREEN}• 检测到 utun 接口 (TUN 模式可能开启)${NC}"
        tun_detected=true
    else
        echo -e "      ${YELLOW}• 未检测到 utun 接口${NC}"
    fi
    
    # 使用 route get 测试公网 IP (8.8.8.8) 的真实走向，以兼容 Clash 的拆分路由
    local external_route
    external_route=$(route get 8.8.8.8 2>/dev/null | grep "interface:")
    
    if [ -n "$external_route" ]; then
        local interface_name=$(echo "$external_route" | awk '{print $2}')
        echo "      外部路由 (8.8.8.8) 接口: $interface_name"
        
        if echo "$interface_name" | grep -q "utun"; then
            echo -e "      ${GREEN}• 外部流量已走 TUN ($interface_name)${NC}"
            route_via_tun=true
        else
            echo -e "      ${YELLOW}• 外部流量未走 TUN (物理网卡: $interface_name)${NC}"
        fi
    fi
    
    if [ "$tun_detected" = true ] && [ "$route_via_tun" = true ]; then
        echo -e "      ${GREEN}→ TUN 模式配置正确 (全局流量接管)${NC}"
        TUN_RESULT=0
        return 0
    elif [ "$tun_detected" = true ]; then
        echo -e "      ${YELLOW}→ TUN 接口存在但路由未配置${NC}"
        echo -e "      ${YELLOW}  💡 修复建议: 尝试赋予代理软件管理员权限并重启，或重新开关 TUN 模式。${NC}"
        FIX_SUGGESTIONS+=("尝试赋予代理软件管理员权限并重启，或重新开关 TUN 模式。")
        TUN_RESULT=1
        return 1
    else
        echo -e "      ${YELLOW}→ 未开启 TUN 模式，可能存在底层直连泄露${NC}"
        echo -e "      ${YELLOW}  💡 修复建议: 打开代理软件，找到并开启「TUN 模式」或「增强模式」。${NC}"
        FIX_SUGGESTIONS+=("打开代理软件，找到并开启「TUN 模式」或「增强模式」。")
        TUN_RESULT=1
        return 1
    fi
}

check_env_proxy() {
    echo -e "\n[4/7] 检测终端环境变量代理..."
    
    local proxy_envs=("http_proxy" "https_proxy" "all_proxy" "HTTP_PROXY" "HTTPS_PROXY" "ALL_PROXY" "no_proxy" "NO_PROXY")
    local found_env=false
    
    for env in "${proxy_envs[@]}"; do
        local val=$(printenv "$env" 2>/dev/null)
        if [ -n "$val" ]; then
            echo "      • $env = $val"
            found_env=true
        fi
    done
    
    # 根据 TUN 模式的状态进行前置条件判断
    if [ $TUN_RESULT -eq 0 ]; then
        # 场景 A: 已经开启了 TUN 模式 (底层已接管)
        if [ "$found_env" = true ]; then
            echo -e "      ${RED}→ 警告：已开启 TUN 模式，但终端仍设置了环境变量${NC}"
            echo -e "      ${YELLOW}  这会引发双重代理冲突和 DNS 泄露问题！${NC}"
            echo -e "      ${YELLOW}  💡 修复建议: 终端执行 unset_proxy${NC}"
            FIX_SUGGESTIONS+=("终端执行 unset_proxy")
            ENV_RESULT=1
            return 1
        else
            echo -e "      ${GREEN}→ 完美：已开启 TUN 模式，且终端未设置环境变量 (干净直通)${NC}"
            ENV_RESULT=0
            return 0
        fi
    else
        # 场景 B: 未开启 TUN 模式 (底层未接管，必须靠环境变量)
        if [ "$found_env" = true ]; then
            echo -e "      ${GREEN}→ 当前终端已设置代理环境变量 (应用层接管)${NC}"
            local filtered=()
            for sug in "${FIX_SUGGESTIONS[@]}"; do
                if ! echo "$sug" | grep -qi "tun\|增强模式"; then
                    filtered+=("$sug")
                fi
            done
            FIX_SUGGESTIONS=("${filtered[@]}")
            ENV_RESULT=0
            return 0
        else
            echo -e "      ${RED}→ 致命：未开启 TUN 模式，且终端未设置代理环境变量！${NC}"
            echo -e "      ${YELLOW}  终端里的 curl、git 等命令将直接裸奔直连！${NC}"
            echo -e "      ${YELLOW}  💡 修复建议: 终端执行 export https_proxy=http://127.0.0.1:端口号 http_proxy=http://127.0.0.1:端口号${NC}"
            FIX_SUGGESTIONS+=("终端执行 export https_proxy=http://127.0.0.1:端口号 http_proxy=http://127.0.0.1:端口号")
            ENV_RESULT=1
            return 1
        fi
    fi
}

check_asn() {
    echo -e "\n[5/7] 检测 ASN/运营商信息..."

    local response org
    if [ -n "$IPINFO_RESPONSE" ]; then
        response="$IPINFO_RESPONSE"
    else
        response=$(curl -s --connect-timeout 5 --max-time 10 "https://ipinfo.io/json" 2>/dev/null)
    fi

    if [ -n "$response" ]; then
        org=$(echo "$response" | python3 -c "import sys,json; print(json.load(sys.stdin).get('org',''))" 2>/dev/null)
        
        if [ -n "$org" ]; then
            echo "      运营商: $org"
        fi
        
        if echo "$org" | grep -qiE "china|chinanet|telecom|unicom|mobile|cmcc|ctnet|cunicom|aliyun|tencent|baidu"; then
            echo -e "      ${RED}→ ASN 属于中国大陆运营商/大厂${NC}"
            echo -e "      ${YELLOW}  💡 修复建议: Claude 风控极严，此节点极大概率被拦截。请切换到原生海外节点。${NC}"
            FIX_SUGGESTIONS+=("Claude 风控极严，此节点极大概率被拦截。请切换到原生海外节点。")
            CLAUDE_SEES_CN=true
            return 1
        else
            echo -e "      ${GREEN}→ ASN 非中国大陆运营商${NC}"
            return 0
        fi
    else
        echo -e "      ${YELLOW}→ 无法获取 ASN 信息${NC}"
        return 0
    fi
}

check_claude_access() {
    echo -e "\n[6/7] 检测 Claude 各平台可访问性..."
    
    local accessible_count=0
    local total_tests=3
    local forbidden_patterns="unavailable|FORBIDDEN|region.*restrict|not.*available|access.*denied|App unavailable in region"
    
    echo -ne "      Claude CLI/API ... "
    local api_response api_code api_ip
    api_response=$(curl -sL --connect-timeout 5 --max-time 10 "https://api.anthropic.com" 2>/dev/null)
    api_code=$(curl -sL --connect-timeout 5 --max-time 10 "https://api.anthropic.com" -o /dev/null -w "%{http_code}" 2>/dev/null)
    api_ip=$(curl -sL --connect-timeout 5 --max-time 10 "https://api.anthropic.com" -o /dev/null -w "%{remote_ip}" 2>/dev/null)

    if [ "$api_code" != "000" ] && ! echo "$api_response" | grep -qiE "$forbidden_patterns"; then
        echo -e "${GREEN}可访问${NC} (HTTP $api_code, IP: $api_ip)"
        ((accessible_count++))
    else
        echo -e "${RED}不可访问${NC}"
    fi

    echo -ne "      Claude.app ... "
    local claude_response claude_final
    claude_response=$(curl -sL --connect-timeout 5 --max-time 10 "https://claude.ai" 2>/dev/null)
    claude_final=$(curl -sL --connect-timeout 5 --max-time 10 -o /dev/null -w "%{url_effective}" "https://claude.ai" 2>/dev/null)

    if echo "$claude_final" | grep -qi "cdn-cgi\|challenge"; then
        echo -e "${RED}被 Cloudflare 拦截${NC}"
    elif echo "$claude_response" | grep -qiE "$forbidden_patterns"; then
        echo -e "${RED}不可访问 (区域限制)${NC}"
    elif [ -n "$claude_response" ]; then
        echo -e "${GREEN}可访问${NC}"
        ((accessible_count++))
    else
        echo -e "${RED}不可访问${NC}"
    fi

    echo -ne "      Claude Web ... "
    local chat_response chat_final
    chat_response=$(curl -sL --connect-timeout 5 --max-time 10 "https://claude.ai/chat" 2>/dev/null)
    chat_final=$(curl -sL --connect-timeout 5 --max-time 10 -o /dev/null -w "%{url_effective}" "https://claude.ai/chat" 2>/dev/null)
    
    if echo "$chat_final" | grep -qi "unavailable"; then
        echo -e "${RED}区域限制页面${NC}"
    elif echo "$chat_response" | grep -qiE "$forbidden_patterns"; then
        echo -e "${RED}不可访问 (区域限制)${NC}"
    elif [ -n "$chat_response" ]; then
        echo -e "${GREEN}可访问${NC}"
        ((accessible_count++))
    else
        echo -e "${RED}不可访问${NC}"
    fi
    
    if [ $accessible_count -eq $total_tests ]; then
        CLAUDE_ACCESSIBLE=true
        echo -e "      ${GREEN}→ 所有 Claude 平台均可访问${NC}"
        return 0
    else
        CLAUDE_ACCESSIBLE=false
        echo -e "      ${RED}→ 部分或全部平台不可访问 ($accessible_count/$total_tests)${NC}"
        if [ $accessible_count -eq 0 ]; then
            echo -e "      ${YELLOW}  💡 修复建议: 当前节点 IP 已被 Claude 封锁，请切换节点后重试。${NC}"
            FIX_SUGGESTIONS+=("当前节点 IP 已被 Claude 封锁，请切换节点后重试。")
        fi
        return 1
    fi
}

check_identity_leak() {
    echo -e "\n[7/7] 系统身份暴露风险评估..."
    
    local risks=0
    
    if [ "$EXIT_COUNTRY" = "CN" ]; then
        echo -e "      ${RED}• 出口 IP 显示中国大陆${NC}"
        CLAUDE_SEES_CN=true
        ((risks++))
    else
        echo -e "      ${GREEN}• 出口 IP 非中国大陆${NC}"
    fi
    
    if [ "$CLAUDE_SEES_CN" = true ] && [ "$EXIT_COUNTRY" != "CN" ]; then
        echo -e "      ${RED}• ASN 显示中国大陆运营商${NC}"
        ((risks++))
    fi
    
    local lang
    lang=$(defaults read -g AppleLanguages 2>/dev/null | head -1 | tr -d '("' | xargs)
    if echo "$lang" | grep -qi "zh-Hans\|zh-CN"; then
        echo -e "      ${YELLOW}• 系统语言是简体中文 (可能被识别)${NC}"
        ((risks++))
    else
        echo -e "      ${GREEN}• 系统语言非简体中文${NC}"
    fi
    
    local tz_name
    tz_name=$(readlink /etc/localtime 2>/dev/null | grep -oE "timezone/[a-zA-Z0-9_/]+" | cut -d'/' -f2-)
    if [ -z "$tz_name" ] || [ "$tz_name" = "administrator" ]; then
        tz_name=$(systemsetup -gettimezone 2>/dev/null | awk '{print $3}')
    fi
    if [ -z "$tz_name" ]; then
        tz_name=$(date +%Z)
    fi
    
    if echo "$tz_name" | grep -qE "Shanghai|Chongqing|Harbin|Urumqi|Beijing|PRC"; then
        echo -e "      ${RED}• 时区是中国大陆特定时区 ($tz_name)${NC}"
        ((risks++))
    elif echo "$tz_name" | grep -qE "Singapore|Kuala_Lumpur|Manila|Tokyo|Seoul"; then
        echo -e "      ${GREEN}• 时区是亚洲其他地区 ($tz_name)${NC}"
    elif [ -n "$tz_name" ]; then
        echo -e "      ${GREEN}• 时区非中国大陆 ($tz_name)${NC}"
    else
        echo -e "      ${YELLOW}• 无法确定时区${NC}"
    fi
    
    if [ $risks -eq 0 ]; then
        echo -e "      ${GREEN}→ 无明显系统级身份暴露风险${NC}"
        return 0
    else
        echo -e "      ${YELLOW}→ 存在 $risks 项潜在暴露风险${NC}"
        echo -e "      ${YELLOW}  💡 修复建议: 将 macOS 首选语言改为 English，时区改为节点所在地时区，并重启浏览器。${NC}"
        FIX_SUGGESTIONS+=("将 macOS 首选语言改为 English，时区改为节点所在地时区，并重启浏览器。")
        return 1
    fi
}

final_report() {
    print_header "检测结果"
    
    local all_pass=true
    local pass_count=0
    local total_checks=7
    
    # 1. 出口 IP
    if [ "$EXIT_COUNTRY" = "CN" ]; then
        echo -e "${RED}[✗] 流量未代理${NC} - 出口 IP 显示中国大陆"
    else
        echo -e "${GREEN}[✓] 流量已代理${NC} - 出口：$EXIT_LOCATION"
        ((pass_count++))
    fi
    
    # 2. DNS
    if [ $DNS_RESULT -eq 0 ]; then
        echo -e "${GREEN}[✓] DNS 无泄露${NC}"
        ((pass_count++))
    else
        echo -e "${RED}[✗] DNS 可能泄露${NC}"
        all_pass=false
    fi
    
    # 3. TUN 模式
    if [ $TUN_RESULT -eq 0 ]; then
        echo -e "${GREEN}[✓] TUN 模式正常${NC} (流量全局接管)"
        ((pass_count++))
    else
        echo -e "${YELLOW}[!] TUN 模式未开启${NC}"
    fi
    
    # 4. 环境变量代理
    if [ $TUN_RESULT -eq 0 ]; then
        if [ $ENV_RESULT -eq 0 ]; then
            echo -e "${GREEN}[✓] 终端环境变量：未设置 (完美状态，全靠 TUN 底层接管)${NC}"
            ((pass_count++))
        else
            echo -e "${RED}[✗] 终端环境变量：冲突 (TUN 模式下请勿配置环境变量)${NC}"
            all_pass=false
        fi
    else
        if [ $ENV_RESULT -eq 0 ]; then
            echo -e "${GREEN}[✓] 终端环境变量：已设置 (应用层代理生效)${NC}"
            ((pass_count++))
        else
            echo -e "${RED}[✗] 终端环境变量：未设置 (在无 TUN 模式下，终端将直连)${NC}"
            all_pass=false
        fi
    fi
    
    # 5. ASN
    if [ "$CLAUDE_SEES_CN" = true ]; then
        echo -e "${RED}[✗] ASN 显示中国大陆运营商${NC}"
        all_pass=false
    else
        echo -e "${GREEN}[✓] ASN 正常${NC}"
        ((pass_count++))
    fi
    
    # 6. Claude 访问
    if [ "$CLAUDE_ACCESSIBLE" = true ]; then
        echo -e "${GREEN}[✓] Claude 可访问${NC}"
        ((pass_count++))
    else
        echo -e "${RED}[✗] Claude 不可访问${NC}"
        all_pass=false
    fi
    
    # 7. 身份暴露
    if [ "$CLAUDE_SEES_CN" = true ] && [ "$EXIT_COUNTRY" = "CN" ]; then
        echo -e "${RED}[✗] 存在被 Claude 识别的中国大陆访问特征${NC}"
        all_pass=false
    else
        echo -e "${GREEN}[✓] 无致命的中国大陆身份暴露特征${NC}"
        ((pass_count++))
    fi
    
    echo ""
    echo "========================================"
    echo " 通过: $pass_count / $total_checks"
    echo "========================================"
    
    local final_status
    if [ "$all_pass" = true ] && [ $pass_count -ge 6 ]; then
        echo -e "${GREEN}【通过】${NC} 可以安全使用 Claude 及其 API"
        final_status=0
        SUMMARY="代理完全没问题, 可放心CC"
    else
        echo -e "${RED}【未通过 / 有隐患】${NC} 建议检查代理配置"
        echo ""
        final_status=1
    fi

    if [ $final_status -ne 0 ]; then
        local unique_suggestions
        unique_suggestions=$(printf "%s\n" "${FIX_SUGGESTIONS[@]+"${FIX_SUGGESTIONS[@]}"}" | awk '!a[$0]++')
        if [ $DNS_RESULT -eq 1 ] && [ "$EXIT_COUNTRY" != "CN" ] && [ $TUN_RESULT -eq 0 ] && [ $ENV_RESULT -eq 0 ] && [ "$CLAUDE_SEES_CN" = false ] && [ "$CLAUDE_ACCESSIBLE" = true ]; then
            local s1
            s1=$(echo "$unique_suggestions" | sed -n 1p)
            SUMMARY="代理及格通过, 建议:\n $s1"
        else
            SUMMARY="代理存在问题, 建议修复:"
            local idx=1
            while IFS= read -r line; do
                [ -z "$line" ] && continue
                SUMMARY="$SUMMARY\n$idx. $line"
                ((idx++))
            done <<< "$unique_suggestions"
        fi
    fi
    
    echo -e "$SUMMARY"
    echo "$SUMMARY" | sed 's/\\n/ /g' | shortcuts run "shell説" -i - >/dev/null 2>&1 &
    
    return $final_status
}

main() {
    print_header "代理流量综合检测 v2.0 (增强全能版)"
    
    check_exit_ip
    check_dns_leak
    check_tun_route
    check_env_proxy
    check_asn
    check_claude_access
    check_identity_leak
    
    final_report
    local final_result=$?
    
    exit $final_result
}

main
