#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
纯 Python NTP 测速脚本（全球版 2026）
只依赖 ntplib，无任何系统依赖
国内 + 全球通用 Anycast 服务器
"""

import asyncio
from concurrent.futures import ThreadPoolExecutor
import time
import socket
from typing import Optional, Dict

import ntplib

# ==================== NTP 服务器列表（国内 + 全球通用） ====================
SERVERS = [
    # ==================== 国内主流 ====================
    "ntp.aliyun.com", "ntp1.aliyun.com", "ntp2.aliyun.com", "ntp3.aliyun.com",
    "ntp4.aliyun.com", "ntp5.aliyun.com", "ntp6.aliyun.com", "ntp7.aliyun.com",
    "time1.aliyun.com", "time2.aliyun.com", "time3.aliyun.com", "time4.aliyun.com",
    "ntp.tencent.com", "ntp1.tencent.com", "ntp2.tencent.com", "ntp3.tencent.com",
    "ntp4.tencent.com", "ntp5.tencent.com",
    "ntp.myhuaweicloud.com", "ntp.baidu.com", "ntp.tuna.tsinghua.edu.cn",
    "ntp.ntsc.ac.cn",
    "ntp.sjtu.edu.cn", "ntp.neu.edu.cn", "ntp.bupt.edu.cn", "s1a.time.edu.cn",

    # ==================== 全球通用 Anycast NTP（重点新增） ====================
    "time.cloudflare.com",                                      # Cloudflare（全球最推荐）
    "time.google.com", "time1.google.com", "time2.google.com",
    "time3.google.com", "time4.google.com",                     # Google（带 leap smearing）
    "time.windows.com",                                         # Microsoft
    "time.apple.com",                                           # Apple
    "time.facebook.com", "time1.facebook.com", "time2.facebook.com",  # Meta/Facebook
    "0.pool.ntp.org", "1.pool.ntp.org", "2.pool.ntp.org", "3.pool.ntp.org", "pool.ntp.org",  # NTP Pool 全球
]

TIMEOUT = 2.5  # 稍增加超时，照顾全球服务器


def query_ntp(server: str) -> Optional[Dict]:
    """单个服务器查询"""
    try:
        ip = socket.gethostbyname(server)
    except Exception:
        ip = "DNS解析失败"

    try:
        client = ntplib.NTPClient()
        response = client.request(server, version=4, timeout=TIMEOUT)

        return {
            "server": server,
            "ip": ip,
            "delay_ms": round(response.delay * 1000, 3),
            "offset": round(response.offset, 6),
            "stratum": response.stratum,
        }
    except Exception:
        return None


async def main():
    print("🔥 纯 Python NTP 测速工具（国内 + 全球通用版）启动...")
    print("------------------------------------------------------------------")
    print(f"{'延迟(ms)':<10} | {'偏移(s)':<12} | {'Stratum':<8} | 服务器 (IP)")
    print("------------------------------------------------------------------")

    start_time = time.time()

    with ThreadPoolExecutor(max_workers=15) as executor:   # 增加并发，适应更多服务器
        loop = asyncio.get_running_loop()
        tasks = [loop.run_in_executor(executor, query_ntp, s) for s in SERVERS]
        results = await asyncio.gather(*tasks)

    # 过滤成功结果并排序（按延迟升序）
    successful = [r for r in results if r is not None]
    successful.sort(key=lambda x: x["delay_ms"])

    # 输出
    for r in successful:
        print(f"{r['delay_ms']:<10.3f} | {r['offset']:<12.6f} | {r['stratum']:<8} | "
              f"{r['server']} ({r['ip']})")

    failed_count = len(SERVERS) - len(successful)
    if failed_count > 0:
        print("------------------------------------------------------------------")
        print(f"❌ 超时/失败服务器：{failed_count} 个（已自动过滤）")

    print("------------------------------------------------------------------")
    total_time = time.time() - start_time
    print(f"✅ 测速完成！共测试 {len(SERVERS)} 个服务器，用时 {total_time:.2f} 秒")
    print("   建议选择顶部 **延迟最低 + Stratum 最小** 的服务器")
    print("   （国内服务器延迟通常更低，全球服务器可作为备用）")


if __name__ == "__main__":
    asyncio.run(main())
