#!/usr/bin/env python3
"""OpenAI OAuth 灰度发布演练脚本（本地模拟）。

该脚本会启动本地 mock Ops API，调用 openai_oauth_gray_guard.py，
验证以下场景：
1) A/B/C/D 四个灰度批次均通过
2) 注入异常场景触发阈值告警并返回退出码 2（模拟自动回滚触发）
"""

from __future__ import annotations

import json
import subprocess
import threading
from dataclasses import dataclass
from http.server import BaseHTTPRequestHandler, HTTPServer
from pathlib import Path
from typing import Dict, Tuple
from urllib.parse import parse_qs, urlparse

ROOT = Path(__file__).resolve().parents[2]
GUARD_SCRIPT = ROOT / "tools" / "perf" / "openai_oauth_gray_guard.py"
REPORT_PATH = ROOT / "docs" / "perf" / "openai-oauth-gray-drill-report.md"


THRESHOLDS = {
    "sla_percent_min": 99.5,
    "ttft_p99_ms_max": 900,
    "request_error_rate_percent_max": 2.0,
    "upstream_error_rate_percent_max": 2.0,
}

STAGE_SNAPSHOTS: Dict[str, Dict[str, float]] = {
    "A": {"sla": 99.78, "ttft": 780, "error_rate": 1.20, "upstream_error_rate": 1.05},
    "B": {"sla": 99.82, "ttft": 730, "error_rate": 1.05, "upstream_error_rate": 0.92},
    "C": {"sla": 99.86, "ttft": 680, "error_rate": 0.88, "upstream_error_rate": 0.80},
    "D": {"sla": 99.89, "ttft": 640, "error_rate": 0.72, "upstream_error_rate": 0.67},
    "rollback": {"sla": 97.10, "ttft": 1550, "error_rate": 6.30, "upstream_error_rate": 5.60},
}


class _MockHandler(BaseHTTPRequestHandler):
    def _write_json(self, payload: dict) -> None:
        raw = json.dumps(payload, ensure_ascii=False).encode("utf-8")
        self.send_response(200)
        self.send_header("Content-Type", "application/json")
        self.send_header("Content-Length", str(len(raw)))
        self.end_headers()
        self.wfile.write(raw)

    def log_message(self, format: str, *args):  # noqa: A003
        return

    def do_GET(self):  # noqa: N802
        parsed = urlparse(self.path)
        if parsed.path.endswith("/api/v1/admin/ops/settings/metric-thresholds"):
            self._write_json({"code": 0, "message": "success", "data": THRESHOLDS})
            return

        if parsed.path.endswith("/api/v1/admin/ops/dashboard/overview"):
            q = parse_qs(parsed.query)
            stage = (q.get("group_id") or ["A"])[0]
            snapshot = STAGE_SNAPSHOTS.get(stage, STAGE_SNAPSHOTS["A"])
            self._write_json(
                {
                    "code": 0,
                    "message": "success",
                    "data": {
                        "sla": snapshot["sla"],
                        "error_rate": snapshot["error_rate"],
                        "upstream_error_rate": snapshot["upstream_error_rate"],
                        "ttft": {"p99_ms": snapshot["ttft"]},
                    },
                }
            )
            return

        self.send_response(404)
        self.end_headers()


def run_guard(base_url: str, stage: str) -> Tuple[int, str]:
    cmd = [
        "python",
        str(GUARD_SCRIPT),
        "--base-url",
        base_url,
        "--platform",
        "openai",
        "--time-range",
        "30m",
        "--group-id",
        stage,
    ]
    proc = subprocess.run(cmd, cwd=str(ROOT), capture_output=True, text=True)
    output = (proc.stdout + "\n" + proc.stderr).strip()
    return proc.returncode, output


def main() -> int:
    server = HTTPServer(("127.0.0.1", 0), _MockHandler)
    host, port = server.server_address
    base_url = f"http://{host}:{port}"

    thread = threading.Thread(target=server.serve_forever, daemon=True)
    thread.start()

    lines = [
        "# OpenAI OAuth 灰度守护演练报告",
        "",
        "> 类型：本地 mock 演练（用于验证灰度守护与回滚触发机制）",
        f"> 生成脚本：`tools/perf/openai_oauth_gray_drill.py`",
        "",
        "## 1. 灰度批次结果（6.1）",
        "",
        "| 批次 | 流量比例 | 守护脚本退出码 | 结果 |",
        "|---|---:|---:|---|",
    ]

    batch_plan = [("A", "5%"), ("B", "20%"), ("C", "50%"), ("D", "100%")]
    all_pass = True
    for stage, ratio in batch_plan:
        code, _ = run_guard(base_url, stage)
        ok = code == 0
        all_pass = all_pass and ok
        lines.append(f"| {stage} | {ratio} | {code} | {'通过' if ok else '失败'} |")

    lines.extend([
        "",
        "## 2. 回滚触发演练（6.2）",
        "",
    ])

    rollback_code, rollback_output = run_guard(base_url, "rollback")
    rollback_triggered = rollback_code == 2
    lines.append(f"- 注入异常场景退出码：`{rollback_code}`")
    lines.append(f"- 是否触发回滚条件：`{'是' if rollback_triggered else '否'}`")
    lines.append("- 关键信息摘录：")
    excerpt = "\n".join(rollback_output.splitlines()[:8])
    lines.append("```text")
    lines.append(excerpt)
    lines.append("```")

    lines.extend([
        "",
        "## 3. 验收结论（6.3）",
        "",
        f"- 批次灰度结果：`{'通过' if all_pass else '不通过'}`",
        f"- 回滚触发机制：`{'通过' if rollback_triggered else '不通过'}`",
        f"- 结论：`{'通过（可进入真实环境灰度）' if all_pass and rollback_triggered else '不通过（需修复后复测）'}`",
    ])

    REPORT_PATH.parent.mkdir(parents=True, exist_ok=True)
    REPORT_PATH.write_text("\n".join(lines) + "\n", encoding="utf-8")

    server.shutdown()
    server.server_close()

    print(f"drill report generated: {REPORT_PATH}")
    return 0 if all_pass and rollback_triggered else 1


if __name__ == "__main__":
    raise SystemExit(main())
