"""Tests for ``mgf.apiprobe.core.report``."""

from __future__ import annotations

from datetime import UTC, datetime

from mgf.apiprobe.core.finding import Finding, RootCause, Severity
from mgf.apiprobe.core.report import Report


def _f(
    code: str = "x",
    severity: Severity = Severity.WARN,
    root_cause: RootCause = RootCause.PROVIDER_QUALITY,
    probe_id: str | None = None,
) -> Finding:
    return Finding(
        code=code,
        severity=severity,
        root_cause=root_cause,
        message="x.",
        probe_id=probe_id,
    )


def _make_report(
    findings: tuple[Finding, ...] = (),
    *,
    probe_count: int = 0,
    transport_errors: int = 0,
) -> Report:
    return Report(
        findings=findings,
        started_at=datetime(2026, 1, 1, tzinfo=UTC),
        finished_at=datetime(2026, 1, 1, 0, 0, 1, tzinfo=UTC),
        probe_count=probe_count,
        transport_errors=transport_errors,
    )


class TestDuration:
    def test_one_second(self) -> None:
        r = _make_report()
        assert r.duration_seconds == 1.0


class TestHasCritical:
    def test_no_findings(self) -> None:
        assert _make_report().has_critical is False

    def test_only_warn(self) -> None:
        r = _make_report((_f(severity=Severity.WARN),))
        assert r.has_critical is False

    def test_with_critical(self) -> None:
        r = _make_report((_f(severity=Severity.WARN), _f(severity=Severity.CRITICAL)))
        assert r.has_critical is True


class TestHasFindingsMeeting:
    def test_threshold_below(self) -> None:
        r = _make_report((_f(severity=Severity.INFO),))
        assert r.has_findings_meeting(Severity.WARN) is False

    def test_threshold_at(self) -> None:
        r = _make_report((_f(severity=Severity.WARN),))
        assert r.has_findings_meeting(Severity.WARN) is True

    def test_threshold_above(self) -> None:
        r = _make_report((_f(severity=Severity.CRITICAL),))
        assert r.has_findings_meeting(Severity.WARN) is True

    def test_empty(self) -> None:
        r = _make_report()
        assert r.has_findings_meeting(Severity.INFO) is False


class TestSeverityBreakdown:
    def test_returns_all_three_keys(self) -> None:
        r = _make_report()
        b = r.severity_breakdown()
        assert set(b.keys()) == {Severity.INFO, Severity.WARN, Severity.CRITICAL}
        assert all(v == 0 for v in b.values())

    def test_counts(self) -> None:
        r = _make_report(
            (
                _f(severity=Severity.INFO),
                _f(severity=Severity.WARN),
                _f(severity=Severity.WARN),
                _f(severity=Severity.CRITICAL),
            )
        )
        b = r.severity_breakdown()
        assert b[Severity.INFO] == 1
        assert b[Severity.WARN] == 2
        assert b[Severity.CRITICAL] == 1


class TestRootCauseBreakdown:
    def test_only_nonzero_keys(self) -> None:
        r = _make_report(
            (
                _f(root_cause=RootCause.NETWORK),
                _f(root_cause=RootCause.NETWORK),
                _f(root_cause=RootCause.PROVIDER_5XX),
            )
        )
        b = r.root_cause_breakdown()
        assert b == {RootCause.NETWORK: 2, RootCause.PROVIDER_5XX: 1}


class TestByProbe:
    def test_grouping(self) -> None:
        r = _make_report(
            (
                _f(probe_id="p1"),
                _f(probe_id="p1"),
                _f(probe_id="p2"),
                _f(probe_id=None),
            )
        )
        groups = r.by_probe()
        assert len(groups["p1"]) == 2
        assert len(groups["p2"]) == 1
        assert len(groups[None]) == 1
