"""Tests for confidence-aware refusal (#1275)."""
from __future__ import annotations

import pytest

from cortex.eval.generation import (
    DEFAULT_CONFIDENCE_THRESHOLD,
    REFUSAL_RESPONSE,
    GeneratedAnswer,
    should_refuse,
    generate_answer,
)


class TestShouldRefuse:
    def test_empty_scores_refuses(self):
        assert should_refuse([]) is True

    def test_all_below_threshold_refuses(self):
        assert should_refuse([0.1, 0.2, 0.15], confidence_threshold=0.3) is True

    def test_one_above_threshold_does_not_refuse(self):
        assert should_refuse([0.1, 0.5, 0.15], confidence_threshold=0.3) is False

    def test_all_above_threshold_does_not_refuse(self):
        assert should_refuse([0.5, 0.6, 0.8], confidence_threshold=0.3) is False

    def test_exact_threshold_does_not_refuse(self):
        # Score == threshold should NOT refuse (only < threshold)
        assert should_refuse([0.3], confidence_threshold=0.3) is False

    def test_zero_threshold_never_refuses(self):
        assert should_refuse([0.0, 0.0], confidence_threshold=0.0) is False

    def test_high_threshold_refuses_moderate(self):
        assert should_refuse([0.5, 0.6], confidence_threshold=0.8) is True


class TestGenerateAnswerRefusal:
    @pytest.mark.asyncio
    async def test_refuses_when_low_scores(self):
        result = await generate_answer(
            question="What color is the sky?",
            retrieved_claims=["irrelevant claim"],
            llm=None,  # Should not be called when refusing
            retrieval_scores=[0.1, 0.2],
            confidence_threshold=0.3,
        )
        assert result.refused is True
        assert result.answer == REFUSAL_RESPONSE

    @pytest.mark.asyncio
    async def test_refuses_when_no_claims(self):
        result = await generate_answer(
            question="What color is the sky?",
            retrieved_claims=[],
            llm=None,
            retrieval_scores=[],
            confidence_threshold=0.3,
        )
        assert result.refused is True

    @pytest.mark.asyncio
    async def test_does_not_refuse_without_scores(self):
        """Backward compat: no scores provided → proceeds normally."""
        class MockLLM:
            async def complete(self, **kwargs):
                class Resp:
                    text = "The sky is blue"
                return Resp()

        result = await generate_answer(
            question="What color is the sky?",
            retrieved_claims=["The sky is blue on clear days"],
            llm=MockLLM(),
        )
        assert result.refused is False
        assert "blue" in result.answer.lower()

    @pytest.mark.asyncio
    async def test_does_not_refuse_high_scores(self):
        class MockLLM:
            async def complete(self, **kwargs):
                class Resp:
                    text = "The sky is blue"
                return Resp()

        result = await generate_answer(
            question="What color is the sky?",
            retrieved_claims=["The sky is blue on clear days"],
            llm=MockLLM(),
            retrieval_scores=[0.8, 0.7],
            confidence_threshold=0.3,
        )
        assert result.refused is False
        assert result.answer and len(result.answer) > 0
