"""Tests for titan-iac supply-chain compliance report generation."""

from __future__ import annotations

import json
from pathlib import Path

from ci.scripts import supply_chain_report


def _write_json(path: Path, payload: dict):
    """Write compact JSON fixtures for report tests."""
    path.write_text(json.dumps(payload), encoding="utf-8")


def test_build_report_separates_waived_and_open_misconfigurations(tmp_path: Path):
    """Existing waivers suppress only exact target/id pairs."""
    waivers = tmp_path / "waivers.json"
    _write_json(
        waivers,
        {
            "default_expires_at": "2026-05-22",
            "misconfigurations": [
                {
                    "id": "KSV-0014",
                    "targets": ["services/example/deployment.yaml"],
                }
            ],
        },
    )
    trivy_payload = {
        "Results": [
            {
                "Target": "services/example/deployment.yaml",
                "Misconfigurations": [
                    {
                        "ID": "KSV-0014",
                        "Status": "FAIL",
                        "Severity": "HIGH",
                        "Title": "Root file system is not read-only",
                    },
                    {
                        "ID": "KSV-0118",
                        "Status": "FAIL",
                        "Severity": "HIGH",
                        "Title": "Default security context configured",
                    },
                ],
            }
        ]
    }

    report = supply_chain_report.build_report(trivy_payload, waivers, today_override="2026-04-22")

    assert report["status"] == "failed"
    assert report["waived_misconfigurations"] == 1
    assert report["high_or_critical_misconfigurations"] == 1
    assert report["open_misconfiguration_examples"] == [
        {
            "id": "KSV-0118",
            "target": "services/example/deployment.yaml",
            "severity": "HIGH",
            "title": "Default security context configured",
        }
    ]


def test_build_report_fails_expired_waivers_and_secrets(tmp_path: Path):
    """Expired waivers intentionally stop hiding old baseline debt."""
    waivers = tmp_path / "waivers.json"
    _write_json(
        waivers,
        {
            "default_expires_at": "2026-04-01",
            "misconfigurations": [
                {
                    "id": "KSV-0014",
                    "targets": ["services/example/deployment.yaml"],
                }
            ],
        },
    )
    trivy_payload = {
        "Results": [
            {
                "Target": "services/example/deployment.yaml",
                "Secrets": [{"RuleID": "secret"}],
                "Misconfigurations": [
                    {
                        "ID": "KSV-0014",
                        "Status": "FAIL",
                        "Severity": "CRITICAL",
                        "Title": "Root file system is not read-only",
                    }
                ],
            }
        ]
    }

    report = supply_chain_report.build_report(trivy_payload, waivers, today_override="2026-04-22")

    assert report["status"] == "failed"
    assert report["compliant"] is False
    assert report["secrets"] == 1
    assert report["expired_waivers"] == 1
    assert report["waived_misconfigurations"] == 0


def test_build_report_fails_when_only_waivers_are_expired(tmp_path: Path):
    """Expiry alone is enough to fail the supply-chain baseline."""
    waivers = tmp_path / "waivers.json"
    _write_json(
        waivers,
        {
            "default_expires_at": "2026-04-01",
            "misconfigurations": [
                {"id": "KSV-0014", "targets": ["services/example/deployment.yaml"]}
            ],
        },
    )

    report = supply_chain_report.build_report(
        {"Results": []}, waivers, today_override="2026-04-22"
    )

    assert report["status"] == "failed"
    assert report["compliant"] is False
    assert report["expired_waivers"] == 1


def test_build_report_handles_missing_and_malformed_waiver_entries(tmp_path: Path):
    """Malformed waiver rows are ignored instead of hiding real findings."""
    missing_waivers = tmp_path / "missing.json"
    empty_report = supply_chain_report.build_report({"Results": []}, missing_waivers, today_override="2026-04-22")
    assert empty_report["status"] == "ok"

    waivers = tmp_path / "waivers.json"
    _write_json(
        waivers,
        {
            "misconfigurations": [
                "bad row",
                {"id": "", "targets": ["services/example/deployment.yaml"]},
                {"id": "KSV-0014", "targets": "not a list"},
                {"id": "KSV-0118", "expires_at": "2026-05-22", "targets": [""]},
            ]
        },
    )
    trivy_payload = {
        "Results": [
            "bad result",
            {
                "Target": "services/example/deployment.yaml",
                "Vulnerabilities": [
                    {"Severity": "HIGH"},
                    {"Severity": "CRITICAL"},
                    {"Severity": "LOW"},
                ],
                "Misconfigurations": [
                    "bad misconfiguration",
                    {"ID": "KSV-0001", "Status": "PASS", "Severity": "CRITICAL"},
                    {"ID": "KSV-0002", "Status": "FAIL", "Severity": "LOW"},
                ],
            },
        ]
    }

    report = supply_chain_report.build_report(trivy_payload, waivers, today_override="2026-04-22")

    assert report["status"] == "failed"
    assert report["critical_vulnerabilities"] == 1
    assert report["high_vulnerabilities"] == 1
    assert report["high_or_critical_misconfigurations"] == 0


def test_read_json_rejects_non_object_payload(tmp_path: Path):
    """Pipeline evidence files must be JSON objects, not arrays or scalars."""
    path = tmp_path / "array.json"
    path.write_text("[]", encoding="utf-8")

    try:
        supply_chain_report._read_json(path)
    except ValueError as exc:
        assert "must contain a JSON object" in str(exc)
    else:  # pragma: no cover - keeps the assertion message readable on failure
        raise AssertionError("expected ValueError")


def test_main_writes_compliance_report(tmp_path: Path):
    """The Jenkins CLI path writes the exact report artifact it publishes."""
    trivy_json = tmp_path / "trivy.json"
    output = tmp_path / "ironbank-compliance.json"
    _write_json(trivy_json, {"Results": []})

    rc = supply_chain_report.main(
        [
            "--trivy-json",
            str(trivy_json),
            "--output",
            str(output),
            "--today",
            "2026-04-22",
        ]
    )

    assert rc == 0
    payload = json.loads(output.read_text(encoding="utf-8"))
    assert payload["status"] == "ok"
    assert payload["compliant"] is True
