"""
Tests for the BaseKnowledgeGenerator class.

Tests cover:
- Initialization
- Validation helpers
- Key point extraction
"""

from unittest.mock import Mock


class ConcreteKnowledgeGenerator:
    """Concrete implementation for testing the base pattern."""

    def __init__(self, model):
        self.model = model

    def generate(self, query, context):
        return "Generated knowledge"

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

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

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

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

    def _validate_knowledge(self, knowledge):
        if not knowledge or not isinstance(knowledge, str):
            return False
        return True

    def _validate_links(self, links):
        if not isinstance(links, list):
            return False
        if not all(isinstance(link, str) for link in links):
            return False
        return True

    def _extract_key_points(self, knowledge):
        return knowledge.split("\n")


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

    def test_init_stores_model(self):
        """Generator stores the model reference."""
        mock_model = Mock()
        generator = ConcreteKnowledgeGenerator(mock_model)
        assert generator.model is mock_model


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

    def test_validate_valid_knowledge(self):
        """Returns True for valid knowledge string."""
        mock_model = Mock()
        generator = ConcreteKnowledgeGenerator(mock_model)

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

        assert result is True

    def test_validate_empty_knowledge(self):
        """Returns False for empty knowledge."""
        mock_model = Mock()
        generator = ConcreteKnowledgeGenerator(mock_model)

        result = generator._validate_knowledge("")

        assert result is False

    def test_validate_none_knowledge(self):
        """Returns False for None knowledge."""
        mock_model = Mock()
        generator = ConcreteKnowledgeGenerator(mock_model)

        result = generator._validate_knowledge(None)

        assert result is False

    def test_validate_non_string_knowledge(self):
        """Returns False for non-string knowledge."""
        mock_model = Mock()
        generator = ConcreteKnowledgeGenerator(mock_model)

        result = generator._validate_knowledge(123)

        assert result is False


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

    def test_validate_valid_links(self):
        """Returns True for valid list of link strings."""
        mock_model = Mock()
        generator = ConcreteKnowledgeGenerator(mock_model)

        result = generator._validate_links(["https://a.com", "https://b.com"])

        assert result is True

    def test_validate_empty_links(self):
        """Returns True for empty list."""
        mock_model = Mock()
        generator = ConcreteKnowledgeGenerator(mock_model)

        result = generator._validate_links([])

        assert result is True

    def test_validate_non_list_links(self):
        """Returns False for non-list input."""
        mock_model = Mock()
        generator = ConcreteKnowledgeGenerator(mock_model)

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

        assert result is False

    def test_validate_links_with_non_string_elements(self):
        """Returns False if any element is not a string."""
        mock_model = Mock()
        generator = ConcreteKnowledgeGenerator(mock_model)

        result = generator._validate_links(["https://a.com", 123])

        assert result is False


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

    def test_extract_single_line(self):
        """Extracts single line as one key point."""
        mock_model = Mock()
        generator = ConcreteKnowledgeGenerator(mock_model)

        result = generator._extract_key_points("Single point")

        assert result == ["Single point"]

    def test_extract_multiple_lines(self):
        """Extracts multiple lines as multiple key points."""
        mock_model = Mock()
        generator = ConcreteKnowledgeGenerator(mock_model)

        result = generator._extract_key_points("Point 1\nPoint 2\nPoint 3")

        assert len(result) == 3
        assert "Point 1" in result
        assert "Point 2" in result
        assert "Point 3" in result

    def test_extract_empty_knowledge(self):
        """Handles empty knowledge."""
        mock_model = Mock()
        generator = ConcreteKnowledgeGenerator(mock_model)

        result = generator._extract_key_points("")

        assert result == [""]


class TestGenerateMethods:
    """Tests for generate methods."""

    def test_generate_returns_string(self):
        """generate returns a string."""
        mock_model = Mock()
        generator = ConcreteKnowledgeGenerator(mock_model)

        result = generator.generate("query", "context")

        assert isinstance(result, str)

    def test_generate_knowledge_returns_string(self):
        """generate_knowledge returns a string."""
        mock_model = Mock()
        generator = ConcreteKnowledgeGenerator(mock_model)

        result = generator.generate_knowledge("query")

        assert isinstance(result, str)

    def test_generate_sub_knowledge_returns_string(self):
        """generate_sub_knowledge returns a string."""
        mock_model = Mock()
        generator = ConcreteKnowledgeGenerator(mock_model)

        result = generator.generate_sub_knowledge("sub-query")

        assert isinstance(result, str)

    def test_compress_knowledge_returns_string(self):
        """compress_knowledge returns a string."""
        mock_model = Mock()
        generator = ConcreteKnowledgeGenerator(mock_model)

        result = generator.compress_knowledge("knowledge", "query", [])

        assert isinstance(result, str)

    def test_format_citations_returns_string(self):
        """format_citations returns a string."""
        mock_model = Mock()
        generator = ConcreteKnowledgeGenerator(mock_model)

        result = generator.format_citations(["https://a.com", "https://b.com"])

        assert isinstance(result, str)
        assert "[1]" in result
        assert "[2]" in result
