"""Tests for KnowledgeBase: topic listing, search, user KB directory, and save_fix."""
import pytest
from pathlib import Path
from armorer.knowledge import KnowledgeBase


class TestKnowledgeBaseTopics:
    """Verify that all built-in knowledge topics are discovered."""

    def test_lists_builtin_topics(self):
        kb = KnowledgeBase()
        topics = kb.topics()
        # All built-in KB files should appear
        expected = [
            "arm_multiarch", "databases", "docker", "dockerfile_patterns",
            "error_patterns", "healthchecks", "networking", "openclaw",
            "security", "troubleshooting",
        ]
        for topic in expected:
            assert topic in topics, f"Missing built-in topic: {topic}"

    def test_get_single_topic(self):
        kb = KnowledgeBase()
        content = kb.get("docker")
        assert "Docker" in content or "docker" in content
        assert len(content) > 20

    def test_get_multiple_topics(self):
        kb = KnowledgeBase()
        content = kb.get("docker", "security")
        assert "Docker" in content or "docker" in content
        assert "Security" in content or "secret" in content.lower()

    def test_get_nonexistent_topic_returns_empty(self):
        kb = KnowledgeBase()
        content = kb.get("this_topic_does_not_exist")
        assert content == ""


class TestKnowledgeBaseSearch:
    """Verify keyword search across knowledge files."""

    def test_search_finds_relevant_content(self):
        kb = KnowledgeBase()
        result = kb.search("volume permissions")
        assert len(result) > 0
        assert "volume" in result.lower() or "permission" in result.lower()

    def test_search_respects_max_chars(self):
        kb = KnowledgeBase()
        result = kb.search("docker", max_chars=500)
        assert len(result) <= 600  # Allow a small margin for the last section

    def test_search_empty_query(self):
        kb = KnowledgeBase()
        assert kb.search("") == ""


class TestKnowledgeBaseExtraDirs:
    """Verify extra_dirs and user-contributed knowledge loading."""

    def test_extra_dir_topics_are_loaded(self, tmp_path):
        # Create a custom KB file in a temp directory
        custom_file = tmp_path / "custom_topic.md"
        custom_file.write_text("# Custom Topic\n\nThis is custom content for testing.")

        kb = KnowledgeBase(extra_dirs=[tmp_path])
        topics = kb.topics()
        assert "custom_topic" in topics

        content = kb.get("custom_topic")
        assert "custom content" in content.lower()

    def test_extra_dir_overrides_builtin(self, tmp_path):
        # Create a file with the same name as a built-in topic
        override = tmp_path / "docker.md"
        override.write_text("# Overridden Docker Topic\n\nThis overrides the built-in.")

        kb = KnowledgeBase(extra_dirs=[tmp_path])
        content = kb.get("docker")
        # Last dir wins, so the override should be returned
        assert "overrides the built-in" in content.lower()


class TestKnowledgeBaseSaveFix:
    """Verify save_fix persists learned repair patterns."""

    def test_save_fix_creates_file(self, tmp_path, monkeypatch):
        # Point _USER_KB_DIR to tmp_path so we don't pollute the real user dir
        import armorer.knowledge as kb_mod
        monkeypatch.setattr(kb_mod, "_USER_KB_DIR", tmp_path / "knowledge")

        kb = KnowledgeBase()
        result = kb.save_fix(
            error_pattern="exec format error",
            diagnosis="Binary compiled for wrong architecture",
            fix="Used multi-arch image instead",
        )
        assert result is True

        learned_file = tmp_path / "knowledge" / "learned_fixes.md"
        assert learned_file.exists()

        content = learned_file.read_text()
        assert "exec format error" in content
        assert "wrong architecture" in content
        assert "multi-arch" in content

    def test_save_fix_appends_to_existing(self, tmp_path, monkeypatch):
        import armorer.knowledge as kb_mod
        monkeypatch.setattr(kb_mod, "_USER_KB_DIR", tmp_path / "knowledge")

        kb = KnowledgeBase()
        kb.save_fix("error 1", "cause 1", "fix 1")
        kb.save_fix("error 2", "cause 2", "fix 2")

        content = (tmp_path / "knowledge" / "learned_fixes.md").read_text()
        assert "error 1" in content
        assert "error 2" in content
