"""
High-value pure logic tests for EvidenceEvaluator.

Tests cover:
- source_reliability dict entries
- _parse_evidence_response() parsing logic
- _parse_evidence_type() mapping and defaults
- _assess_match_quality() scoring
"""

import pytest
from unittest.mock import MagicMock

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,
)


@pytest.fixture
def evaluator():
    """Create an EvidenceEvaluator bypassing __init__."""
    obj = EvidenceEvaluator.__new__(EvidenceEvaluator)
    obj.model = MagicMock()
    obj.source_reliability = {
        "official": 1.0,
        "research": 0.95,
        "news": 0.8,
        "community": 0.6,
        "inference": 0.5,
        "speculation": 0.3,
    }
    return obj


# ---------------------------------------------------------------------------
# source_reliability dict tests
# ---------------------------------------------------------------------------


class TestSourceReliability:
    """Verify all 6 source_reliability entries."""

    def test_official_reliability(self, evaluator):
        assert evaluator.source_reliability["official"] == 1.0

    def test_research_reliability(self, evaluator):
        assert evaluator.source_reliability["research"] == 0.95

    def test_news_reliability(self, evaluator):
        assert evaluator.source_reliability["news"] == 0.8

    def test_community_reliability(self, evaluator):
        assert evaluator.source_reliability["community"] == 0.6

    def test_inference_reliability(self, evaluator):
        assert evaluator.source_reliability["inference"] == 0.5

    def test_speculation_reliability(self, evaluator):
        assert evaluator.source_reliability["speculation"] == 0.3


# ---------------------------------------------------------------------------
# _parse_evidence_response() tests
# ---------------------------------------------------------------------------


class TestParseEvidenceResponse:
    """Test key-value parsing from LLM output."""

    def test_basic_parsing(self, evaluator):
        content = (
            "CLAIM: The lake was formed by glaciers\n"
            "TYPE: direct_statement\n"
            "SOURCE: Wikipedia\n"
            "CONFIDENCE: 0.9\n"
            "REASONING: Clear geological evidence\n"
            "QUOTE: formed during the last ice age"
        )
        result = evaluator._parse_evidence_response(content)
        assert result["claim"] == "The lake was formed by glaciers"
        assert result["type"] == "direct_statement"
        assert result["source"] == "Wikipedia"
        assert result["confidence"] == "0.9"
        assert result["reasoning"] == "Clear geological evidence"
        assert result["quote"] == "formed during the last ice age"

    def test_confidence_regex_extracts_float(self, evaluator):
        content = "CONFIDENCE: approximately 0.85 based on evidence"
        result = evaluator._parse_evidence_response(content)
        assert result["confidence"] == "0.85"

    def test_confidence_integer_extraction(self, evaluator):
        content = "CONFIDENCE: 1"
        result = evaluator._parse_evidence_response(content)
        assert result["confidence"] == "1"

    def test_unknown_keys_ignored(self, evaluator):
        content = (
            "CLAIM: some claim\n"
            "EXTRA_FIELD: should be ignored\n"
            "NOTES: also ignored"
        )
        result = evaluator._parse_evidence_response(content)
        assert "claim" in result
        assert "extra_field" not in result
        assert "notes" not in result

    def test_missing_keys_return_empty_dict(self, evaluator):
        content = "No structured content here at all"
        result = evaluator._parse_evidence_response(content)
        assert isinstance(result, dict)
        assert len(result) == 0

    def test_value_with_colons(self, evaluator):
        """Values containing colons should be preserved after the first split."""
        content = "CLAIM: URL is https://example.com:8080/path"
        result = evaluator._parse_evidence_response(content)
        assert result["claim"] == "URL is https://example.com:8080/path"

    def test_leading_trailing_whitespace_stripped(self, evaluator):
        content = "  CLAIM:   lots of spaces   \n  TYPE:   inference  "
        result = evaluator._parse_evidence_response(content)
        assert result["claim"] == "lots of spaces"
        assert result["type"] == "inference"

    def test_case_insensitive_keys(self, evaluator):
        content = "Claim: mixed case key\nTYPE: speculation"
        result = evaluator._parse_evidence_response(content)
        assert result["claim"] == "mixed case key"
        assert result["type"] == "speculation"


# ---------------------------------------------------------------------------
# _parse_evidence_type() tests
# ---------------------------------------------------------------------------


class TestParseEvidenceType:
    """Test evidence type string-to-enum mapping."""

    @pytest.mark.parametrize(
        "type_str,expected",
        [
            ("direct_statement", EvidenceType.DIRECT_STATEMENT),
            ("official_record", EvidenceType.OFFICIAL_RECORD),
            ("research_finding", EvidenceType.RESEARCH_FINDING),
            ("news_report", EvidenceType.NEWS_REPORT),
            ("statistical_data", EvidenceType.STATISTICAL_DATA),
            ("inference", EvidenceType.INFERENCE),
            ("correlation", EvidenceType.CORRELATION),
            ("speculation", EvidenceType.SPECULATION),
        ],
    )
    def test_all_valid_types(self, evaluator, type_str, expected):
        assert evaluator._parse_evidence_type(type_str) == expected

    def test_case_insensitivity(self, evaluator):
        assert (
            evaluator._parse_evidence_type("DIRECT_STATEMENT")
            == EvidenceType.DIRECT_STATEMENT
        )
        assert (
            evaluator._parse_evidence_type("News_Report")
            == EvidenceType.NEWS_REPORT
        )

    def test_unknown_type_defaults_to_speculation(self, evaluator):
        assert (
            evaluator._parse_evidence_type("made_up_type")
            == EvidenceType.SPECULATION
        )

    def test_empty_string_defaults_to_speculation(self, evaluator):
        assert evaluator._parse_evidence_type("") == EvidenceType.SPECULATION


# ---------------------------------------------------------------------------
# _assess_match_quality() tests
# ---------------------------------------------------------------------------


class TestAssessMatchQuality:
    """Test match quality scoring between evidence and constraints."""

    def _make_evidence(self, claim: str) -> Evidence:
        return Evidence(
            claim=claim,
            type=EvidenceType.DIRECT_STATEMENT,
            source="test",
            confidence=0.9,
        )

    def _make_constraint(self, value: str) -> Constraint:
        return Constraint(
            id="c1",
            type=ConstraintType.PROPERTY,
            description="test constraint",
            value=value,
        )

    def test_exact_value_match_returns_1(self, evaluator):
        evidence = self._make_evidence("The lake was formed during ice age")
        constraint = self._make_constraint("formed during ice age")
        assert evaluator._assess_match_quality(evidence, constraint) == 1.0

    def test_partial_word_match_returns_0_8(self, evaluator):
        evidence = self._make_evidence("The trail has glacial features")
        constraint = self._make_constraint("glacial ice formations")
        # "glacial" appears in evidence claim
        assert evaluator._assess_match_quality(evidence, constraint) == 0.8

    def test_no_match_returns_0_6(self, evaluator):
        evidence = self._make_evidence("The river flows south")
        constraint = self._make_constraint("volcanic eruption")
        assert evaluator._assess_match_quality(evidence, constraint) == 0.6

    def test_case_insensitive_exact_match(self, evaluator):
        evidence = self._make_evidence("Contains BODY PART in name")
        constraint = self._make_constraint("body part")
        assert evaluator._assess_match_quality(evidence, constraint) == 1.0

    def test_case_insensitive_partial_match(self, evaluator):
        evidence = self._make_evidence("Located near MOUNTAINS")
        constraint = self._make_constraint("rocky mountains area")
        # "mountains" word matches
        assert evaluator._assess_match_quality(evidence, constraint) == 0.8
