#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
模块名称：run_case_verify.py
模块描述：触发指定用例执行并轮询结果（新建会议 step 11 修复验收用）

用法：
    python scripts/run_case_verify.py --base http://localhost:8001 --case case_xxx [--name 展示名]

流程：POST /api/executions → POST /api/executions/{id}/run（同步阻塞）→
      GET /api/executions/{id}/results/{case_id} 拉步骤明细
输出：执行结果摘要 + 失败步骤详情（便于验收 step 7/8/9 不再跳过、step 11 通过）

作者：czj
创建日期：2026-08-19
"""

import argparse
import json
import sys
import time
import urllib.parse
import urllib.request

# Windows 控制台默认 GBK，强制 UTF-8 输出（避免 ✓/⏭ 等字符崩溃）
try:
    sys.stdout.reconfigure(encoding="utf-8")
except Exception:
    pass


def api(base: str, path: str, method: str = "GET", body: dict = None, timeout: int = 600) -> dict:
    url = base + path
    data = json.dumps(body).encode("utf-8") if body is not None else None
    req = urllib.request.Request(url, data=data, method=method, headers={
        "Accept": "application/json",
        "Content-Type": "application/json" if body is not None else "text/plain",
    })
    try:
        with urllib.request.urlopen(req, timeout=timeout) as resp:
            raw = resp.read().decode("utf-8")
            return json.loads(raw) if raw else {}
    except Exception as e:
        print(f"[API错误] {method} {path}: {e}")
        return {}


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--base", default="http://localhost:8001", help="后端地址")
    parser.add_argument("--case", required=True, help="用例 ID")
    parser.add_argument("--name", default="", help="展示名（可选）")
    args = parser.parse_args()

    base = args.base.rstrip("/")
    case_id = args.case

    print(f"== 触发执行: {args.name or case_id} @ {base} ==")

    # 1. 创建执行记录
    created = api(base, "/api/executions", method="POST", body={"case_ids": [case_id]}, timeout=30)
    exec_id = created.get("id") or created.get("execution_id")
    if not exec_id:
        print(f"!! 创建执行失败: {created}")
        sys.exit(1)
    print(f"执行记录: {exec_id}")

    # 2. 同步执行（阻塞，可能数分钟）
    t0 = time.time()
    run_res = api(base, f"/api/executions/{exec_id}/run", method="POST", timeout=600)
    elapsed = time.time() - t0
    print(f"执行完成: {run_res.get('status')}（用时 {elapsed:.1f}s）")

    # 3. 拉取结果
    result = api(base, f"/api/executions/{exec_id}/results/{case_id}", timeout=30)
    if not result:
        print("!! 未获取到执行结果")
        sys.exit(1)

    status = result.get("status")
    steps = result.get("steps_result") or result.get("steps") or []
    print(f"\n结果: status={status} | 步骤数={len(steps)}")
    print("-" * 80)

    failed = []
    for s in steps:
        s_status = s.get("status")
        log = (s.get("log") or "").replace("\n", " ")[:90]
        mark = {"passed": "[PASS]", "failed": "[FAIL]", "skipped": "[SKIP]"}.get(s_status, "[?]")
        print(f"[{s.get('order', '?'):>2}] {mark} {s_status:<7} {s.get('name', '')} || {log}")
        if s_status == "failed":
            failed.append(s)

    print("-" * 80)
    if failed:
        print(f"!! 失败步骤: {len(failed)} 个")
        for s in failed:
            print(f"   order={s.get('order')} {s.get('name')}")
        sys.exit(2)
    else:
        skipped = [s for s in steps if s.get("status") == "skipped"]
        print(f"✅ 全部通过（{len(steps)} 步，skipped={len(skipped)}）")
    return 0


if __name__ == "__main__":
    sys.exit(main())
