"""命令行入口：`.venv/Scripts/python.exe -m evaluation ...`。"""
from __future__ import annotations

import argparse
import json
import sys
from pathlib import Path

from .audit import audit_repository, audit_security_repository
from .client import EvalClientError, ZcbotClient
from .combine import combine_reports
from .inspect_bridge import export_inspect_jsonl
from .models import EvalConfigError
from .report import summarize, write_reports
from .runner import RunSettings, run_suite
from .suite import load_suite


ROOT = Path(__file__).resolve().parents[1]
DEFAULT_SUITE = ROOT / "evaluation" / "datasets" / "smoke.json"
DEFAULT_CONFIG = ROOT / "evaluation" / "config.example.json"


def _parser() -> argparse.ArgumentParser:
    parser = argparse.ArgumentParser(description="zcbot 黑盒技术评测")
    sub = parser.add_subparsers(dest="command", required=True)
    validate = sub.add_parser("validate", help="只校验任务集，不调用 zcbot")
    validate.add_argument("--suite", type=Path, default=DEFAULT_SUITE)

    audit = sub.add_parser("audit", help="运行本地工程质量审计并生成报告")
    audit.add_argument("--suite", type=Path, default=DEFAULT_SUITE)
    audit.add_argument("--output", type=Path, default=ROOT / "evaluation" / "reports")
    audit.add_argument("--timeout-s", type=float, default=900)

    inspect_export = sub.add_parser(
        "export-inspect", help="把 suite 导出为 Inspect AI JSONL"
    )
    inspect_export.add_argument("--suite", type=Path, default=DEFAULT_SUITE)
    inspect_export.add_argument("--output", type=Path, required=True)

    combine = sub.add_parser("combine", help="合并已有 JSON 报告")
    combine.add_argument(
        "--report",
        type=Path,
        action="append",
        required=True,
        help="输入报告 JSON；可重复传入",
    )
    combine.add_argument(
        "--output",
        type=Path,
        default=ROOT / "evaluation" / "reports" / "latest",
    )

    run = sub.add_parser("run", help="执行任务集并生成 JSON/Markdown 报告")
    run.add_argument("--suite", type=Path, default=DEFAULT_SUITE)
    run.add_argument("--config", type=Path, default=DEFAULT_CONFIG)
    run.add_argument("--output", type=Path, default=ROOT / "evaluation" / "reports")
    run.add_argument("--repetitions", type=int)
    run.add_argument("--timeout-s", type=float, default=900)
    run.add_argument("--allow-remote", action="store_true")
    run.add_argument(
        "--with-audit",
        action="store_true",
        help="在线任务结束后同时执行本地工程审计，补齐 engineering 维度",
    )
    run.add_argument(
        "--execute",
        action="store_true",
        help="确认实际调用模型并产生费用；缺少此参数时拒绝执行",
    )
    return parser


def main(argv: list[str] | None = None) -> int:
    args = _parser().parse_args(argv)
    try:
        if args.command == "combine":
            summary = combine_reports(args.report)
            json_path, md_path = write_reports(summary, args.output)
            print(f"[OK] provisional_score={summary['provisional_score']}")
            print(f"[OK] total_score={summary['total_score']}")
            print(f"[OK] json={json_path}")
            print(f"[OK] markdown={md_path}")
            return 0
        suite = load_suite(args.suite)
        if args.command == "validate":
            print(
                f"[OK] suite={suite.name} version={suite.version} "
                f"cases={len(suite.cases)}"
            )
            return 0
        if args.command == "audit":
            engineering = audit_repository(
                ROOT, timeout_s=args.timeout_s, progress=print
            )
            security = audit_security_repository(
                ROOT, timeout_s=args.timeout_s, progress=print
            )
            summary = summarize(suite, [engineering, security], repo_root=ROOT)
            json_path, md_path = write_reports(
                summary, args.output, stem="engineering-audit"
            )
            print(f"[OK] engineering_score={engineering.score * 100:.2f}")
            print(f"[OK] security_score={security.score * 100:.2f}")
            print(f"[OK] json={json_path}")
            print(f"[OK] markdown={md_path}")
            return 0
        if args.command == "export-inspect":
            count = export_inspect_jsonl(suite, args.output)
            print(f"[OK] inspect_jsonl={args.output} samples={count}")
            return 0
        if not args.execute:
            print("[ERR] run 需要显式传 --execute（会调用模型并产生费用）")
            return 2
        config = json.loads(args.config.read_text(encoding="utf-8"))
        if not isinstance(config, dict):
            raise EvalConfigError("config 顶层必须是 JSON object")
        with ZcbotClient.from_config(
            config, allow_remote=args.allow_remote
        ) as client:
            results = run_suite(
                suite,
                client,
                settings=RunSettings(
                    repetitions=args.repetitions,
                    timeout_s=args.timeout_s,
                ),
                progress=print,
            )
        if args.with_audit:
            results.extend(
                [
                    audit_repository(
                        ROOT, timeout_s=args.timeout_s, progress=print
                    ),
                    audit_security_repository(
                        ROOT, timeout_s=args.timeout_s, progress=print
                    ),
                ]
            )
        summary = summarize(suite, results, repo_root=ROOT)
        json_path, md_path = write_reports(summary, args.output)
        print(f"[OK] json={json_path}")
        print(f"[OK] markdown={md_path}")
        return 0
    except (
        EvalConfigError,
        EvalClientError,
        OSError,
        ValueError,
        json.JSONDecodeError,
    ) as exc:
        print(f"[ERR] {exc}")
        return 2


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