"""
RAG Provider 測試
================
Phase 13.2 #84 - Runbook RAG Tool

測試項目：
- Provider 初始化 (DI 注入 vs Lazy Load)
- Tool 列表
- Input 驗證
- 健康檢查

P1 修復: 2026-03-29 (首席架構師審查後補充)
"""

import pytest

from src.plugins.mcp.providers.rag_provider import RAGProvider


class TestRAGProviderInit:
    """Provider 初始化測試"""

    def test_init_without_service(self):
        """測試無參數初始化 (Lazy Load 模式)"""
        provider = RAGProvider()
        assert provider.name == "runbooks"
        assert provider._rag_service is None

    def test_init_with_service_injection(self):
        """測試 DI 注入模式"""

        class MockRAGService:
            """Minimal mock for DI testing"""

            async def search(self, query: str, top_k: int):
                return []

            async def get_index_stats(self):
                return {"status": "ok"}

        mock_service = MockRAGService()
        provider = RAGProvider(rag_service=mock_service)
        assert provider._rag_service is mock_service


class TestRAGProviderTools:
    """Tool 列表測試"""

    @pytest.mark.asyncio
    async def test_list_tools_returns_three_tools(self):
        """確認提供 3 個工具"""
        provider = RAGProvider()
        tools = await provider.list_tools()

        assert len(tools) == 3
        tool_names = {t.name for t in tools}
        assert tool_names == {"search_runbook", "index_documents", "get_index_stats"}

    @pytest.mark.asyncio
    async def test_search_runbook_tool_schema(self):
        """確認 search_runbook 的 schema 正確"""
        provider = RAGProvider()
        tools = await provider.list_tools()

        search_tool = next(t for t in tools if t.name == "search_runbook")
        schema = search_tool.input_schema

        assert "properties" in schema
        assert "query" in schema["properties"]
        assert schema["required"] == ["query"]

    @pytest.mark.asyncio
    async def test_index_documents_tool_schema(self):
        """確認 index_documents 的 schema 正確"""
        provider = RAGProvider()
        tools = await provider.list_tools()

        index_tool = next(t for t in tools if t.name == "index_documents")
        schema = index_tool.input_schema

        assert "properties" in schema
        assert "force" in schema["properties"]


class TestRAGProviderValidation:
    """Input 驗證測試"""

    @pytest.mark.asyncio
    async def test_search_without_query_returns_error(self):
        """空 query 應該返回錯誤"""

        class MockRAGService:
            async def search(self, query: str, top_k: int):
                return []

        provider = RAGProvider(rag_service=MockRAGService())
        result = await provider.execute("search_runbook", {"query": ""})

        assert result.success is True  # 執行成功但結果為空
        assert result.output["error"] == "Query is required"
        assert result.output["results"] == []

    @pytest.mark.asyncio
    async def test_search_top_k_limited_to_10(self):
        """top_k 應該被限制在 10 以內"""

        class MockRAGService:
            def __init__(self):
                self.last_top_k = None

            async def search(self, query: str, top_k: int):
                self.last_top_k = top_k
                return [{"content": "test", "score": 0.9}]

        mock_service = MockRAGService()
        provider = RAGProvider(rag_service=mock_service)

        await provider.execute("search_runbook", {"query": "test", "top_k": 100})
        assert mock_service.last_top_k == 10  # 應該被限制為 10

    @pytest.mark.asyncio
    async def test_unknown_tool_returns_error(self):
        """未知工具應該返回錯誤"""
        provider = RAGProvider()
        result = await provider.execute("unknown_tool", {})

        assert result.success is False
        assert "Unknown tool" in result.error


class TestRAGProviderClose:
    """Close 方法測試"""

    @pytest.mark.asyncio
    async def test_close_clears_service(self):
        """close 應該清理 service 引用"""

        class MockRAGService:
            pass

        provider = RAGProvider(rag_service=MockRAGService())
        assert provider._rag_service is not None

        await provider.close()
        assert provider._rag_service is None
