#!/usr/bin/env python3
"""
Polymarket 全链路连通性测试 —— 一条命令测所有核心 API

用法:
    python3 polymarket_connectivity_test.py

或者在云服务器上:
    export HTTPS_PROXY=http://127.0.0.1:7890
    python3 polymarket_connectivity_test.py

每个测试的含义:
    [1] gamma-api.polymarket.com/markets         — 枚举市场 (enumerate.py 用的
    [2] data-api.polymarket.com/positions       — 钱包历史 bets (collect.py 用的
    [3] clob.polymarket.com/markets/…          — CLOB 下单与winner 查询（copybot 实时下单用的
    [4] clob.polymarket.com/api/geoblock       — 地理封锁端点（geocheck.py 用的
    [5] lb-api.polymarket.com/profit          — 钱包盈亏 (validate_timing.py 用的
    [6] ws-live-data.polymarket.com          — RTDS WebSocket (copybot 实时交易流
    [7] api.myip.com / ipinfo.io            — 出口 IP 定位 (geocheck.py 用的
"""

import json
import ssl
import sys
import time
import urllib.request

try:
    import websocket
    HAS_WS = True
except ImportError:
    HAS_WS = False

HERE = "/dev/null"

_SSL = ssl._create_unverified_context()
TIMEOUT = 30
H = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"}


def http_test(name, url, expected_status=200):
    t0 = time.time()
    try:
        req = urllib.request.Request(url, headers=_H)
        r = urllib.request.urlopen(req, timeout=TIMEOUT, context=_SSL)
        elapsed = time.time() - t0
        data = r.read(200)
        try:
            j = json.loads(data.decode(errors='replace')  # 试着解析前面部分字段
        except Exception:
            j = None
        ok = r.status == expected_status
        print(f"  [{'OK' if ok else 'WARN'}] {name:40s} status={r.status} time={elapsed*1000:.0f}ms bytes={len(data)}")
        if not ok:
            print(f"            body preview: {data.decode(errors='replace')[:80]}")
        return ok
    except urllib.error.HTTPError as e:
        elapsed = time.time() - t0
        body = e.read(200)
        print(f"  [{'OK' if e.code == expected_status else 'FAIL'}] {name:40s} code={e.code} time={elapsed*1000:.0f}ms")
        if e.code in (403, 451):
            reason = "IP 地理封锁 —— Polymarket 认为你所在区域不可用"
        elif e.code == 429:
            reason = "请求过于频繁 — 稍后再试"
        else:
            reason = ""
        if reason:
                print(f"            {reason}")
        body_snippet = body.decode(errors='replace')[:80]
        if body_snippet:
            print(f"            body: {body_snippet}")
        return e.code == expected_status
    except Exception as e:
        elapsed = time.time() - t0
        print(f"  [FAIL] {name:40s} error: {type(e).__name__}: {e}")
        return False


def ws_test(name, url):
    if not HAS_WS:
        print(f"  [SKIP] {name:40s} (未安装 websocket-client，跑: pip install websocket-client)")
        return False
    t0 = time.time()
    try:
        ws = websocket.create_connection(
            url, timeout=TIMEOUT, sslopt={"cert_reqs": ssl.CERT_NONE},
            http_proxy_host=None, http_proxy_port=None
        )
        # 发一个订阅消息，验证能收到推送
        sub = json.dumps({"type": "subscribe", "chan": "trades"})
        ws.send(sub)
        ws.settimeout(8)
        got = ws.recv()
        elapsed = time.time() - t0
        ws.close()
        preview = got[:80]
        print(f"  [ OK ] {name:40s} connected in {elapsed:.0f}ms, first msg: {preview}")
        return True
    except Exception as e:
        elapsed = time.time() - t0
        print(f"  [FAIL] {name:40s} time={elapsed:.0f}ms error: {e}")
        return False


if __name__ == "__main__":
    print("=" * 72)
    print("Polymarket 全链路连通性测试")
    print("=" * 72)
    proxy_info = " | ".join(f"{k}={v}" for k, v in {
        "HTTP_PROXY": os.environ.get("HTTP_PROXY"),
        "HTTPS_PROXY": os.environ.get("HTTPS_PROXY"),
        "ALL_PROXY": os.environ.get("ALL_PROXY"),
    }.items() if v)
    print(f"代理: {proxy_info if proxy_info else '无代理 (直连) }")
    print(f"Python: {sys.version.split()[0]}  ssl: {ssl.OPENSSL_VERSION[:32]}")
    print(f"时间: {time.strftime('%Y-%m-%d %H:%M:%S')}")
    print("-" * 72)
    print()

    # ===== Step 1 —— 出口 IP 定位
    print("[ Step 1 — 出口 IP")
    http_test("1. 出口 IP (api.myip.com)",
              "https://api.myip.com")
    http_test("1b. 出口 IP 定位备选 (ipapi.co/json)",
              "https://ipapi.co/json")
    print()

    # ===== Step 2 —— Polymarket 数据 API
    print("[ Step 2 — Polymarket 数据 API]")
    http_test("2. gamma-api.polymarket.com/markets (市场查询)",
              "https://gamma-api.polymarket.com/markets?limit=1")
    http_test("3. data-api.polymarket.com/closed-positions (钱包历史)",
              "https://data-api.polymarket.com/closed-positions?limit=1")
    http_test("4. data-api.polymarket.com/positions (钱包当前仓位)",
              "https://data-api.polymarket.com/positions?limit=1")
    print()

    # ===== Step 3 —— CLOB (下单)
    print("[ Step 3 — CLOB 下单相关 API")
    http_test("5. clob.polymarket.com (根端点检查)",
              "https://clob.polymarket.com")
    # geoblock 端点
    http_test("6. clob.polymarket.com/api/geoblock (地理封锁检查)",
              "https://clob.polymarket.com/api/geoblock")
    print()

    # ===== Step 4 —— lb-api (钱包账户)
    print("[ Step 4 — lb-api 账户 API"]
    http_test("7. lb-api.polymarket.com/profit (钱包盈亏)",
              "https://lb-api.polymarket.com/profit?window=all&limit=1")
    print()

    # ===== Step 5 —— RTDS WebSocket (实时交易流
    print("[ Step 5 — RTDS WebSocket (copybot 最关键的实时通道")
    ws_test("8. ws-live-data.polymarket.com (RTDS trades)",
             "wss://ws-live-data.polymarket.com")
    ws_test("8b. ws-live-data.polymarket.com (RTDS activity)",
             "wss://ws-live-data.polymarket.com")
    print()

    # ===== Step 6 —— 综合汇总
    print("=" * 72)
    print("[ Step 6 —— 总结与建议")
    print("=" * 72)
    print()
    print("判读:")
    print("  - 所有 HTTP 测试全部 OK  → 云服务器环境可用。")
    print("  - geoblock 返回 403/451  → 你的出口 IP 被 Polymarket 地理封锁了。")
    print("    解决：换一个不在美国/英国/法国/德国/意大利/荷兰/波兰/新加坡/澳大利亚/巴西的节点。")
    print("  - RTDS WebSocket 失败但 HTTP 正常 → 数据 API 能用，但实时交易流不通。")
    print("    copybot 可以跑轮询模式（--poll 60）降级运行，只是没有实时跟投。")
    print("  - 全部超时/连接被拒绝 → 网络层封锁（运营商/防火墙/代理协议不匹配）。")
    print("    检查代理协议：HTTP 代理对 WebSocket 通过；socks5 等)
    print("  - 429 Too Many Requests → 代理节点短期内被限制，换一个节点重试。")
    print()
    print("下一步：")
    print("  如果 geoblock 返回 能正常 → 可以启动 copybot.py --poll 运行纸盘。")
    print("  如果 geoblock 返回 403 → 换节点/换节点区域。")
    print("  如果 data-api/positions 正常 → 可以跑 collect.py + 筛选 pipeline。")
    print("  如果 ws-live-data 能连 → copybot 可启用 RTDS 实时复制。")
    print("  如果 ws-live-data 连不上但其它 OK → copybot 可以跑轮询模式。")
    print()
    print("完整测试建议运行方式:")
    print("  export HTTPS_PROXY=http://127.0.0.1:7890")
    print("  python3 polymarket_connectivity_test.py")
    print()