"""
Tests for advanced_search_system/evidence/evaluator.py

Tests cover:
- EvidenceEvaluator initialization
- extract_evidence method
- _parse_evidence_response method
- _parse_evidence_type method
- _assess_match_quality method
"""

from unittest.mock import Mock, patch


class TestEvidenceEvaluatorInit:
    """Tests for EvidenceEvaluator initialization."""

    def test_init_stores_model(self):
        """Test that model is stored."""
        from local_deep_research.advanced_search_system.evidence.evaluator import (
            EvidenceEvaluator,
        )

        mock_model = Mock()
        evaluator = EvidenceEvaluator(mock_model)

        assert evaluator.model is mock_model

    def test_init_creates_source_reliability_dict(self):
        """Test that source reliability dict is created."""
        from local_deep_research.advanced_search_system.evidence.evaluator import (
            EvidenceEvaluator,
        )

        evaluator = EvidenceEvaluator(Mock())

        assert "official" in evaluator.source_reliability
        assert "research" in evaluator.source_reliability
        assert "news" in evaluator.source_reliability
        assert "community" in evaluator.source_reliability
        assert "inference" in evaluator.source_reliability
        assert "speculation" in evaluator.source_reliability

    def test_source_reliability_values(self):
        """Test source reliability values."""
        from local_deep_research.advanced_search_system.evidence.evaluator import (
            EvidenceEvaluator,
        )

        evaluator = EvidenceEvaluator(Mock())

        assert evaluator.source_reliability["official"] == 1.0
        assert evaluator.source_reliability["research"] == 0.95
        assert evaluator.source_reliability["news"] == 0.8
        assert evaluator.source_reliability["community"] == 0.6
        assert evaluator.source_reliability["inference"] == 0.5
        assert evaluator.source_reliability["speculation"] == 0.3


class TestParseEvidenceResponse:
    """Tests for _parse_evidence_response method."""

    def test_parse_valid_response(self):
        """Test parsing a valid response."""
        from local_deep_research.advanced_search_system.evidence.evaluator import (
            EvidenceEvaluator,
        )

        evaluator = EvidenceEvaluator(Mock())
        content = """CLAIM: The Earth is round
TYPE: direct_statement
SOURCE: NASA
CONFIDENCE: 0.95
REASONING: Based on scientific evidence
QUOTE: Earth is an oblate spheroid"""

        parsed = evaluator._parse_evidence_response(content)

        assert parsed["claim"] == "The Earth is round"
        assert parsed["type"] == "direct_statement"
        assert parsed["source"] == "NASA"
        assert parsed["confidence"] == "0.95"
        assert parsed["reasoning"] == "Based on scientific evidence"
        assert parsed["quote"] == "Earth is an oblate spheroid"

    def test_parse_confidence_with_extra_text(self):
        """Test parsing confidence with extra text."""
        from local_deep_research.advanced_search_system.evidence.evaluator import (
            EvidenceEvaluator,
        )

        evaluator = EvidenceEvaluator(Mock())
        content = """CLAIM: Test claim
CONFIDENCE: 0.85 (high confidence based on multiple sources)"""

        parsed = evaluator._parse_evidence_response(content)

        assert parsed["confidence"] == "0.85"

    def test_parse_handles_missing_fields(self):
        """Test parsing handles missing fields."""
        from local_deep_research.advanced_search_system.evidence.evaluator import (
            EvidenceEvaluator,
        )

        evaluator = EvidenceEvaluator(Mock())
        content = """CLAIM: Test claim
TYPE: news_report"""

        parsed = evaluator._parse_evidence_response(content)

        assert parsed["claim"] == "Test claim"
        assert parsed["type"] == "news_report"
        assert "source" not in parsed

    def test_parse_ignores_unknown_keys(self):
        """Test parsing ignores unknown keys."""
        from local_deep_research.advanced_search_system.evidence.evaluator import (
            EvidenceEvaluator,
        )

        evaluator = EvidenceEvaluator(Mock())
        content = """CLAIM: Test claim
UNKNOWN: Some value
TYPE: inference"""

        parsed = evaluator._parse_evidence_response(content)

        assert "unknown" not in parsed
        assert parsed["claim"] == "Test claim"
        assert parsed["type"] == "inference"

    def test_parse_handles_empty_content(self):
        """Test parsing handles empty content."""
        from local_deep_research.advanced_search_system.evidence.evaluator import (
            EvidenceEvaluator,
        )

        evaluator = EvidenceEvaluator(Mock())
        parsed = evaluator._parse_evidence_response("")

        assert parsed == {}


class TestParseEvidenceType:
    """Tests for _parse_evidence_type method."""

    def test_parse_direct_statement(self):
        """Test parsing direct_statement type."""
        from local_deep_research.advanced_search_system.evidence.evaluator import (
            EvidenceEvaluator,
        )
        from local_deep_research.advanced_search_system.evidence.base_evidence import (
            EvidenceType,
        )

        evaluator = EvidenceEvaluator(Mock())
        result = evaluator._parse_evidence_type("direct_statement")

        assert result == EvidenceType.DIRECT_STATEMENT

    def test_parse_official_record(self):
        """Test parsing official_record type."""
        from local_deep_research.advanced_search_system.evidence.evaluator import (
            EvidenceEvaluator,
        )
        from local_deep_research.advanced_search_system.evidence.base_evidence import (
            EvidenceType,
        )

        evaluator = EvidenceEvaluator(Mock())
        result = evaluator._parse_evidence_type("official_record")

        assert result == EvidenceType.OFFICIAL_RECORD

    def test_parse_research_finding(self):
        """Test parsing research_finding type."""
        from local_deep_research.advanced_search_system.evidence.evaluator import (
            EvidenceEvaluator,
        )
        from local_deep_research.advanced_search_system.evidence.base_evidence import (
            EvidenceType,
        )

        evaluator = EvidenceEvaluator(Mock())
        result = evaluator._parse_evidence_type("research_finding")

        assert result == EvidenceType.RESEARCH_FINDING

    def test_parse_news_report(self):
        """Test parsing news_report type."""
        from local_deep_research.advanced_search_system.evidence.evaluator import (
            EvidenceEvaluator,
        )
        from local_deep_research.advanced_search_system.evidence.base_evidence import (
            EvidenceType,
        )

        evaluator = EvidenceEvaluator(Mock())
        result = evaluator._parse_evidence_type("news_report")

        assert result == EvidenceType.NEWS_REPORT

    def test_parse_statistical_data(self):
        """Test parsing statistical_data type."""
        from local_deep_research.advanced_search_system.evidence.evaluator import (
            EvidenceEvaluator,
        )
        from local_deep_research.advanced_search_system.evidence.base_evidence import (
            EvidenceType,
        )

        evaluator = EvidenceEvaluator(Mock())
        result = evaluator._parse_evidence_type("statistical_data")

        assert result == EvidenceType.STATISTICAL_DATA

    def test_parse_inference(self):
        """Test parsing inference type."""
        from local_deep_research.advanced_search_system.evidence.evaluator import (
            EvidenceEvaluator,
        )
        from local_deep_research.advanced_search_system.evidence.base_evidence import (
            EvidenceType,
        )

        evaluator = EvidenceEvaluator(Mock())
        result = evaluator._parse_evidence_type("inference")

        assert result == EvidenceType.INFERENCE

    def test_parse_correlation(self):
        """Test parsing correlation type."""
        from local_deep_research.advanced_search_system.evidence.evaluator import (
            EvidenceEvaluator,
        )
        from local_deep_research.advanced_search_system.evidence.base_evidence import (
            EvidenceType,
        )

        evaluator = EvidenceEvaluator(Mock())
        result = evaluator._parse_evidence_type("correlation")

        assert result == EvidenceType.CORRELATION

    def test_parse_speculation(self):
        """Test parsing speculation type."""
        from local_deep_research.advanced_search_system.evidence.evaluator import (
            EvidenceEvaluator,
        )
        from local_deep_research.advanced_search_system.evidence.base_evidence import (
            EvidenceType,
        )

        evaluator = EvidenceEvaluator(Mock())
        result = evaluator._parse_evidence_type("speculation")

        assert result == EvidenceType.SPECULATION

    def test_parse_case_insensitive(self):
        """Test parsing is case insensitive."""
        from local_deep_research.advanced_search_system.evidence.evaluator import (
            EvidenceEvaluator,
        )
        from local_deep_research.advanced_search_system.evidence.base_evidence import (
            EvidenceType,
        )

        evaluator = EvidenceEvaluator(Mock())

        assert (
            evaluator._parse_evidence_type("DIRECT_STATEMENT")
            == EvidenceType.DIRECT_STATEMENT
        )
        assert (
            evaluator._parse_evidence_type("News_Report")
            == EvidenceType.NEWS_REPORT
        )

    def test_parse_unknown_defaults_to_speculation(self):
        """Test unknown type defaults to speculation."""
        from local_deep_research.advanced_search_system.evidence.evaluator import (
            EvidenceEvaluator,
        )
        from local_deep_research.advanced_search_system.evidence.base_evidence import (
            EvidenceType,
        )

        evaluator = EvidenceEvaluator(Mock())
        result = evaluator._parse_evidence_type("unknown_type")

        assert result == EvidenceType.SPECULATION


class TestAssessMatchQuality:
    """Tests for _assess_match_quality method."""

    def test_exact_match_returns_one(self):
        """Test exact value match returns 1.0."""
        from local_deep_research.advanced_search_system.evidence.evaluator import (
            EvidenceEvaluator,
        )
        from local_deep_research.advanced_search_system.evidence.base_evidence import (
            Evidence,
            EvidenceType,
        )
        from local_deep_research.advanced_search_system.constraints.base_constraint import (
            Constraint,
            ConstraintType,
        )

        evaluator = EvidenceEvaluator(Mock())
        evidence = Evidence(
            claim="The population is 1000000",
            type=EvidenceType.STATISTICAL_DATA,
            source="Census",
        )
        constraint = Constraint(
            id="test",
            type=ConstraintType.STATISTIC,
            value="1000000",
            description="Population count",
        )

        quality = evaluator._assess_match_quality(evidence, constraint)

        assert quality == 1.0

    def test_partial_word_match_returns_high(self):
        """Test partial word match returns 0.8."""
        from local_deep_research.advanced_search_system.evidence.evaluator import (
            EvidenceEvaluator,
        )
        from local_deep_research.advanced_search_system.evidence.base_evidence import (
            Evidence,
            EvidenceType,
        )
        from local_deep_research.advanced_search_system.constraints.base_constraint import (
            Constraint,
            ConstraintType,
        )

        evaluator = EvidenceEvaluator(Mock())
        evidence = Evidence(
            claim="The city has a large population",
            type=EvidenceType.NEWS_REPORT,
            source="News",
        )
        constraint = Constraint(
            id="test",
            type=ConstraintType.PROPERTY,
            value="large population growth",
            description="Population growth",
        )

        quality = evaluator._assess_match_quality(evidence, constraint)

        assert quality == 0.8

    def test_no_match_returns_partial(self):
        """Test no match returns 0.6."""
        from local_deep_research.advanced_search_system.evidence.evaluator import (
            EvidenceEvaluator,
        )
        from local_deep_research.advanced_search_system.evidence.base_evidence import (
            Evidence,
            EvidenceType,
        )
        from local_deep_research.advanced_search_system.constraints.base_constraint import (
            Constraint,
            ConstraintType,
        )

        evaluator = EvidenceEvaluator(Mock())
        evidence = Evidence(
            claim="The sky is blue",
            type=EvidenceType.INFERENCE,
            source="Observation",
        )
        constraint = Constraint(
            id="test",
            type=ConstraintType.PROPERTY,
            value="red coloring",
            description="Color property",
        )

        quality = evaluator._assess_match_quality(evidence, constraint)

        assert quality == 0.6

    def test_case_insensitive_match(self):
        """Test match is case insensitive."""
        from local_deep_research.advanced_search_system.evidence.evaluator import (
            EvidenceEvaluator,
        )
        from local_deep_research.advanced_search_system.evidence.base_evidence import (
            Evidence,
            EvidenceType,
        )
        from local_deep_research.advanced_search_system.constraints.base_constraint import (
            Constraint,
            ConstraintType,
        )

        evaluator = EvidenceEvaluator(Mock())
        evidence = Evidence(
            claim="PARIS is the capital",
            type=EvidenceType.DIRECT_STATEMENT,
            source="Encyclopedia",
        )
        constraint = Constraint(
            id="test",
            type=ConstraintType.PROPERTY,
            value="paris",
            description="Capital city",
        )

        quality = evaluator._assess_match_quality(evidence, constraint)

        assert quality == 1.0


class TestExtractEvidence:
    """Tests for extract_evidence method."""

    @patch(
        "local_deep_research.advanced_search_system.evidence.evaluator.remove_think_tags"
    )
    def test_extract_evidence_calls_model(self, mock_remove_tags):
        """Test that extract_evidence calls the model."""
        from local_deep_research.advanced_search_system.evidence.evaluator import (
            EvidenceEvaluator,
        )
        from local_deep_research.advanced_search_system.constraints.base_constraint import (
            Constraint,
            ConstraintType,
        )

        mock_model = Mock()
        mock_model.invoke.return_value = Mock(
            content="""CLAIM: Test claim
TYPE: direct_statement
SOURCE: Test source
CONFIDENCE: 0.8
REASONING: Test reasoning
QUOTE: Test quote"""
        )
        mock_remove_tags.side_effect = lambda x: x

        evaluator = EvidenceEvaluator(mock_model)
        constraint = Constraint(
            id="test",
            type=ConstraintType.PROPERTY,
            value="test value",
            description="Test description",
        )

        evaluator.extract_evidence("search results", "candidate", constraint)

        mock_model.invoke.assert_called_once()

    @patch(
        "local_deep_research.advanced_search_system.evidence.evaluator.remove_think_tags"
    )
    def test_extract_evidence_returns_evidence_object(self, mock_remove_tags):
        """Test that extract_evidence returns Evidence object."""
        from local_deep_research.advanced_search_system.evidence.evaluator import (
            EvidenceEvaluator,
        )
        from local_deep_research.advanced_search_system.evidence.base_evidence import (
            Evidence,
        )
        from local_deep_research.advanced_search_system.constraints.base_constraint import (
            Constraint,
            ConstraintType,
        )

        mock_model = Mock()
        mock_model.invoke.return_value = Mock(
            content="""CLAIM: Test claim
TYPE: news_report
SOURCE: News outlet
CONFIDENCE: 0.75
REASONING: From news
QUOTE: The quote"""
        )
        mock_remove_tags.side_effect = lambda x: x

        evaluator = EvidenceEvaluator(mock_model)
        constraint = Constraint(
            id="test",
            type=ConstraintType.EVENT,
            value="test value",
            description="Test description",
        )

        result = evaluator.extract_evidence(
            "search results", "candidate", constraint
        )

        assert isinstance(result, Evidence)
        assert result.claim == "Test claim"
        assert result.source == "News outlet"

    @patch(
        "local_deep_research.advanced_search_system.evidence.evaluator.remove_think_tags"
    )
    def test_extract_evidence_handles_invalid_confidence(
        self, mock_remove_tags
    ):
        """Test that invalid confidence is handled."""
        from local_deep_research.advanced_search_system.evidence.evaluator import (
            EvidenceEvaluator,
        )
        from local_deep_research.advanced_search_system.constraints.base_constraint import (
            Constraint,
            ConstraintType,
        )

        mock_model = Mock()
        mock_model.invoke.return_value = Mock(
            content="""CLAIM: Test claim
TYPE: inference
SOURCE: Analysis
CONFIDENCE: not_a_number"""
        )
        mock_remove_tags.side_effect = lambda x: x

        evaluator = EvidenceEvaluator(mock_model)
        constraint = Constraint(
            id="test",
            type=ConstraintType.PROPERTY,
            value="test",
            description="Test",
        )

        result = evaluator.extract_evidence(
            "search results", "candidate", constraint
        )

        # Should default to 0.5 when parsing fails
        assert result.confidence > 0

    @patch(
        "local_deep_research.advanced_search_system.evidence.evaluator.remove_think_tags"
    )
    def test_extract_evidence_includes_metadata(self, mock_remove_tags):
        """Test that metadata is included in evidence."""
        from local_deep_research.advanced_search_system.evidence.evaluator import (
            EvidenceEvaluator,
        )
        from local_deep_research.advanced_search_system.constraints.base_constraint import (
            Constraint,
            ConstraintType,
        )

        mock_model = Mock()
        mock_model.invoke.return_value = Mock(
            content="""CLAIM: Test claim
TYPE: direct_statement
SOURCE: Test
CONFIDENCE: 0.9"""
        )
        mock_remove_tags.side_effect = lambda x: x

        evaluator = EvidenceEvaluator(mock_model)
        constraint = Constraint(
            id="constraint_123",
            type=ConstraintType.PROPERTY,
            value="test",
            description="Test",
        )

        result = evaluator.extract_evidence(
            "search results", "test_candidate", constraint
        )

        assert result.metadata["candidate"] == "test_candidate"
        assert result.metadata["constraint_id"] == "constraint_123"
        assert result.metadata["constraint_type"] == "property"
