"""A run that measured nothing must never render as a favourable result.

All of these come from one real session: the CLI was pointed at a static
HTML/CSS repo with a subscription login and no API key, so every trial failed
to authenticate. The run completed, and the outputs said:

    Δ = +nanpp                          (terminal)
    "delta": NaN, "mde_pass_rate": Infinity   (json — rejected by JSON.parse)
    | Pass Rate | 0.00 | 0.00 | +nan% |      (pr comment)
    ### ablate · CLAUDE.md changed · ✅ no regression detected

The last line is the one that matters: eighteen failed trials presented to a
reviewer as approval. These tests exist so that specific sentence can never be
emitted over an empty dataset again.
"""

from __future__ import annotations

import json

import pytest

from ablate.config.variant import ConfigVariant
from ablate.record import AssertionRecord, TelemetryRecord, TrialRecord
from ablate.report.analysis import analyze
from ablate.report.formats import (
    NOT_REPORTED,
    render_json,
    render_junit,
    render_markdown,
    render_pr_comment,
)


def _trial(task: str, arm: str, rep: int, *, error: str | None = None) -> TrialRecord:
    return TrialRecord(
        trial_id=f"{task}-{arm}-{rep}",
        run_id="run1",
        task_id=task,
        variant_id=arm,
        variant_hash="sha256:x",
        replicate=rep,
        agent="claude-code",
        started_at="2026-07-28T00:00:00Z",
        duration_s=1.0,
        telemetry=TelemetryRecord(turns=0, cost_usd=None),
        assertions=[AssertionRecord(id="a", type="exit_code", passed=False)],
        passed=False,
        error=error,
    )


@pytest.fixture
def all_failed():
    """Every trial errored — the authentication case, reproduced."""
    records = [
        _trial(f"task-{i}", arm, r, error='{"is_error":true,"result":"Not logged in"}')
        for i in range(3)
        for arm in ("A", "B")
        for r in range(3)
    ]
    return analyze(records, ("A", "B"), run_id="run1", seed=1)


@pytest.fixture
def variants():
    return [
        ConfigVariant(id="A", source="CLAUDE.md", text="# rules\n"),
        ConfigVariant(id="B", source="/dev/null", text=None),
    ]


def test_nothing_is_reported_as_measured(all_failed):
    assert all_failed.errors == 18
    assert all_failed.n_tasks == 0
    for metric in all_failed.metrics:
        assert not metric.measured
        # Never 0.0: an arm that reported nothing did not score zero.
        assert all(v is None for v in metric.arm_values.values())


def test_pr_comment_never_claims_no_regression_over_an_empty_run(all_failed, variants):
    """The finding that motivated this module."""
    comment = render_pr_comment(all_failed, variants, fail_on="regression")

    assert "no regression detected" not in comment
    assert "✅" not in comment
    assert "nothing measured" in comment.lower()


def test_pr_comment_surfaces_the_error_count(all_failed, variants):
    """A reviewer reads the comment inline and may never open the artifact."""
    comment = render_pr_comment(all_failed, variants, fail_on="regression")

    assert "18 trials errored" in comment


def test_no_nan_or_inf_reaches_any_rendered_output(all_failed, variants):
    md = render_markdown(all_failed, variants, command="ablate compare")
    comment = render_pr_comment(all_failed, variants)
    junit = render_junit(all_failed)

    for name, text in (("markdown", md), ("pr-comment", comment), ("junit", junit)):
        lowered = text.lower()
        assert "nan" not in lowered, name
        assert "inf" not in lowered, name


def test_json_is_valid_json(all_failed, variants):
    """Bare NaN/Infinity are not JSON. JSON.parse and Go's encoding/json both
    reject them, and this is the CI-facing artifact."""
    raw = render_json(all_failed, variants, command="ablate compare")

    assert "NaN" not in raw
    assert "Infinity" not in raw

    def reject(constant: str) -> None:
        raise AssertionError(f"non-standard JSON constant {constant!r}")

    payload = json.loads(raw, parse_constant=reject)

    for metric in payload["metrics"]:
        assert metric["measured"] is False
        assert metric["delta"] is None
        assert metric["lo"] is None and metric["hi"] is None
        assert all(v is None for v in metric["arms"].values())
    assert payload["design"]["mde_pass_rate"] is None
    assert payload["cost_usd"] is None


def test_markdown_headline_does_not_assert_a_verdict(all_failed, variants):
    md = render_markdown(all_failed, variants)

    assert "nothing measured" in md.lower()


def test_junit_summary_says_nothing_was_measured(all_failed):
    """Three green cases in a CI pane read as a pass."""
    assert "NOTHING MEASURED" in render_junit(all_failed)


def test_unmeasured_values_render_as_the_shared_token(all_failed, variants):
    md = render_markdown(all_failed, variants)

    assert NOT_REPORTED in md


def test_a_real_measurement_still_reports_normally(variants):
    """Guards the fix against overcorrecting into never showing numbers."""
    records = []
    for i in range(10):
        for arm in ("A", "B"):
            for r in range(5):
                rec = _trial(f"task-{i}", arm, r)
                rec = rec.model_copy(
                    update={
                        "passed": arm == "A" or r > 1,
                        "telemetry": TelemetryRecord(
                            turns=6, input_tokens=100, output_tokens=50, cost_usd=0.01
                        ),
                        "assertions": [
                            AssertionRecord(id="a", type="exit_code", passed=True)
                        ],
                    }
                )
                records.append(rec)

    analysis = analyze(records, ("A", "B"), run_id="run1", seed=1)
    comment = render_pr_comment(analysis, variants, fail_on="regression")

    assert any(m.measured for m in analysis.metrics)
    assert "nothing measured" not in comment.lower()
    payload = json.loads(render_json(analysis, variants))
    assert payload["metrics"][0]["delta"] is not None
