"""
Pure-logic tests for EvidenceEvaluator parsing and scoring helpers.

Tests _parse_evidence_response, _parse_evidence_type, and
_assess_match_quality — no LLM or search calls.
"""

from unittest.mock import Mock

from local_deep_research.advanced_search_system.constraints.base_constraint import (
    Constraint,
    ConstraintType,
)
from local_deep_research.advanced_search_system.evidence.base_evidence import (
    Evidence,
    EvidenceType,
)
from local_deep_research.advanced_search_system.evidence.evaluator import (
    EvidenceEvaluator,
)


def _evaluator():
    return EvidenceEvaluator(model=Mock())


def _constraint(value="test value"):
    return Constraint(
        id="c1",
        type=ConstraintType.PROPERTY,
        description=value,
        value=value,
        weight=1.0,
    )


def _evidence(claim="test claim"):
    return Evidence(
        claim=claim,
        type=EvidenceType.DIRECT_STATEMENT,
        source="src",
        confidence=0.8,
    )


# ---------------------------------------------------------------------------
# _parse_evidence_response
# ---------------------------------------------------------------------------


class TestParseEvidenceResponse:
    """Verify LLM response parsing into evidence components."""

    def test_all_fields_parsed(self):
        """All standard fields are extracted."""
        ev = _evaluator()
        content = (
            "CLAIM: The mountain is tall\n"
            "TYPE: direct_statement\n"
            "SOURCE: Official survey\n"
            "CONFIDENCE: 0.85\n"
            "REASONING: Based on measurements\n"
            "QUOTE: It stands at 14411 feet"
        )
        result = ev._parse_evidence_response(content)
        assert result["claim"] == "The mountain is tall"
        assert result["type"] == "direct_statement"
        assert result["source"] == "Official survey"
        assert result["confidence"] == "0.85"
        assert result["reasoning"] == "Based on measurements"
        assert result["quote"] == "It stands at 14411 feet"

    def test_confidence_extracts_float_from_text(self):
        """Confidence value extracted from surrounding text."""
        ev = _evaluator()
        content = "CONFIDENCE: approximately 0.75 based on evidence"
        result = ev._parse_evidence_response(content)
        assert result["confidence"] == "0.75"

    def test_confidence_integer(self):
        """Integer confidence is extracted."""
        ev = _evaluator()
        content = "CONFIDENCE: 1"
        result = ev._parse_evidence_response(content)
        assert result["confidence"] == "1"

    def test_unknown_fields_ignored(self):
        """Fields not in the expected set are ignored."""
        ev = _evaluator()
        content = "CLAIM: test\nFOO: bar\nNOTES: something"
        result = ev._parse_evidence_response(content)
        assert "claim" in result
        assert "foo" not in result
        assert "notes" not in result

    def test_empty_content(self):
        """Empty content returns empty dict."""
        ev = _evaluator()
        result = ev._parse_evidence_response("")
        assert result == {}

    def test_no_colon_lines_skipped(self):
        """Lines without colons are skipped."""
        ev = _evaluator()
        content = "CLAIM: test\nThis line has no colon\nTYPE: inference"
        result = ev._parse_evidence_response(content)
        assert result["claim"] == "test"
        assert result["type"] == "inference"

    def test_colon_in_value(self):
        """Values containing colons are preserved."""
        ev = _evaluator()
        content = "CLAIM: the ratio is 3:1 for water"
        result = ev._parse_evidence_response(content)
        assert result["claim"] == "the ratio is 3:1 for water"

    def test_case_insensitive_keys(self):
        """Keys are matched case-insensitively."""
        ev = _evaluator()
        content = "Claim: hello\nType: inference"
        result = ev._parse_evidence_response(content)
        assert result["claim"] == "hello"
        assert result["type"] == "inference"


# ---------------------------------------------------------------------------
# _parse_evidence_type
# ---------------------------------------------------------------------------


class TestParseEvidenceType:
    """Verify evidence type string mapping."""

    def test_direct_statement(self):
        ev = _evaluator()
        assert (
            ev._parse_evidence_type("direct_statement")
            == EvidenceType.DIRECT_STATEMENT
        )

    def test_official_record(self):
        ev = _evaluator()
        assert (
            ev._parse_evidence_type("official_record")
            == EvidenceType.OFFICIAL_RECORD
        )

    def test_research_finding(self):
        ev = _evaluator()
        assert (
            ev._parse_evidence_type("research_finding")
            == EvidenceType.RESEARCH_FINDING
        )

    def test_news_report(self):
        ev = _evaluator()
        assert (
            ev._parse_evidence_type("news_report") == EvidenceType.NEWS_REPORT
        )

    def test_statistical_data(self):
        ev = _evaluator()
        assert (
            ev._parse_evidence_type("statistical_data")
            == EvidenceType.STATISTICAL_DATA
        )

    def test_inference(self):
        ev = _evaluator()
        assert ev._parse_evidence_type("inference") == EvidenceType.INFERENCE

    def test_correlation(self):
        ev = _evaluator()
        assert (
            ev._parse_evidence_type("correlation") == EvidenceType.CORRELATION
        )

    def test_speculation(self):
        ev = _evaluator()
        assert (
            ev._parse_evidence_type("speculation") == EvidenceType.SPECULATION
        )

    def test_unknown_defaults_to_speculation(self):
        ev = _evaluator()
        assert (
            ev._parse_evidence_type("unknown_type") == EvidenceType.SPECULATION
        )

    def test_case_insensitive(self):
        ev = _evaluator()
        assert (
            ev._parse_evidence_type("DIRECT_STATEMENT")
            == EvidenceType.DIRECT_STATEMENT
        )

    def test_mixed_case(self):
        ev = _evaluator()
        assert (
            ev._parse_evidence_type("News_Report") == EvidenceType.NEWS_REPORT
        )


# ---------------------------------------------------------------------------
# _assess_match_quality
# ---------------------------------------------------------------------------


class TestAssessMatchQuality:
    """Verify evidence-constraint match quality scoring."""

    def test_exact_match_returns_1(self):
        """Constraint value fully in claim returns 1.0."""
        ev = _evaluator()
        constraint = _constraint("Mount Rainier")
        evidence = _evidence("Mount Rainier is a volcano in Washington")
        assert ev._assess_match_quality(evidence, constraint) == 1.0

    def test_partial_word_match_returns_08(self):
        """Some constraint words in claim returns 0.8."""
        ev = _evaluator()
        constraint = _constraint("Mount Rainier elevation")
        evidence = _evidence("The elevation of the peak is 14411 feet")
        result = ev._assess_match_quality(evidence, constraint)
        assert result == 0.8

    def test_no_match_returns_06(self):
        """No constraint words in claim returns 0.6."""
        ev = _evaluator()
        constraint = _constraint("population density")
        evidence = _evidence("The weather is sunny today")
        result = ev._assess_match_quality(evidence, constraint)
        assert result == 0.6

    def test_case_insensitive_matching(self):
        """Matching is case-insensitive."""
        ev = _evaluator()
        constraint = _constraint("MOUNT RAINIER")
        evidence = _evidence("mount rainier is beautiful")
        assert ev._assess_match_quality(evidence, constraint) == 1.0

    def test_single_word_match(self):
        """Single word from multi-word constraint matches at 0.8."""
        ev = _evaluator()
        constraint = _constraint("tall mountain peak")
        evidence = _evidence("The mountain was first climbed in 1899")
        result = ev._assess_match_quality(evidence, constraint)
        assert result == 0.8
