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

import pytest
from unittest.mock import MagicMock, patch

from local_deep_research.advanced_search_system.strategies.followup.enhanced_contextual_followup import (
    EnhancedContextualFollowUpStrategy,
)


@pytest.fixture
def make_strategy():
    """Factory to create strategy with controlled research_context."""

    def _make(research_context=None):
        with patch.object(
            EnhancedContextualFollowUpStrategy,
            "__init__",
            lambda self, *a, **kw: None,
        ):
            s = EnhancedContextualFollowUpStrategy.__new__(
                EnhancedContextualFollowUpStrategy
            )
            s.model = MagicMock()
            s.search = MagicMock()
            s.delegate_strategy = MagicMock()
            s.research_context = research_context or {}
            s.relevance_filter = MagicMock()
            s.context_manager = MagicMock()
            s.question_generator = MagicMock()
            s.combine_sources = True
            s.settings_snapshot = {}
            s.progress_callback = None
            s.all_links_of_system = []

            # Mock context_manager.build_context
            s.context_manager.build_context = MagicMock(
                return_value={
                    "past_sources": [],
                    "past_findings": "",
                    "summary": "",
                    "key_entities": [],
                }
            )

            s.full_context = s._build_full_context()
            return s

    return _make


# --- _build_full_context ---


class TestBuildFullContext:
    def test_no_research_context(self, make_strategy):
        s = make_strategy(research_context=None)
        # When no research_context, returns default empty context
        ctx = s.full_context
        assert ctx["past_sources"] == []
        assert ctx["past_findings"] == ""
        assert ctx["original_query"] == ""

    def test_with_research_context_resources(self, make_strategy):
        s = make_strategy(
            research_context={
                "resources": [{"url": "http://a.com"}],
                "past_findings": "Some findings",
                "original_query": "What is X?",
            }
        )
        # Re-build to use the actual research_context
        s.full_context = s._build_full_context()
        assert len(s.full_context["past_sources"]) >= 1

    def test_field_fallback_all_links(self, make_strategy):
        s = make_strategy(
            research_context={
                "all_links_of_system": [{"url": "http://b.com"}],
            }
        )
        s.full_context = s._build_full_context()
        assert len(s.full_context["past_sources"]) >= 1

    def test_field_fallback_past_links(self, make_strategy):
        s = make_strategy(
            research_context={
                "past_links": [{"url": "http://c.com"}],
            }
        )
        s.full_context = s._build_full_context()
        assert len(s.full_context["past_sources"]) >= 1

    def test_past_findings_extracted(self, make_strategy):
        s = make_strategy(
            research_context={
                "past_findings": "Important discovery about X",
            }
        )
        s.full_context = s._build_full_context()
        assert s.full_context["past_findings"] == "Important discovery about X"

    def test_original_query_extracted(self, make_strategy):
        s = make_strategy(
            research_context={
                "original_query": "What is quantum computing?",
            }
        )
        s.full_context = s._build_full_context()
        assert s.full_context["original_query"] == "What is quantum computing?"


# --- _inject_context_into_delegate ---


class TestInjectContextIntoDelegate:
    def test_url_dedup(self, make_strategy):
        s = make_strategy()
        s.delegate_strategy.all_links_of_system = [
            {"url": "http://existing.com"},
        ]

        sources = [
            {"url": "http://existing.com"},
            {"url": "http://new.com", "relevance_score": 0.8},
        ]
        s._inject_context_into_delegate(sources, "query")

        urls = [link["url"] for link in s.delegate_strategy.all_links_of_system]
        assert urls.count("http://existing.com") == 1
        assert "http://new.com" in urls

    def test_from_past_research_marking(self, make_strategy):
        s = make_strategy()
        s.delegate_strategy.all_links_of_system = []

        sources = [{"url": "http://test.com"}]
        s._inject_context_into_delegate(sources, "query")

        injected = s.delegate_strategy.all_links_of_system[0]
        assert injected["from_past_research"] is True

    def test_insert_at_beginning(self, make_strategy):
        s = make_strategy()
        s.delegate_strategy.all_links_of_system = [
            {"url": "http://original.com"},
        ]

        sources = [{"url": "http://priority.com"}]
        s._inject_context_into_delegate(sources, "query")

        assert (
            s.delegate_strategy.all_links_of_system[0]["url"]
            == "http://priority.com"
        )

    def test_set_followup_context_called(self, make_strategy):
        s = make_strategy()
        s.delegate_strategy.all_links_of_system = []
        s.delegate_strategy.set_followup_context = MagicMock()
        s.full_context = {"summary": "test", "key_entities": ["X"]}

        s._inject_context_into_delegate([], "query")
        s.delegate_strategy.set_followup_context.assert_called_once()

    def test_empty_sources_no_injection(self, make_strategy):
        s = make_strategy()
        s.delegate_strategy.all_links_of_system = [{"url": "http://a.com"}]

        s._inject_context_into_delegate([], "query")
        assert len(s.delegate_strategy.all_links_of_system) == 1

    def test_initializes_empty_list_if_needed(self, make_strategy):
        s = make_strategy()
        s.delegate_strategy.all_links_of_system = None

        sources = [{"url": "http://new.com"}]
        s._inject_context_into_delegate(sources, "query")

        # Should not crash - initializes to []
        assert len(s.delegate_strategy.all_links_of_system) >= 0


# --- Source combination in analyze_topic ---


class TestSourceCombination:
    def test_dedup_in_combine(self, make_strategy):
        s = make_strategy()
        s.full_context = {
            "past_sources": [{"url": "http://old.com"}],
            "follow_up_query": "",
            "past_findings": "",
            "original_query": "",
        }
        s.combine_sources = True
        s.delegate_strategy.analyze_topic = MagicMock(
            return_value={
                "all_links_of_system": [
                    {"url": "http://old.com"},
                    {"url": "http://new.com"},
                ],
            }
        )
        s._filter_relevant_sources = MagicMock(return_value=[])
        s._inject_context_into_delegate = MagicMock()
        s._update_progress = MagicMock()
        s.question_generator.generate_contextualized_query = MagicMock(
            return_value="query"
        )

        result = s.analyze_topic("follow-up question")
        urls = [link.get("url") for link in result["all_links_of_system"]]
        assert urls.count("http://old.com") == 1

    def test_past_research_tagging(self, make_strategy):
        s = make_strategy()
        s.full_context = {
            "past_sources": [{"url": "http://past.com"}],
            "follow_up_query": "",
            "past_findings": "",
            "original_query": "",
        }
        s.combine_sources = True
        s.delegate_strategy.analyze_topic = MagicMock(
            return_value={"all_links_of_system": []},
        )
        s._filter_relevant_sources = MagicMock(return_value=[])
        s._inject_context_into_delegate = MagicMock()
        s._update_progress = MagicMock()
        s.question_generator.generate_contextualized_query = MagicMock(
            return_value="query"
        )

        result = s.analyze_topic("follow-up")
        assert result["all_links_of_system"][0]["from_past_research"] is True


# --- Metadata assembly ---


class TestMetadataAssembly:
    def test_follow_up_enhancement_dict(self, make_strategy):
        s = make_strategy()
        s.full_context = {
            "past_sources": [],
            "follow_up_query": "",
            "past_findings": "",
            "original_query": "",
            "parent_research_id": "abc123",
        }
        s.delegate_strategy.analyze_topic = MagicMock(
            return_value={"all_links_of_system": []},
        )
        s._filter_relevant_sources = MagicMock(
            return_value=[{"url": "http://x.com"}]
        )
        s._inject_context_into_delegate = MagicMock()
        s._update_progress = MagicMock()
        s.question_generator.generate_contextualized_query = MagicMock(
            return_value="query"
        )

        result = s.analyze_topic("follow-up")
        meta = result["metadata"]["follow_up_enhancement"]
        assert meta["original_query"] == "follow-up"
        assert meta["contextualized"] is True
        assert meta["sources_reused"] == 1
        assert meta["parent_research_id"] == "abc123"
