"""
Tests for Knowledge Base Tool
"""

import pytest
import os
import sys

sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

from services.router.tool_manager import ToolManager, ToolResult


class TestKnowledgeBaseTool:
    """Test KB tool functionality"""

    @pytest.mark.asyncio
    async def test_search_requires_query(self):
        """Test that search requires query"""
        tool_mgr = ToolManager({})
        
        result = await tool_mgr._kb_tool({
            "action": "search",
            "params": {}
        })
        
        assert result.success is False
        assert "query" in result.error.lower()

    @pytest.mark.asyncio
    async def test_search_returns_results(self):
        """Test search returns results structure"""
        tool_mgr = ToolManager({})
        
        result = await tool_mgr._kb_tool({
            "action": "search",
            "params": {
                "query": "test query",
                "limit": 10
            }
        })
        
        assert result.success is True
        assert "results" in result.result
        assert "summary" in result.result

    @pytest.mark.asyncio
    async def test_search_with_paths_filter(self):
        """Test search with paths filter"""
        tool_mgr = ToolManager({})
        
        result = await tool_mgr._kb_tool({
            "action": "search",
            "params": {
                "query": "test",
                "paths": ["docs"],
                "limit": 5
            }
        })
        
        assert result.success is True
        assert result.result["count"] >= 0

    @pytest.mark.asyncio
    async def test_snippets_requires_query(self):
        """Test snippets requires query"""
        tool_mgr = ToolManager({})
        
        result = await tool_mgr._kb_tool({
            "action": "snippets",
            "params": {}
        })
        
        assert result.success is False
        assert "query" in result.error.lower()

    @pytest.mark.asyncio
    async def test_snippets_returns_structure(self):
        """Test snippets returns proper structure"""
        tool_mgr = ToolManager({})
        
        result = await tool_mgr._kb_tool({
            "action": "snippets",
            "params": {
                "query": "test",
                "limit": 5
            }
        })
        
        assert result.success is True
        assert "results" in result.result

    @pytest.mark.asyncio
    async def test_open_requires_path(self):
        """Test open requires path"""
        tool_mgr = ToolManager({})
        
        result = await tool_mgr._kb_tool({
            "action": "open",
            "params": {}
        })
        
        assert result.success is False
        assert "path" in result.error.lower()

    @pytest.mark.asyncio
    async def test_open_blocks_traversal(self):
        """Test open blocks path traversal"""
        tool_mgr = ToolManager({})
        
        result = await tool_mgr._kb_tool({
            "action": "open",
            "params": {
                "path": "../../../etc/passwd"
            }
        })
        
        assert result.success is False
        assert "traversal" in result.error.lower()

    @pytest.mark.asyncio
    async def test_open_blocks_not_allowed_path(self):
        """Test open blocks not allowed paths"""
        tool_mgr = ToolManager({})
        
        result = await tool_mgr._kb_tool({
            "action": "open",
            "params": {
                "path": "services/router/tool_manager.py"
            }
        })
        
        assert result.success is False
        assert "not in allowed" in result.error.lower() or "not found" in result.error.lower()

    @pytest.mark.asyncio
    async def test_sources_returns_indexed(self):
        """Test sources returns indexed sources"""
        tool_mgr = ToolManager({})
        
        result = await tool_mgr._kb_tool({
            "action": "sources",
            "params": {}
        })
        
        assert result.success is True
        assert "sources" in result.result
        assert "allowed_paths" in result.result

    @pytest.mark.asyncio
    async def test_sources_with_paths_filter(self):
        """Test sources with paths filter"""
        tool_mgr = ToolManager({})
        
        result = await tool_mgr._kb_tool({
            "action": "sources",
            "params": {
                "paths": ["docs"]
            }
        })
        
        assert result.success is True

    @pytest.mark.asyncio
    async def test_unknown_action_returns_error(self):
        """Test unknown action returns error"""
        tool_mgr = ToolManager({})
        
        result = await tool_mgr._kb_tool({
            "action": "unknown_action",
            "params": {}
        })
        
        assert result.success is False
        assert "unknown action" in result.error.lower()

    @pytest.mark.asyncio
    async def test_search_with_file_glob(self):
        """Test search with file glob filter"""
        tool_mgr = ToolManager({})
        
        result = await tool_mgr._kb_tool({
            "action": "search",
            "params": {
                "query": "test",
                "file_glob": "**/*.md",
                "limit": 10
            }
        })
        
        assert result.success is True

    @pytest.mark.asyncio
    async def test_snippets_context_lines(self):
        """Test snippets with context lines"""
        tool_mgr = ToolManager({})
        
        result = await tool_mgr._kb_tool({
            "action": "snippets",
            "params": {
                "query": "test",
                "context_lines": 2,
                "limit": 3
            }
        })
        
        assert result.success is True

    @pytest.mark.asyncio
    async def test_open_with_line_range(self):
        """Test open with line range"""
        tool_mgr = ToolManager({})
        
        result = await tool_mgr._kb_tool({
            "action": "open",
            "params": {
                "path": "docs/README.md",
                "start_line": 1,
                "end_line": 10
            }
        })
        
        if result.success:
            assert "content" in result.result
            assert "start_line" in result.result

    @pytest.mark.asyncio
    async def test_search_result_structure(self):
        """Test search result has proper structure"""
        tool_mgr = ToolManager({})
        
        result = await tool_mgr._kb_tool({
            "action": "search",
            "params": {
                "query": "documentation",
                "limit": 5
            }
        })
        
        assert result.success is True
        if result.result["count"] > 0:
            r = result.result["results"][0]
            assert "path" in r
            assert "score" in r
            assert "highlights" in r

    @pytest.mark.asyncio
    async def test_redaction_of_secrets(self):
        """Test that secrets are redacted"""
        tool_mgr = ToolManager({})
        
        result = await tool_mgr._kb_tool({
            "action": "snippets",
            "params": {
                "query": "API_KEY",
                "limit": 1
            }
        })
        
        if result.success and result.result["count"] > 0:
            for snippet in result.result["results"]:
                text = snippet.get("text", "")
                assert "sk-***" in text or "API_KEY" not in text or "***" in text
