"""Tests for complyform.reporting.json_report."""

from __future__ import annotations

from complyform import __version__
from complyform.core.assessor.control_matcher import Finding
from complyform.reporting.json_report import (
    AssessmentMetadata,
    AssessmentSummary,
    format_json_envelope,
)


def _make_finding(
    control_id: str = "CC6.1",
    framework: str = "soc2",
    status: str = "PASS",
    severity: str = "MEDIUM",
) -> Finding:
    return Finding(
        control_id=control_id,
        framework=framework,
        resource_address="module.test.google_compute_instance.main",
        resource_type="google_compute_instance",
        status=status,
        severity=severity,
        finding=f"Control {control_id} {status.lower()}",
        remediation="Apply fix" if status == "FAIL" else "",
        checkov_id="CKV_GCP_1",
        cross_mappings=None,
        native_ids=None,
        confidence="high",
    )


def _make_summary() -> AssessmentSummary:
    return AssessmentSummary(
        total_controls=4,
        passed=2,
        failed=1,
        manual_review=1,
        not_assessed=0,
        score=66.7,
        severity_counts={"MEDIUM": 3, "HIGH": 1},
    )


def _make_metadata() -> AssessmentMetadata:
    return AssessmentMetadata(
        resource_count=5,
        assessment_duration_ms=120,
        tier="community",
        cache_hit=True,
        provider_versions={"google": "5.0.0"},
    )


def _build_envelope(
    findings: list[Finding] | None = None,
    summary: AssessmentSummary | None = None,
    metadata: AssessmentMetadata | None = None,
) -> dict:
    if findings is None:
        findings = [
            _make_finding(status="PASS"),
            _make_finding(control_id="CC6.2", status="FAIL", severity="HIGH"),
            _make_finding(control_id="CC7.1", status="MANUAL_REVIEW"),
            _make_finding(control_id="CC7.2", status="PASS"),
        ]
    if summary is None:
        summary = _make_summary()
    if metadata is None:
        metadata = _make_metadata()
    return format_json_envelope(
        findings,
        summary,
        metadata,
        cloud="gcp",
        state_hash="sha256:abc123",
        frameworks=["soc2"],
    )


class TestEnvelopeRequiredKeys:
    def test_has_all_required_keys(self) -> None:
        envelope = _build_envelope()
        required = {
            "schema_version",
            "tool",
            "tool_version",
            "command",
            "timestamp",
            "cloud",
            "scan_source",
            "state_hash",
            "frameworks",
            "summary",
            "findings",
            "metadata",
            "cloud_intelligence",
            "upgrade_hints",
        }
        assert required.issubset(envelope.keys())


class TestSchemaVersion:
    def test_schema_version_is_1(self) -> None:
        envelope = _build_envelope()
        assert envelope["schema_version"] == 1


class TestFindingsKey:
    def test_findings_present_and_is_list(self) -> None:
        envelope = _build_envelope()
        assert isinstance(envelope["findings"], list)
        assert len(envelope["findings"]) == 4


class TestSummaryScore:
    def test_summary_score_matches(self) -> None:
        envelope = _build_envelope()
        assert envelope["summary"]["score"] == 66.7


class TestSeverityCounts:
    def test_severity_counts_tallied(self) -> None:
        envelope = _build_envelope()
        sc = envelope["summary"]["severity_counts"]
        assert sc["MEDIUM"] == 3
        assert sc["HIGH"] == 1


class TestToolVersion:
    def test_tool_version_present(self) -> None:
        envelope = _build_envelope()
        assert envelope["tool_version"] == __version__
        assert envelope["tool"] == "complyform"
