"""
Tests for advanced_search_system/questions/followup/base_followup_question.py

Tests cover:
- BaseFollowUpQuestionGenerator abstract class
- Initialization
- set_follow_up_context method
- generate_questions method
- Abstract method requirements
"""

from unittest.mock import Mock

import pytest


class TestBaseFollowUpQuestionGeneratorInit:
    """Tests for BaseFollowUpQuestionGenerator initialization."""

    def test_init_stores_model(self):
        """Test that model is stored."""
        from local_deep_research.advanced_search_system.questions.followup.base_followup_question import (
            BaseFollowUpQuestionGenerator,
        )

        class ConcreteGenerator(BaseFollowUpQuestionGenerator):
            def generate_contextualized_query(
                self, follow_up_query, original_query, past_findings, **kwargs
            ):
                return follow_up_query

        mock_model = Mock()
        generator = ConcreteGenerator(mock_model)

        assert generator.model is mock_model

    def test_init_creates_empty_follow_up_context(self):
        """Test that follow_up_context is initialized empty."""
        from local_deep_research.advanced_search_system.questions.followup.base_followup_question import (
            BaseFollowUpQuestionGenerator,
        )

        class ConcreteGenerator(BaseFollowUpQuestionGenerator):
            def generate_contextualized_query(
                self, follow_up_query, original_query, past_findings, **kwargs
            ):
                return follow_up_query

        generator = ConcreteGenerator(Mock())

        assert generator.follow_up_context == {}

    def test_inherits_from_base_question_generator(self):
        """Test that class inherits from BaseQuestionGenerator."""
        from local_deep_research.advanced_search_system.questions.followup.base_followup_question import (
            BaseFollowUpQuestionGenerator,
        )
        from local_deep_research.advanced_search_system.questions.base_question import (
            BaseQuestionGenerator,
        )

        assert issubclass(BaseFollowUpQuestionGenerator, BaseQuestionGenerator)


class TestSetFollowUpContext:
    """Tests for set_follow_up_context method."""

    def test_stores_context_dictionary(self):
        """Test that context dictionary is stored."""
        from local_deep_research.advanced_search_system.questions.followup.base_followup_question import (
            BaseFollowUpQuestionGenerator,
        )

        class ConcreteGenerator(BaseFollowUpQuestionGenerator):
            def generate_contextualized_query(
                self, follow_up_query, original_query, past_findings, **kwargs
            ):
                return follow_up_query

        generator = ConcreteGenerator(Mock())
        context = {
            "past_findings": "Previous research results",
            "original_query": "Original question",
            "follow_up_query": "Follow-up question",
            "past_sources": ["source1", "source2"],
            "key_entities": ["entity1", "entity2"],
        }

        generator.set_follow_up_context(context)

        assert generator.follow_up_context == context

    def test_overwrites_previous_context(self):
        """Test that new context overwrites previous."""
        from local_deep_research.advanced_search_system.questions.followup.base_followup_question import (
            BaseFollowUpQuestionGenerator,
        )

        class ConcreteGenerator(BaseFollowUpQuestionGenerator):
            def generate_contextualized_query(
                self, follow_up_query, original_query, past_findings, **kwargs
            ):
                return follow_up_query

        generator = ConcreteGenerator(Mock())

        generator.set_follow_up_context({"first": "context"})
        generator.set_follow_up_context({"second": "context"})

        assert generator.follow_up_context == {"second": "context"}
        assert "first" not in generator.follow_up_context

    def test_accepts_empty_context(self):
        """Test that empty context is accepted."""
        from local_deep_research.advanced_search_system.questions.followup.base_followup_question import (
            BaseFollowUpQuestionGenerator,
        )

        class ConcreteGenerator(BaseFollowUpQuestionGenerator):
            def generate_contextualized_query(
                self, follow_up_query, original_query, past_findings, **kwargs
            ):
                return follow_up_query

        generator = ConcreteGenerator(Mock())
        generator.set_follow_up_context({"some": "data"})
        generator.set_follow_up_context({})

        assert generator.follow_up_context == {}


class TestGenerateQuestions:
    """Tests for generate_questions method."""

    def test_returns_query_as_single_item_list(self):
        """Test that generate_questions returns query as single item list."""
        from local_deep_research.advanced_search_system.questions.followup.base_followup_question import (
            BaseFollowUpQuestionGenerator,
        )

        class ConcreteGenerator(BaseFollowUpQuestionGenerator):
            def generate_contextualized_query(
                self, follow_up_query, original_query, past_findings, **kwargs
            ):
                return follow_up_query

        generator = ConcreteGenerator(Mock())

        result = generator.generate_questions(
            current_knowledge="knowledge",
            query="test query",
            questions_per_iteration=5,
            questions_by_iteration={},
        )

        assert result == ["test query"]

    def test_ignores_questions_per_iteration(self):
        """Test that questions_per_iteration is ignored."""
        from local_deep_research.advanced_search_system.questions.followup.base_followup_question import (
            BaseFollowUpQuestionGenerator,
        )

        class ConcreteGenerator(BaseFollowUpQuestionGenerator):
            def generate_contextualized_query(
                self, follow_up_query, original_query, past_findings, **kwargs
            ):
                return follow_up_query

        generator = ConcreteGenerator(Mock())

        result = generator.generate_questions(
            current_knowledge="",
            query="query",
            questions_per_iteration=10,
            questions_by_iteration={},
        )

        # Should still return single item
        assert len(result) == 1

    def test_preserves_exact_query_string(self):
        """Test that the exact query string is preserved."""
        from local_deep_research.advanced_search_system.questions.followup.base_followup_question import (
            BaseFollowUpQuestionGenerator,
        )

        class ConcreteGenerator(BaseFollowUpQuestionGenerator):
            def generate_contextualized_query(
                self, follow_up_query, original_query, past_findings, **kwargs
            ):
                return follow_up_query

        generator = ConcreteGenerator(Mock())
        complex_query = "Complex query with special chars: @#$%"

        result = generator.generate_questions(
            current_knowledge="",
            query=complex_query,
            questions_per_iteration=5,
            questions_by_iteration={},
        )

        assert result[0] == complex_query


class TestAbstractMethods:
    """Tests for abstract method requirements."""

    def test_cannot_instantiate_directly(self):
        """Test that BaseFollowUpQuestionGenerator cannot be instantiated."""
        from local_deep_research.advanced_search_system.questions.followup.base_followup_question import (
            BaseFollowUpQuestionGenerator,
        )

        with pytest.raises(TypeError):
            BaseFollowUpQuestionGenerator(Mock())

    def test_requires_generate_contextualized_query(self):
        """Test that generate_contextualized_query must be implemented."""
        from local_deep_research.advanced_search_system.questions.followup.base_followup_question import (
            BaseFollowUpQuestionGenerator,
        )

        class IncompleteGenerator(BaseFollowUpQuestionGenerator):
            pass

        with pytest.raises(TypeError):
            IncompleteGenerator(Mock())


class TestConcreteImplementation:
    """Tests for concrete implementations."""

    def test_concrete_implementation_works(self):
        """Test that a complete concrete implementation works."""
        from local_deep_research.advanced_search_system.questions.followup.base_followup_question import (
            BaseFollowUpQuestionGenerator,
        )

        class ConcreteGenerator(BaseFollowUpQuestionGenerator):
            def generate_contextualized_query(
                self, follow_up_query, original_query, past_findings, **kwargs
            ):
                return f"Context: {original_query} -> {follow_up_query}"

        generator = ConcreteGenerator(Mock())

        result = generator.generate_contextualized_query(
            follow_up_query="follow up",
            original_query="original",
            past_findings="findings",
        )

        assert "original" in result
        assert "follow up" in result
