"""``JsonReportWriter`` — JSON-serializable dict rendering.

Produces a stable shape suitable for piping into jq, dashboards, CI
artifact stores, etc. The shape is part of the public contract for
v0.1 — fields can be ADDED in 0.x but not removed or renamed without
a minor bump.

Returns a ``dict[str, Any]`` rather than a JSON string so consumers
can serialise with their preferred encoder (json.dumps with custom
indentation, or pass through Pydantic, etc.). Stringification is the
caller's job::

    import json
    writer = JsonReportWriter()
    print(json.dumps(writer.write(report), indent=2))
"""

from __future__ import annotations

from typing import TYPE_CHECKING, Any

from mgf.apiprobe.reporting.base import ReportWriter

if TYPE_CHECKING:
    from mgf.apiprobe.core.finding import Finding
    from mgf.apiprobe.core.report import Report


class JsonReportWriter(ReportWriter):
    """Produces a JSON-serializable dict from a :class:`Report`.

    Shape (v0.1, public contract — additions only)::

        {
          "started_at": "2026-04-29T12:00:00Z",
          "finished_at": "2026-04-29T12:00:01Z",
          "duration_seconds": 1.0,
          "probe_count": 5,
          "transport_errors": 0,
          "severity_breakdown": {"info": 0, "warn": 3, "critical": 2},
          "root_cause_breakdown": {"provider_contract": 5},
          "findings": [
            {
              "code": "contract.status.unexpected",
              "severity": "critical",
              "root_cause": "provider_contract",
              "message": "Expected status in [200], got 500.",
              "evidence": {"expected": [200], "actual": 500},
              "remediation": "...",
              "probe_id": "list-users",
              "threat_refs": [],
              "tags": ["read", "public"],
              "since": null
            }
          ]
        }
    """

    def write(self, report: Report) -> dict[str, Any]:
        return {
            "started_at": report.started_at.isoformat().replace("+00:00", "Z"),
            "finished_at": report.finished_at.isoformat().replace("+00:00", "Z"),
            "duration_seconds": report.duration_seconds,
            "probe_count": report.probe_count,
            "transport_errors": report.transport_errors,
            "severity_breakdown": {k.value: v for k, v in report.severity_breakdown().items()},
            "root_cause_breakdown": {k.value: v for k, v in report.root_cause_breakdown().items()},
            "findings": [_finding_to_dict(f) for f in report.findings],
        }


def _finding_to_dict(finding: Finding) -> dict[str, Any]:
    return {
        "code": finding.code,
        "severity": finding.severity.value,
        "root_cause": finding.root_cause.value,
        "message": finding.message,
        "evidence": finding.evidence,
        "remediation": finding.remediation,
        "probe_id": finding.probe_id,
        "threat_refs": list(finding.threat_refs),
        "tags": list(finding.tags),
        "since": finding.since,
    }


__all__ = ["JsonReportWriter"]
