"""Focused tests for publish_test_metrics quality helper fallbacks."""

from __future__ import annotations

from pathlib import Path

from ci.scripts import publish_test_metrics_quality as quality_helpers


def test_infer_workspace_coverage_percent_handles_candidate_paths_and_parse_failures(tmp_path: Path) -> None:
    """Coverage inference should honor explicit XML hints and fail closed on bad XML."""

    build_dir = tmp_path / "build"
    build_dir.mkdir()

    coverage_xml = build_dir / "custom-coverage.xml"
    coverage_xml.write_text('<coverage line-rate="0.975" />', encoding="utf-8")
    summary = {"results": [None, {"name": "coverage", "coverage_xml": str(coverage_xml)}]}
    assert quality_helpers._infer_workspace_coverage_percent(summary, "build/default.xml") == 97.5

    missing_xml = build_dir / "missing.xml"
    assert quality_helpers._infer_workspace_coverage_percent({}, str(missing_xml)) == 0.0

    no_rate_xml = build_dir / "no-rate.xml"
    no_rate_xml.write_text("<coverage />", encoding="utf-8")
    assert quality_helpers._infer_workspace_coverage_percent({}, str(no_rate_xml)) == 0.0

    bad_xml = build_dir / "bad.xml"
    bad_xml.write_text("<coverage", encoding="utf-8")
    assert quality_helpers._infer_workspace_coverage_percent({}, str(bad_xml)) == 0.0


def test_infer_source_lines_over_500_counts_only_string_hygiene_issues() -> None:
    """LOC inference should ignore non-lists and only count explicit over-limit strings."""

    summary = {
        "results": [
            None,
            {"name": "docs", "issues": ["ignore me"]},
            {"name": "loc", "issues": "not-a-list"},
            {
                "name": "hygiene",
                "issues": [
                    "file exceeds 500 LOC: alpha.py (501)",
                    42,
                    "naming rule failed: beta.py",
                    "file exceeds 500 LOC: gamma.py (650)",
                ],
            },
        ]
    }

    assert quality_helpers._infer_source_lines_over_500(summary) == 2


def test_build_check_statuses_uses_fallbacks_for_tests_docs_and_gate_glue() -> None:
    """Fallback status synthesis should derive missing checks from related signals."""

    statuses = quality_helpers._build_check_statuses(
        summary={
            "results": [
                {"name": "docs", "status": "ok"},
                {"name": "smell", "status": "ok"},
                {"name": "gate", "status": "warning"},
            ]
        },
        tests={"tests": 3, "failures": 1, "errors": 0, "skipped": 0},
        workspace_line_coverage_percent=0.0,
        source_lines_over_500=0,
        sonarqube_report={},
        semgrep_report={},
        supply_chain_report={},
        supply_chain_required=False,
    )

    assert statuses["tests"] == "failed"
    assert statuses["coverage"] == "not_applicable"
    assert statuses["loc"] == "ok"
    assert statuses["docs_naming"] == "ok"
    assert statuses["gate_glue"] == "failed"


def test_build_check_statuses_preserves_explicit_loc_docs_and_glue_results() -> None:
    """Explicit canonical statuses should win over fallback inference."""

    statuses = quality_helpers._build_check_statuses(
        summary={
            "results": [
                {"name": "loc", "status": "ok"},
                {"name": "docs_naming", "status": "ok"},
                {"name": "gate_glue", "status": "ok"},
            ]
        },
        tests={"tests": 0, "failures": 0, "errors": 0, "skipped": 0},
        workspace_line_coverage_percent=96.0,
        source_lines_over_500=9,
        sonarqube_report={},
        semgrep_report={"status": "ok"},
        supply_chain_report={},
        supply_chain_required=False,
    )

    assert statuses["tests"] == "not_applicable"
    assert statuses["coverage"] == "ok"
    assert statuses["loc"] == "ok"
    assert statuses["docs_naming"] == "ok"
    assert statuses["gate_glue"] == "ok"
    assert statuses["semgrep"] == "ok"
