"""보고서 서사에서 설계 표면 탐지기 소유 스냅샷을 생성한다."""
from __future__ import annotations

import argparse
import json
import sys
from pathlib import Path
from typing import Any, Mapping

from .convergence_store import write_json_atomic
from .design_surfaces import DesignSurfaceError, detect_design_surfaces
from .final_report_schema import load_schema_version
from .report_narrative import NarrativeContractError, parse_narrative


def _evidence(trigger: Any) -> list[dict[str, Any]]:
    return [
        {"step": row.step, "field": row.field, "match": row.match}
        for row in trigger.evidence
    ]


def build_design_snapshot(planning: Mapping[str, Any]) -> dict[str, Any]:
    """계획 본문에서 재현 가능한 설계 표면과 보수적 준비 항목을 만든다."""
    triggers = detect_design_surfaces(planning)
    by_stage: dict[int, list[dict[str, Any]]] = {}
    items = []
    for index, trigger in enumerate(triggers, start=1):
        evidence = _evidence(trigger)
        prep_id = f"PREP-{index:03d}"
        evidence_refs = [
            f"Stage {trigger.stage} step {row['step'] or 'n/a'} "
            f"{row['field']}={row['match']}"
            for row in evidence
        ]
        by_stage.setdefault(trigger.stage, []).append({
            "kind": trigger.kind,
            "triggerEvidence": evidence,
            "disposition": "prep-item",
            "prepItemId": prep_id,
        })
        items.append({
            "id": prep_id,
            "kind": trigger.kind,
            "title": f"Stage {trigger.stage} {trigger.kind} contract",
            "stageRefs": [trigger.stage],
            "status": "provisional",
            "need": (
                f"Stage {trigger.stage} touches a {trigger.kind} surface, but the "
                "detector evidence does not define its implementation contract."
            ),
            "knownFacts": [
                {"statement": "The plan triggered this design surface.", "evidence": ref}
                for ref in evidence_refs
            ],
            "openQuestions": [
                f"What exact {trigger.kind} contract must Stage {trigger.stage} implement?"
            ],
            "aiProposal": {
                "summary": "Preserve existing behaviour until the contract is confirmed.",
                "details": [
                    "Record the concrete contract before an irreversible implementation step."
                ],
                "assumptions": [
                    "Detector evidence proves surface presence, not the missing contract details."
                ],
                "evidence": evidence_refs,
                "confidence": "low",
            },
            "humanConfirmation": {
                "required": True,
                "reason": "The plan does not contain enough evidence to infer the contract.",
                "suggestedAction": "confirm-or-edit",
            },
            "workingAssumption": "Preserve existing behaviour and avoid irreversible changes.",
            "guardrails": [
                "Do not present a synthetic or inferred contract as externally verified."
            ],
            "reviewAt": {"phase": "implementation", "stage": trigger.stage},
            "ifStillOpen": "block",
            "requestPath": (
                f"design-prep-requests/design-prep-request-{trigger.stage}-{prep_id}.md"
            ),
            "replanTriggerFields": ["aiProposal", "workingAssumption"],
        })
    preparation = {
        "mode": "assessed" if triggers else "no-design-inputs",
        "reason": (
            f"Detector found {len(triggers)} design surface(s)."
            if triggers else "Detector found no design surfaces in the plan."
        ),
        "items": items,
    }
    return {
        "schemaVersion": "1.0",
        "owner": "design-surface-detector",
        "designPreparation": preparation,
        "stageCoverage": [
            {"stage": stage, "rows": rows}
            for stage, rows in sorted(by_stage.items())
        ],
    }


def write_snapshot(narrative_path: Path, output_path: Path) -> dict[str, Any]:
    narrative = parse_narrative(
        narrative_path.read_text(encoding="utf-8"), load_schema_version("3.0")
    )
    planning = narrative.get("implementationPlanning")
    if not isinstance(planning, Mapping):
        raise DesignSurfaceError("implementationPlanning is missing from narrative")
    snapshot = build_design_snapshot(planning)
    write_json_atomic(output_path, snapshot)
    return snapshot


def main(argv: list[str] | None = None) -> int:
    parser = argparse.ArgumentParser(prog="okstra design-snapshot")
    parser.add_argument("--narrative", type=Path, required=True)
    parser.add_argument("--output", type=Path, required=True)
    args = parser.parse_args(argv)
    try:
        snapshot = write_snapshot(args.narrative, args.output)
    except (OSError, UnicodeError, DesignSurfaceError, NarrativeContractError) as exc:
        print(f"design-snapshot: {exc}", file=sys.stderr)
        return 2
    print(json.dumps({"ok": True, "surfaces": sum(
        len(row["rows"]) for row in snapshot["stageCoverage"]
    )}, ensure_ascii=False))
    return 0


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