import pytest
from inspect_ai.scorer import (
    CORRECT,
    INCORRECT,
    NOANSWER,
    PARTIAL,
    Metric,
    SampleScore,
    Score,
    ValueToFloat,
)

from inspect_evals.lab_bench.metrics import (
    coverage,
    precision,
    precision_value_to_float,
)

to_float: ValueToFloat = precision_value_to_float()


def test_correct_conversion():
    assert to_float(CORRECT) == pytest.approx(1.0)


def test_incorrect_conversion():
    assert to_float(INCORRECT) == pytest.approx(0.0)


def test_partial_conversion():
    assert to_float(PARTIAL) == pytest.approx(0.5)


def test_noanswer_conversion():
    assert to_float(NOANSWER) == pytest.approx(-1.0)


def test_invalid_input():
    assert to_float("invalid_input") == pytest.approx(0.0)


precision_metric: Metric = precision()


def test_precision_metric_with_default_to_float():
    scores = [
        SampleScore(score=Score(value=CORRECT)),
        SampleScore(score=Score(value=INCORRECT)),
        SampleScore(score=Score(value=PARTIAL)),
        SampleScore(score=Score(value=CORRECT)),
        SampleScore(score=Score(value=NOANSWER)),
        SampleScore(score=Score(value=INCORRECT)),
        SampleScore(score=Score(value=NOANSWER)),
    ]
    result = precision_metric(scores)
    assert result == pytest.approx(0.5)  # (1 + 0.0 + 0.5 + 1.0 + 0.0) / 5 answered


def test_precision_metric_with_no_answers():
    scores = [
        SampleScore(score=Score(value=NOANSWER)),
        SampleScore(score=Score(value=NOANSWER)),
    ]
    result = precision_metric(scores)
    assert result == pytest.approx(0.0)


def test_precision_metric_with_empty_scores():
    scores = []
    result = precision_metric(scores)
    assert result == pytest.approx(0.0)


coverage_metric: Metric = coverage()


def test_coverage_metric_with_default_to_float():
    scores = [
        SampleScore(score=Score(value=CORRECT)),
        SampleScore(score=Score(value=INCORRECT)),
        SampleScore(score=Score(value=PARTIAL)),
        SampleScore(score=Score(value=CORRECT)),
        SampleScore(score=Score(value=NOANSWER)),
        SampleScore(score=Score(value=INCORRECT)),
        SampleScore(score=Score(value=NOANSWER)),
        SampleScore(score=Score(value=PARTIAL)),
    ]
    result = coverage_metric(scores)
    assert result == pytest.approx(0.75)  # 6 answered / 8 total


def test_coverage_metric_with_no_answers():
    scores = [
        SampleScore(score=Score(value=NOANSWER)),
        SampleScore(score=Score(value=NOANSWER)),
    ]
    result = coverage_metric(scores)
    assert result == pytest.approx(0.0)


def test_coverage_metric_with_empty_scores():
    scores = []
    result = coverage_metric(scores)
    assert result == pytest.approx(0.0)
