"""Tests for AnswerRelevancyMetric."""

from __future__ import annotations

import pytest

from evalkit.metrics.answer_relevancy import AnswerRelevancyMetric
from evalkit.models import MetricScore
from evalkit.models import TestCase as EvalTestCase


class TestAnswerRelevancyMetric:
    def test_name(self) -> None:
        assert AnswerRelevancyMetric.name == "answer_relevancy"

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

    def test_custom_threshold(self) -> None:
        metric = AnswerRelevancyMetric(threshold=0.75)
        assert metric.threshold == 0.75

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

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

    def test_prompt_contains_answer(self, sample_test_case: EvalTestCase) -> None:
        metric = AnswerRelevancyMetric()
        prompt = metric._build_prompt(sample_test_case)
        assert sample_test_case.answer in prompt

    def test_prompt_does_not_contain_context(self, sample_test_case: EvalTestCase) -> None:
        """Context should NOT be included in the answer relevancy prompt."""
        metric = AnswerRelevancyMetric()
        prompt = metric._build_prompt(sample_test_case)
        for chunk in sample_test_case.context:
            assert chunk not in prompt

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

    def test_score_returns_metric_score(self, mock_judge, sample_test_case: EvalTestCase) -> None:
        metric = AnswerRelevancyMetric()
        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 = AnswerRelevancyMetric()
        result = metric.score(sample_test_case, mock_judge)
        assert result.metric_name == "answer_relevancy"

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

        judge = MockJudge(score=0.95, reason="Perfectly on-topic")
        metric = AnswerRelevancyMetric()
        result = metric.score(sample_test_case, judge)
        assert result.score == pytest.approx(0.95)
        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.1, reason="Off-topic answer")
        metric = AnswerRelevancyMetric()
        result = metric.score(sample_test_case, judge)
        assert result.score == pytest.approx(0.1)
        assert result.passed is False

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