#!/usr/bin/env python3
"""Normalize and verify the school-side one-click Apifox regression suite."""

from __future__ import annotations

import importlib.util
import json
from datetime import datetime
from pathlib import Path


HERE = Path(__file__).resolve().parent
SHARED_PATH = HERE / "sync_school_s00_s06_scenarios.py"
SPEC = importlib.util.spec_from_file_location("school_sync", SHARED_PATH)
if SPEC is None or SPEC.loader is None:
    raise RuntimeError(f"cannot load shared Apifox helper: {SHARED_PATH}")
SHARED = importlib.util.module_from_spec(SPEC)
SPEC.loader.exec_module(SHARED)

PROJECT_ID = SHARED.PROJECT_ID
SUITE_ID = SHARED.TEST_SUITE_ID
SUITE_NAME = "学校端-双库全量一键回归"

EXPECTED_NAMES = [
    "S00-环境与认证（双库）",
    "S01-首页与预警（双库）",
    "S02-晨检管理（双库真实写入）",
    "S03-农残检测（双库真实写入）",
    "S04-消毒管理（双库真实写入）",
    "S05-废弃物管理（双库真实写入）",
    "S06-设备安全（双库真实写入）",
    "S07-留样管理（双库真实写入）",
    "S08-菜品与留样人员（双库真实写入）",
    "S09-库存与供应链（双库真实写入）",
    "S10-供应商管理（双库真实写入）",
    "S11-人员食堂与证照（双库真实写入）",
    "S12-用户角色与审计（双库真实写入）",
    "S13-物联网配置与明厨亮灶（双库真实写入）",
]


def walk_requests(steps: list[dict]) -> list[tuple[str, bool]]:
    result: list[tuple[str, bool]] = []
    for step in steps:
        request = step.get("customHttpRequest")
        if request:
            result.append((str(request.get("name", "")), bool(step.get("disable"))))
        result.extend(walk_requests(step.get("children", [])))
    return result


def main() -> None:
    api = SHARED.Apifox()
    suite = api.test_suite()
    backup_dir = HERE.parent / "backups"
    backup_dir.mkdir(parents=True, exist_ok=True)
    stamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    backup = backup_dir / f"school-one-click-suite-before-sync_{stamp}.json"
    backup.write_text(json.dumps(suite, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")

    actual_names = [item.get("name") for item in suite.get("items", [])]
    if actual_names != EXPECTED_NAMES:
        raise RuntimeError(f"school suite item order mismatch: {actual_names}")

    enabled = 0
    disabled = 0
    for item in suite["items"]:
        scenario_id = int(item["testScenarios"][0]["id"])
        scenario = api.scenario(scenario_id)
        rows = walk_requests(scenario.get("steps", []))
        enabled += sum(not is_disabled for _, is_disabled in rows)
        disabled += sum(is_disabled for _, is_disabled in rows)

    suite["name"] = SUITE_NAME
    suite["description"] = (
        f"学校端 S00-S13 共 {len(EXPECTED_NAMES)} 个常规模块的一键串行双库回归："
        f"默认启用 {enabled} 个请求步骤，每步依次执行 MySQL foodsafe_test 与达梦 WWWWEB，"
        f"共 {enabled * 2} 次实际请求；另有 {disabled} 个删除、SSE、外部设备或夹具步骤默认关闭。"
        "S12-R 重启后读回专项使用隔离端口 3552/3553，不混入日常一键套件。"
        "所有普通 HTTP 步骤均应包含字段断言、实际返回摘要和脱敏 APIFOX_EVIDENCE。"
    )
    suite.setdefault("options", {})["runMode"] = "serial"
    api.save_test_suite(suite)

    saved = api.test_suite()
    if saved.get("name") != SUITE_NAME:
        raise RuntimeError(f"suite rename failed: {saved.get('name')}")
    if [item.get("name") for item in saved.get("items", [])] != EXPECTED_NAMES:
        raise RuntimeError("saved suite item order changed unexpectedly")
    if saved.get("options", {}).get("runMode") != "serial":
        raise RuntimeError("saved suite is not serial")

    print(f"backup={backup}")
    print(
        f"suite={saved['name']}, id={saved['id']}, modules={len(EXPECTED_NAMES)}, "
        f"enabledSteps={enabled}, dualExecutions={enabled * 2}, disabledSteps={disabled}, runMode=serial"
    )


if __name__ == "__main__":
    main()
