"""
High-value pure logic tests for base_evidence module.

Tests EvidenceType enum values, base_confidence property,
and Evidence dataclass behavior including defaults and __post_init__.
"""

import pytest
from datetime import datetime

from local_deep_research.advanced_search_system.evidence.base_evidence import (
    Evidence,
    EvidenceType,
)


# ---------------------------------------------------------------------------
# EvidenceType enum: membership and value strings
# ---------------------------------------------------------------------------


class TestEvidenceTypeEnum:
    """Tests for EvidenceType enum values."""

    def test_direct_statement_value(self):
        assert EvidenceType.DIRECT_STATEMENT.value == "direct_statement"

    def test_official_record_value(self):
        assert EvidenceType.OFFICIAL_RECORD.value == "official_record"

    def test_research_finding_value(self):
        assert EvidenceType.RESEARCH_FINDING.value == "research_finding"

    def test_news_report_value(self):
        assert EvidenceType.NEWS_REPORT.value == "news_report"

    def test_statistical_data_value(self):
        assert EvidenceType.STATISTICAL_DATA.value == "statistical_data"

    def test_inference_value(self):
        assert EvidenceType.INFERENCE.value == "inference"

    def test_correlation_value(self):
        assert EvidenceType.CORRELATION.value == "correlation"

    def test_speculation_value(self):
        assert EvidenceType.SPECULATION.value == "speculation"

    def test_enum_has_exactly_eight_members(self):
        assert len(EvidenceType) == 8


# ---------------------------------------------------------------------------
# EvidenceType.base_confidence property
# ---------------------------------------------------------------------------


class TestEvidenceTypeBaseConfidence:
    """Tests for the base_confidence property on each enum member."""

    @pytest.mark.parametrize(
        "evidence_type, expected_confidence",
        [
            (EvidenceType.DIRECT_STATEMENT, 0.95),
            (EvidenceType.OFFICIAL_RECORD, 0.90),
            (EvidenceType.RESEARCH_FINDING, 0.85),
            (EvidenceType.STATISTICAL_DATA, 0.85),
            (EvidenceType.NEWS_REPORT, 0.75),
            (EvidenceType.INFERENCE, 0.50),
            (EvidenceType.CORRELATION, 0.30),
            (EvidenceType.SPECULATION, 0.10),
        ],
        ids=[
            "direct_statement",
            "official_record",
            "research_finding",
            "statistical_data",
            "news_report",
            "inference",
            "correlation",
            "speculation",
        ],
    )
    def test_base_confidence(self, evidence_type, expected_confidence):
        assert evidence_type.base_confidence == expected_confidence

    def test_highest_confidence_is_direct_statement(self):
        highest = max(EvidenceType, key=lambda t: t.base_confidence)
        assert highest is EvidenceType.DIRECT_STATEMENT

    def test_lowest_confidence_is_speculation(self):
        lowest = min(EvidenceType, key=lambda t: t.base_confidence)
        assert lowest is EvidenceType.SPECULATION


# ---------------------------------------------------------------------------
# Evidence dataclass: construction, defaults, __post_init__
# ---------------------------------------------------------------------------


class TestEvidenceDataclass:
    """Tests for the Evidence dataclass."""

    def test_required_fields_only(self):
        ev = Evidence(
            claim="The sky is blue",
            type=EvidenceType.DIRECT_STATEMENT,
            source="observation",
        )
        assert ev.claim == "The sky is blue"
        assert ev.type is EvidenceType.DIRECT_STATEMENT
        assert ev.source == "observation"

    def test_default_confidence_auto_set_from_type(self):
        """When confidence is left at default 0.0, __post_init__ sets it."""
        ev = Evidence(
            claim="claim",
            type=EvidenceType.OFFICIAL_RECORD,
            source="src",
        )
        assert ev.confidence == 0.90

    def test_explicit_confidence_preserved(self):
        """When confidence is explicitly provided (non-zero), it is kept."""
        ev = Evidence(
            claim="claim",
            type=EvidenceType.DIRECT_STATEMENT,
            source="src",
            confidence=0.42,
        )
        assert ev.confidence == 0.42

    def test_default_reasoning_is_none(self):
        ev = Evidence(claim="c", type=EvidenceType.INFERENCE, source="s")
        assert ev.reasoning is None

    def test_default_raw_text_is_none(self):
        ev = Evidence(claim="c", type=EvidenceType.INFERENCE, source="s")
        assert ev.raw_text is None

    def test_default_metadata_is_empty_dict(self):
        ev = Evidence(claim="c", type=EvidenceType.INFERENCE, source="s")
        assert ev.metadata == {}
        assert isinstance(ev.metadata, dict)

    def test_metadata_default_is_not_shared_across_instances(self):
        """Each instance should get its own dict, not a shared mutable default."""
        ev1 = Evidence(claim="c1", type=EvidenceType.INFERENCE, source="s")
        ev2 = Evidence(claim="c2", type=EvidenceType.INFERENCE, source="s")
        ev1.metadata["key"] = "value"
        assert "key" not in ev2.metadata

    def test_timestamp_auto_generated(self):
        ev = Evidence(claim="c", type=EvidenceType.INFERENCE, source="s")
        assert isinstance(ev.timestamp, str)
        # Should be a valid ISO-format timestamp
        parsed = datetime.fromisoformat(ev.timestamp)
        assert isinstance(parsed, datetime)

    def test_timestamp_is_recent(self):
        before = datetime.utcnow()
        ev = Evidence(claim="c", type=EvidenceType.INFERENCE, source="s")
        parsed = datetime.fromisoformat(ev.timestamp.replace("+00:00", ""))
        # Timestamp should be within a few seconds of now
        delta = abs((parsed - before).total_seconds())
        assert delta < 5

    def test_all_fields_set_explicitly(self):
        ev = Evidence(
            claim="test claim",
            type=EvidenceType.SPECULATION,
            source="test source",
            confidence=0.77,
            reasoning="some reasoning",
            raw_text="raw text here",
            metadata={"key": "val"},
        )
        assert ev.claim == "test claim"
        assert ev.type is EvidenceType.SPECULATION
        assert ev.source == "test source"
        assert ev.confidence == 0.77
        assert ev.reasoning == "some reasoning"
        assert ev.raw_text == "raw text here"
        assert ev.metadata == {"key": "val"}

    def test_post_init_each_type_sets_correct_confidence(self):
        """Verify __post_init__ sets the right confidence for every type."""
        for et in EvidenceType:
            ev = Evidence(claim="c", type=et, source="s")
            assert ev.confidence == et.base_confidence, (
                f"Expected {et.base_confidence} for {et.name}, got {ev.confidence}"
            )

    def test_confidence_zero_triggers_auto_set(self):
        """Explicitly passing confidence=0.0 should still trigger auto-set."""
        ev = Evidence(
            claim="c",
            type=EvidenceType.RESEARCH_FINDING,
            source="s",
            confidence=0.0,
        )
        assert ev.confidence == 0.85
