"""Worked examples of the reward, and the marker region the page quotes."""

from __future__ import annotations

from pathlib import Path

import pytest

from alert_triage.reward import (
    FALSE_ESCALATION_CREDIT,
    WEIGHTS,
    Episode,
    escalate_break_even,
    metrics,
    score,
    score_exact,
    total,
)


def ep(**kw) -> Episode:
    base = dict(label="benign", planted=[["kyc.a"]], disposition="close", cites=["kyc.a"], minutes_spent=33,
                reference_minutes=33, turns_spent=1, rejected=0)
    base.update(kw)
    return Episode(**base)


def test_weights_sum_to_one_and_have_a_counterweight() -> None:
    assert abs(sum(WEIGHTS.values()) - 1.0) < 1e-12
    from alert_triage.reward import ROLES
    assert "counterweight" in ROLES.values()


def test_perfect_close() -> None:
    assert score(ep()) == {"caught": 1.0, "hours": 1.0, "evidence": 1.0}
    assert abs(total(ep()) - 1.0) < 1e-12


def test_a_miss_scores_exactly_zero() -> None:
    e = ep(label="suspicious", planted=[["T-1", "T-2"]], disposition="close", cites=["kyc.a"])
    assert score(e) == {"caught": 0.0, "hours": 0.0, "evidence": 0.0}
    assert total(e) == 0.0


def test_a_false_escalation_takes_half_the_counterweight_and_nothing_else() -> None:
    e = ep(disposition="escalate", cites=["kyc.a"])
    assert score(e) == {"caught": FALSE_ESCALATION_CREDIT, "hours": 0.0, "evidence": 0.0}


def test_no_disposition_is_zero_and_truncated_is_none() -> None:
    assert score(ep(disposition=None, cites=[])) == {"caught": 0.0, "hours": 0.0, "evidence": 0.0}
    assert score(ep(truncated=True)) == {"caught": None, "hours": None, "evidence": None}
    assert total(ep(truncated=True)) is None


def test_hours_is_capped_and_ratio_against_the_reference() -> None:
    assert score(ep(minutes_spent=20))["hours"] == 1.0
    assert abs(score(ep(minutes_spent=66))["hours"] - 0.5) < 1e-12
    assert score(ep(reference_minutes=None))["hours"] is None
    assert total(ep(reference_minutes=None)) is None


def test_evidence_is_f1_over_the_best_alternate() -> None:
    e = ep(planted=[["a", "b"], ["a"]], cites=["a"])
    assert score(e)["evidence"] == 1.0
    e = ep(planted=[["a", "b"]], cites=["a", "x", "y"])
    assert abs(score(e)["evidence"] - 0.4) < 1e-12           # 2·1 / (3+2)
    e = ep(planted=[["a"]], cites=["a", "b", "c", "d", "e", "f", "g", "h"])
    assert abs(score(e)["evidence"] - 2 / 9) < 1e-12          # one planted among eight cited
    assert score_exact(e)["evidence"] == [2, 9]


def test_exact_and_float_scores_agree() -> None:
    for e in (ep(), ep(minutes_spent=66), ep(planted=[["a", "b"]], cites=["a", "x", "y"]), ep(disposition="escalate")):
        exact = score_exact(e)
        approx = score(e)
        for k in approx:
            assert abs(exact[k][0] / exact[k][1] - approx[k]) < 1e-12


def test_break_even_is_between_zero_and_one() -> None:
    assert 0.3 < escalate_break_even() < 0.7


def test_metrics_are_diagnostics() -> None:
    m = metrics(ep(disposition="escalate", typology="UNKNOWN", true_typology="UNKNOWN", label="suspicious"))
    assert m["typology_match"] == 1.0 and m["false_escalation"] == 0.0
    assert metrics(ep())["typology_match"] is None


def test_exactly_one_marker_pair() -> None:
    text = (Path(__file__).parent.parent / "alert_triage" / "reward.py").read_text()
    assert text.count("# region: pig-demo/reward") == 1
    assert text.count("# endregion: pig-demo/reward") == 1
