#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""FlexUI DevTools watch — DevServer 状态监视 + 调试 URL 提示。

配合 scripts/debug-server.sh 使用:debug-server.sh 启动 DevServer 后前台运行本脚本;
本脚本阻塞运行(轮询 DevServer /json),按 Ctrl+C 退出后由 debug-server.sh 关闭 DevServer。

功能:
  1. 设备与 rport 转发检测(hdc):缺失 rport 规则时自动添加
  2. 持续监听 DevServer /json,新 target 出现时提示最新调试 URL
  3. 周期显示 DevServer / 设备 / target 状态
"""
import argparse
import json
import subprocess
import sys
import time
import urllib.request

try:
    sys.stdout.reconfigure(encoding="utf-8")
    sys.stderr.reconfigure(encoding="utf-8")
except Exception:
    pass

C_RESET = "\033[0m"
C_GREEN = "\033[32m"
C_YELLOW = "\033[33m"
C_CYAN = "\033[36m"
C_RED = "\033[31m"
C_BOLD = "\033[1m"


def color(text, code, enable=True):
    return f"{code}{text}{C_RESET}" if enable else text


def run(cmd, timeout=10):
    try:
        r = subprocess.run(cmd, capture_output=True, text=True, timeout=timeout)
        out = (r.stdout or "").strip()
        err = (r.stderr or "").strip()
        return out + ("\n" + err if err else "")
    except Exception as e:  # noqa: BLE001
        return f"<{e}>"


def fetch_json(url, timeout=3):
    try:
        with urllib.request.urlopen(url, timeout=timeout) as resp:
            return json.loads(resp.read().decode("utf-8"))
    except Exception:  # noqa: BLE001
        return None


def ensure_rport(port, verbose=True):
    """检测 hdc rport 规则(设备 localhost:port → PC port),缺失则添加。

    返回 (device, rule_ok)。device 为空表示无设备连接。
    """
    targets = run(["hdc", "list", "targets"]).strip()
    device = targets.splitlines()[0].strip() if targets.strip() else ""
    if not device:
        return "", False
    fports = run(["hdc", "fport", "ls"])
    rule = f"tcp:{port} tcp:{port}"
    if "[Reverse]" in fports and rule in fports:
        return device, True
    out = run(["hdc", "rport", f"tcp:{port}", f"tcp:{port}"])
    return device, ("result:OK" in out)


def main():
    ap = argparse.ArgumentParser(description="FlexUI DevTools watch")
    ap.add_argument("--port", type=int, default=38989)
    ap.add_argument("--host", default="localhost")
    ap.add_argument("--interval", type=float, default=2.0)
    args = ap.parse_args()

    base = f"http://{args.host}:{args.port}"
    json_url = f"{base}/json"
    version_url = f"{base}/json/version"
    color_on = sys.stdout.isatty()

    def p(text, code=C_RESET):
        print(color(text, code, color_on), flush=True)

    p(f"===== FlexUI DevTools watch — {base} =====", C_BOLD + C_CYAN)

    # 1) DevServer 健康
    version = fetch_json(version_url)
    if version is None:
        p(f"[FAIL] DevServer 未响应 {version_url} —— 请先通过 debug-server.sh 启动 DevServer", C_RED)
        sys.exit(1)
    browser = version.get("Browser") or version.get("browser") or ""
    p(f"[OK] DevServer 就绪" + (f" ({browser})" if browser else ""), C_GREEN)

    # 2) 设备 / rport
    dev, ok = ensure_rport(args.port)
    if not dev:
        p("[WARN] 未检测到 hdc 设备(hdc list targets 为空)—— 请连接设备后重试", C_YELLOW)
    else:
        p(f"[OK] hdc 设备: {dev}", C_GREEN)
        if ok:
            p(f"[OK] rport 转发就绪: tcp:{args.port} tcp:{args.port} [Reverse]", C_GREEN)
        else:
            p(f"[WARN] rport 转发添加结果未知,请检查 'hdc fport ls'", C_YELLOW)

    print("")
    p("等待设备 App 连接…… 请重启 App(force-stop 后重新启动)以触发 DevServer 连接。", C_BOLD)
    p("看到新的调试 URL 后,在浏览器打开即可进入 DevTools。按 Ctrl+C 退出(会同时关闭 DevServer)。")
    print("")

    seen = set()
    last_summary = 0.0
    last_summary_text = None
    try:
        while True:
            targets = fetch_json(json_url) or []
            current = {t.get("clientId") or t.get("id") for t in targets}
            new_ids = current - seen
            for tid in new_ids:
                for t in targets:
                    if (t.get("clientId") or t.get("id")) == tid:
                        title = t.get("title", "?")
                        fe_url = t.get("devtoolsFrontendUrl", "")
                        ws_url = t.get("webSocketDebuggerUrl", "")
                        print("")
                        p(f"*** 新的调试 target: {title} ***", C_BOLD + C_GREEN)
                        if fe_url:
                            p(f"    DevTools 打开: {fe_url}", C_CYAN)
                        if ws_url:
                            p(f"    WS 直连:       {ws_url}")
                        print("")
                        break
            seen |= current

            # 周期状态:仅当内容变化时才打印(避免同一状态反复刷屏)
            now = time.time()
            if now - last_summary >= 8.0:
                last_summary = now
                dev2, ok2 = ensure_rport(args.port, verbose=False)
                summary = f"[状态] targets={len(targets)} 设备={dev2 or '无'} rport={'OK' if ok2 else '?'}"
                if summary != last_summary_text:
                    p(summary, C_YELLOW)
                    last_summary_text = summary

            time.sleep(args.interval)
    except KeyboardInterrupt:
        print("")
        p("收到退出信号,停止监听。DevServer 将由 debug-server.sh 关闭。", C_YELLOW)


if __name__ == "__main__":
    main()