"""
Tests for advanced_search_system/knowledge/base_knowledge.py

Tests cover:
- BaseKnowledgeGenerator abstract class
- Initialization
- Abstract method requirements
- Utility methods (_validate_knowledge, _validate_links, _extract_key_points)
"""

from unittest.mock import Mock

import pytest


class TestBaseKnowledgeGeneratorInit:
    """Tests for BaseKnowledgeGenerator initialization."""

    def test_stores_model(self):
        """Test that model is stored."""
        from local_deep_research.advanced_search_system.knowledge.base_knowledge import (
            BaseKnowledgeGenerator,
        )

        class ConcreteGenerator(BaseKnowledgeGenerator):
            def generate(self, query, context):
                return ""

            def generate_knowledge(
                self, query, context="", current_knowledge="", questions=None
            ):
                return ""

            def generate_sub_knowledge(self, sub_query, context=""):
                return ""

            def compress_knowledge(
                self, current_knowledge, query, section_links, **kwargs
            ):
                return ""

            def format_citations(self, links):
                return ""

        mock_model = Mock()
        generator = ConcreteGenerator(mock_model)

        assert generator.model is mock_model


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

    def test_cannot_instantiate_directly(self):
        """Test that BaseKnowledgeGenerator cannot be instantiated."""
        from local_deep_research.advanced_search_system.knowledge.base_knowledge import (
            BaseKnowledgeGenerator,
        )

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

    def test_requires_generate(self):
        """Test that generate must be implemented."""
        from local_deep_research.advanced_search_system.knowledge.base_knowledge import (
            BaseKnowledgeGenerator,
        )

        class IncompleteGenerator(BaseKnowledgeGenerator):
            def generate_knowledge(
                self, query, context="", current_knowledge="", questions=None
            ):
                return ""

            def generate_sub_knowledge(self, sub_query, context=""):
                return ""

            def compress_knowledge(
                self, current_knowledge, query, section_links, **kwargs
            ):
                return ""

            def format_citations(self, links):
                return ""

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

    def test_requires_generate_knowledge(self):
        """Test that generate_knowledge must be implemented."""
        from local_deep_research.advanced_search_system.knowledge.base_knowledge import (
            BaseKnowledgeGenerator,
        )

        class IncompleteGenerator(BaseKnowledgeGenerator):
            def generate(self, query, context):
                return ""

            def generate_sub_knowledge(self, sub_query, context=""):
                return ""

            def compress_knowledge(
                self, current_knowledge, query, section_links, **kwargs
            ):
                return ""

            def format_citations(self, links):
                return ""

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

    def test_requires_generate_sub_knowledge(self):
        """Test that generate_sub_knowledge must be implemented."""
        from local_deep_research.advanced_search_system.knowledge.base_knowledge import (
            BaseKnowledgeGenerator,
        )

        class IncompleteGenerator(BaseKnowledgeGenerator):
            def generate(self, query, context):
                return ""

            def generate_knowledge(
                self, query, context="", current_knowledge="", questions=None
            ):
                return ""

            def compress_knowledge(
                self, current_knowledge, query, section_links, **kwargs
            ):
                return ""

            def format_citations(self, links):
                return ""

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

    def test_requires_compress_knowledge(self):
        """Test that compress_knowledge must be implemented."""
        from local_deep_research.advanced_search_system.knowledge.base_knowledge import (
            BaseKnowledgeGenerator,
        )

        class IncompleteGenerator(BaseKnowledgeGenerator):
            def generate(self, query, context):
                return ""

            def generate_knowledge(
                self, query, context="", current_knowledge="", questions=None
            ):
                return ""

            def generate_sub_knowledge(self, sub_query, context=""):
                return ""

            def format_citations(self, links):
                return ""

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

    def test_requires_format_citations(self):
        """Test that format_citations must be implemented."""
        from local_deep_research.advanced_search_system.knowledge.base_knowledge import (
            BaseKnowledgeGenerator,
        )

        class IncompleteGenerator(BaseKnowledgeGenerator):
            def generate(self, query, context):
                return ""

            def generate_knowledge(
                self, query, context="", current_knowledge="", questions=None
            ):
                return ""

            def generate_sub_knowledge(self, sub_query, context=""):
                return ""

            def compress_knowledge(
                self, current_knowledge, query, section_links, **kwargs
            ):
                return ""

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


class TestValidateKnowledge:
    """Tests for _validate_knowledge method."""

    def _create_concrete_generator(self):
        """Create a concrete generator for testing."""
        from local_deep_research.advanced_search_system.knowledge.base_knowledge import (
            BaseKnowledgeGenerator,
        )

        class ConcreteGenerator(BaseKnowledgeGenerator):
            def generate(self, query, context):
                return ""

            def generate_knowledge(
                self, query, context="", current_knowledge="", questions=None
            ):
                return ""

            def generate_sub_knowledge(self, sub_query, context=""):
                return ""

            def compress_knowledge(
                self, current_knowledge, query, section_links, **kwargs
            ):
                return ""

            def format_citations(self, links):
                return ""

        return ConcreteGenerator(Mock())

    def test_valid_knowledge_returns_true(self):
        """Test that valid knowledge returns True."""
        generator = self._create_concrete_generator()

        result = generator._validate_knowledge("This is valid knowledge")

        assert result is True

    def test_empty_knowledge_returns_false(self):
        """Test that empty knowledge returns False."""
        generator = self._create_concrete_generator()

        result = generator._validate_knowledge("")

        assert result is False

    def test_none_knowledge_returns_false(self):
        """Test that None knowledge returns False."""
        generator = self._create_concrete_generator()

        result = generator._validate_knowledge(None)

        assert result is False

    def test_non_string_knowledge_returns_false(self):
        """Test that non-string knowledge returns False."""
        generator = self._create_concrete_generator()

        result = generator._validate_knowledge(12345)

        assert result is False

    def test_list_knowledge_returns_false(self):
        """Test that list knowledge returns False."""
        generator = self._create_concrete_generator()

        result = generator._validate_knowledge(["knowledge", "items"])

        assert result is False


class TestValidateLinks:
    """Tests for _validate_links method."""

    def _create_concrete_generator(self):
        """Create a concrete generator for testing."""
        from local_deep_research.advanced_search_system.knowledge.base_knowledge import (
            BaseKnowledgeGenerator,
        )

        class ConcreteGenerator(BaseKnowledgeGenerator):
            def generate(self, query, context):
                return ""

            def generate_knowledge(
                self, query, context="", current_knowledge="", questions=None
            ):
                return ""

            def generate_sub_knowledge(self, sub_query, context=""):
                return ""

            def compress_knowledge(
                self, current_knowledge, query, section_links, **kwargs
            ):
                return ""

            def format_citations(self, links):
                return ""

        return ConcreteGenerator(Mock())

    def test_valid_links_returns_true(self):
        """Test that valid links return True."""
        generator = self._create_concrete_generator()

        result = generator._validate_links(
            ["https://example.com", "https://test.com"]
        )

        assert result is True

    def test_empty_list_returns_true(self):
        """Test that empty list is valid."""
        generator = self._create_concrete_generator()

        result = generator._validate_links([])

        assert result is True

    def test_non_list_returns_false(self):
        """Test that non-list returns False."""
        generator = self._create_concrete_generator()

        result = generator._validate_links("not a list")

        assert result is False

    def test_list_with_non_string_returns_false(self):
        """Test that list with non-string items returns False."""
        generator = self._create_concrete_generator()

        result = generator._validate_links(["valid", 123, "also valid"])

        assert result is False

    def test_none_returns_false(self):
        """Test that None returns False."""
        generator = self._create_concrete_generator()

        result = generator._validate_links(None)

        assert result is False


class TestExtractKeyPoints:
    """Tests for _extract_key_points method."""

    def _create_concrete_generator(self):
        """Create a concrete generator for testing."""
        from local_deep_research.advanced_search_system.knowledge.base_knowledge import (
            BaseKnowledgeGenerator,
        )

        class ConcreteGenerator(BaseKnowledgeGenerator):
            def generate(self, query, context):
                return ""

            def generate_knowledge(
                self, query, context="", current_knowledge="", questions=None
            ):
                return ""

            def generate_sub_knowledge(self, sub_query, context=""):
                return ""

            def compress_knowledge(
                self, current_knowledge, query, section_links, **kwargs
            ):
                return ""

            def format_citations(self, links):
                return ""

        return ConcreteGenerator(Mock())

    def test_splits_by_newlines(self):
        """Test that knowledge is split by newlines."""
        generator = self._create_concrete_generator()
        knowledge = "Point 1\nPoint 2\nPoint 3"

        result = generator._extract_key_points(knowledge)

        assert result == ["Point 1", "Point 2", "Point 3"]

    def test_handles_single_line(self):
        """Test handling single line knowledge."""
        generator = self._create_concrete_generator()
        knowledge = "Single point of knowledge"

        result = generator._extract_key_points(knowledge)

        assert result == ["Single point of knowledge"]

    def test_returns_list(self):
        """Test that result is always a list."""
        generator = self._create_concrete_generator()

        result = generator._extract_key_points("Some knowledge")

        assert isinstance(result, list)


class TestConcreteImplementation:
    """Tests for concrete implementation behavior."""

    def test_concrete_implementation_works(self):
        """Test that concrete implementation can be instantiated and used."""
        from local_deep_research.advanced_search_system.knowledge.base_knowledge import (
            BaseKnowledgeGenerator,
        )

        class ConcreteGenerator(BaseKnowledgeGenerator):
            def generate(self, query, context):
                return f"Generated: {query}"

            def generate_knowledge(
                self, query, context="", current_knowledge="", questions=None
            ):
                return f"Knowledge: {query}"

            def generate_sub_knowledge(self, sub_query, context=""):
                return f"Sub: {sub_query}"

            def compress_knowledge(
                self, current_knowledge, query, section_links, **kwargs
            ):
                return f"Compressed: {len(current_knowledge)} chars"

            def format_citations(self, links):
                return "\n".join(
                    f"[{idx}] {link}" for idx, link in enumerate(links, 1)
                )

        generator = ConcreteGenerator(Mock())

        assert generator.generate("test", "ctx") == "Generated: test"
        assert generator.generate_knowledge("test") == "Knowledge: test"
        assert generator.generate_sub_knowledge("sub") == "Sub: sub"
        assert "Compressed" in generator.compress_knowledge("text", "q", [])
        assert "[1]" in generator.format_citations(["link1"])
