"""Tests for ContextualRelevancyMetric."""

from __future__ import annotations

import pytest

from evalkit.metrics.contextual_relevancy import ContextualRelevancyMetric
from evalkit.models import MetricScore
from evalkit.models import TestCase as EvalTestCase


class TestContextualRelevancyMetric:
    def test_name(self) -> None:
        assert ContextualRelevancyMetric.name == "contextual_relevancy"

    def test_default_threshold(self) -> None:
        metric = ContextualRelevancyMetric()
        assert metric.threshold == 0.5

    def test_custom_threshold(self) -> None:
        metric = ContextualRelevancyMetric(threshold=0.6)
        assert metric.threshold == 0.6

    # ------------------------------------------------------------------
    # Prompt construction
    # ------------------------------------------------------------------

    def test_prompt_contains_question(self, sample_test_case: EvalTestCase) -> None:
        metric = ContextualRelevancyMetric()
        prompt = metric._build_prompt(sample_test_case)
        assert sample_test_case.question in prompt

    def test_prompt_contains_context_chunks(self, sample_test_case: EvalTestCase) -> None:
        metric = ContextualRelevancyMetric()
        prompt = metric._build_prompt(sample_test_case)
        for chunk in sample_test_case.context:
            assert chunk in prompt

    def test_prompt_numbers_context_chunks(self, sample_test_case: EvalTestCase) -> None:
        metric = ContextualRelevancyMetric()
        prompt = metric._build_prompt(sample_test_case)
        assert "[1]" in prompt

    def test_prompt_with_multiple_chunks(self) -> None:
        test_case = EvalTestCase(
            question="What is the speed of light?",
            context=["Light travels at approximately 3×10^8 m/s.", "It is a constant in a vacuum."],
            answer="The speed of light is about 3×10^8 m/s.",
        )
        metric = ContextualRelevancyMetric()
        prompt = metric._build_prompt(test_case)
        assert "[1]" in prompt
        assert "[2]" in prompt

    # ------------------------------------------------------------------
    # score() result
    # ------------------------------------------------------------------

    def test_score_returns_metric_score(self, mock_judge, sample_test_case: EvalTestCase) -> None:
        metric = ContextualRelevancyMetric()
        result = metric.score(sample_test_case, mock_judge)
        assert isinstance(result, MetricScore)

    def test_score_metric_name(self, mock_judge, sample_test_case: EvalTestCase) -> None:
        metric = ContextualRelevancyMetric()
        result = metric.score(sample_test_case, mock_judge)
        assert result.metric_name == "contextual_relevancy"

    def test_score_with_high_judge_response(self, sample_test_case: EvalTestCase) -> None:
        from tests.conftest import MockJudge

        judge = MockJudge(score=0.9, reason="Context directly answers the question")
        metric = ContextualRelevancyMetric()
        result = metric.score(sample_test_case, judge)
        assert result.score == pytest.approx(0.9)
        assert result.passed is True

    def test_score_with_low_judge_response(self, sample_test_case: EvalTestCase) -> None:
        from tests.conftest import MockJudge

        judge = MockJudge(score=0.15, reason="Context is unrelated")
        metric = ContextualRelevancyMetric()
        result = metric.score(sample_test_case, judge)
        assert result.score == pytest.approx(0.15)
        assert result.passed is False

    def test_score_calls_judge_once(self, mock_judge, sample_test_case: EvalTestCase) -> None:
        metric = ContextualRelevancyMetric()
        metric.score(sample_test_case, mock_judge)
        assert mock_judge.call_count == 1
