"""Write diagnostics artifacts and batch summary for CODE_QA evaluation."""

from __future__ import annotations

import json
from datetime import datetime
from pathlib import Path

from tests.pipeline_setup.suite_01_synthetic.code_qa_eval.runner import EvalCaseResult


def dump_run_artifact(
    result: EvalCaseResult,
    out_dir: Path,
    *,
    run_id: str = "",
) -> None:
    """Write one run: markdown summary and JSON detail for manual review."""
    out_dir.mkdir(parents=True, exist_ok=True)
    prefix = result.case.id
    if run_id:
        prefix = f"{run_id}_{prefix}"

    md_path = out_dir / f"{prefix}.md"
    md_path.write_text(_run_markdown(result), encoding="utf-8")

    json_path = out_dir / f"{prefix}.json"
    json_path.write_text(
        json.dumps(_run_json(result), ensure_ascii=False, indent=2),
        encoding="utf-8",
    )


def _run_markdown(result: EvalCaseResult) -> str:
    c = result.case
    p = result.pipeline_result
    dr = p.diagnostics_report
    lines = [
        f"# {c.id}",
        "",
        "## Query",
        c.query,
        "",
        "## Expected",
        f"- intent: {c.expected_intent}, sub_intent: {c.expected_sub_intent}",
        f"- answer_mode: {c.expected_answer_mode}",
        "",
        "## Actual",
        f"- intent: {p.router_result.intent}, sub_intent: {p.router_result.query_plan.sub_intent if p.router_result.query_plan else '—'}",
        f"- answer_mode: {p.answer_mode}",
        f"- evidence_gate_passed: {p.evidence_gate_passed}",
        f"- evidence_count: {p.evidence_bundle.evidence_count}",
        "",
        "## Result",
        "PASS" if result.passed else "FAIL",
        "",
    ]
    if result.mismatches:
        lines.append("## Mismatches")
        for m in result.mismatches:
            lines.append(f"- {m}")
        lines.append("")
    lines.extend([
        "## Router",
        f"- path_scope: {list(getattr(p.router_result.retrieval_spec.filters, 'path_scope', []) or [])}",
        f"- layers: {[q.layer_id for q in (p.router_result.retrieval_spec.layer_queries or [])]}",
        "",
        "## Retrieval",
        f"- requested_layers: {p.retrieval_request.requested_layers}",
        f"- chunk_count: {len(p.retrieval_result.code_chunks)}",
        f"- layer_outcomes: {[(o.layer_id, o.hit_count) for o in p.retrieval_result.layer_outcomes]}",
        "",
        "## Evidence gate",
        f"- failure_reasons: {dr.failure_reasons if dr else []}",
        "",
        "## Timings (ms)",
        f"{p.timings_ms}",
        "",
    ])
    return "\n".join(lines)


def _run_json(result: EvalCaseResult) -> dict:
    c = result.case
    p = result.pipeline_result
    dr = p.diagnostics_report
    return {
        "case_id": c.id,
        "query": c.query,
        "expected": {
            "intent": c.expected_intent,
            "sub_intent": c.expected_sub_intent,
            "answer_mode": c.expected_answer_mode,
        },
        "actual": {
            "intent": p.router_result.intent,
            "sub_intent": p.router_result.query_plan.sub_intent if p.router_result.query_plan else None,
            "answer_mode": p.answer_mode,
            "evidence_gate_passed": p.evidence_gate_passed,
            "evidence_count": p.evidence_bundle.evidence_count,
        },
        "passed": result.passed,
        "mismatches": result.mismatches,
        "router_result": dr.router_result if dr else {},
        "retrieval_request": dr.retrieval_request if dr else {},
        "per_layer_outcome": dr.per_layer_outcome if dr else [],
        "failure_reasons": dr.failure_reasons if dr else [],
        "timings_ms": p.timings_ms,
    }


def write_batch_summary(
    results: list[EvalCaseResult],
    out_dir: Path,
    *,
    run_id: str = "",
) -> Path:
    """Write a single readable batch summary; returns path to the file."""
    out_dir.mkdir(parents=True, exist_ok=True)
    passed = sum(1 for r in results if r.passed)
    total = len(results)
    stamp = run_id or datetime.now().strftime("%Y%m%d_%H%M%S")
    path = out_dir / f"summary_{stamp}.md"
    lines = [
        "# CODE_QA evaluation summary",
        "",
        f"**{passed}/{total}** cases passed.",
        "",
        "| Case ID | Query | Expected scenario | Actual scenario | Target | Evidence | Answer mode | Pass |",
        "|---------|-------|------------------|-----------------|--------|----------|-------------|------|",
    ]
    for r in results:
        c = r.case
        p = r.pipeline_result
        sub = p.router_result.query_plan.sub_intent if p.router_result.query_plan else "—"
        target = "—"
        if p.evidence_bundle.resolved_target:
            target = p.evidence_bundle.resolved_target[:40] + ("…" if len(p.evidence_bundle.resolved_target or "") > 40 else "")
        ev = "✓" if p.evidence_gate_passed else "✗"
        mode = p.answer_mode
        pass_mark = "✓" if r.passed else "✗"
        q_short = c.query[:40] + ("…" if len(c.query) > 40 else "")
        lines.append(
            f"| {c.id} | {q_short} | {c.expected_sub_intent} | {sub} | {target} | {ev} | {mode} | {pass_mark} |"
        )
    lines.append("")
    lines.append("## Failures")
    for r in results:
        if not r.passed and r.mismatches:
            lines.append(f"- **{r.case.id}**: {'; '.join(r.mismatches)}")
    path.write_text("\n".join(lines), encoding="utf-8")
    return path
