"""
Tests for the Tool Description Enhancer functionality.
"""

from typing import Any

import pytest

from src.tools.admin.tool_enhancer import ToolDescriptionEnhancer


class TestToolDescriptionEnhancer:
    """Test tool description enhancement functionality"""

    @pytest.fixture
    async def enhancer_tool(self):
        """Create a ToolDescriptionEnhancer instance for testing"""
        return ToolDescriptionEnhancer("enhance_tool_description", "Tool description enhancer")

    async def test_enhance_existing_tool_description(
        self, enhancer_tool, fastmcp_client, extract_tool_result
    ):
        """Test enhancing a known tool's description"""
        async with fastmcp_client as client:
            result = await client.call_tool(
                "enhance_tool_description", {"tool_name": "get_configurations"}
            )

            data = extract_tool_result(result)

            if "error" not in data:
                assert "tool_name" in data
                assert "original_description" in data
                assert "enhanced_description" in data
                assert "analysis" in data
                assert "recommendations" in data

                # Verify enhanced description has Args section
                enhanced_desc = data["enhanced_description"]
                assert "Args:" in enhanced_desc

                # Verify analysis contains parameters
                analysis = data["analysis"]
                assert "parameters" in analysis
                assert "examples" in analysis

    async def test_enhance_nonexistent_tool(
        self, enhancer_tool, fastmcp_client, extract_tool_result
    ):
        """Test error handling for non-existent tool"""
        async with fastmcp_client as client:
            result = await client.call_tool(
                "enhance_tool_description", {"tool_name": "nonexistent_tool"}
            )

            data = extract_tool_result(result)
            # Should return error for non-existent tool
            assert "error" in data or "not found" in str(result)

    async def test_parameter_analysis(self, enhancer_tool):
        """Test parameter analysis functionality"""
        # Test with our own tool to ensure consistent results
        analysis = await enhancer_tool._analyze_tool(
            None,  # ctx not needed for this test
            "enhance_tool_description",
            enhancer_tool.METADATA,
            ToolDescriptionEnhancer,
            generate_examples=True,
            include_response_format=True,
        )

        # Verify analysis structure
        assert "metadata" in analysis
        assert "parameters" in analysis
        assert "examples" in analysis
        assert "response_format" in analysis

        # Check specific parameters
        params = analysis["parameters"]
        assert "tool_name" in params
        assert params["tool_name"]["required"] is True
        assert "str" in params["tool_name"]["type"]

        assert "generate_examples" in params
        assert params["generate_examples"]["required"] is False
        assert "bool" in params["generate_examples"]["type"]

    async def test_admin_category_examples(self, enhancer_tool):
        """Test example generation for admin category tools"""
        parameters = {
            "conf_file": {"type": "str", "required": True},
            "stanza": {"type": "str", "required": False},
            "app_name": {"type": "str", "required": False},
        }

        examples = enhancer_tool._generate_admin_examples(parameters)

        # Verify admin-specific examples
        assert "conf_file" in examples
        assert "props" in examples["conf_file"]
        assert "transforms" in examples["conf_file"]

        assert "stanza" in examples
        assert "default" in examples["stanza"]

        assert "app_name" in examples
        assert isinstance(examples["app_name"], list)

    async def test_search_category_examples(self, enhancer_tool):
        """Test example generation for search category tools"""
        parameters = {
            "query": {"type": "str", "required": True},
            "earliest_time": {"type": "str", "required": False},
            "max_results": {"type": "int", "required": False},
        }

        examples = enhancer_tool._generate_search_examples(parameters)

        # Verify search-specific examples
        assert "query" in examples
        assert any("index=" in str(q) for q in examples["query"])

        assert "earliest_time" in examples
        assert "-24h@h" in examples["earliest_time"]

        assert "max_results" in examples
        assert 100 in examples["max_results"]

    async def test_metadata_category_examples(self, enhancer_tool):
        """Test example generation for metadata category tools"""
        parameters = {
            "index_name": {"type": "str", "required": True},
            "sourcetype": {"type": "str", "required": False},
        }

        examples = enhancer_tool._generate_metadata_examples(parameters)

        # Verify metadata-specific examples
        assert "index_name" in examples
        assert "main" in examples["index_name"]

        assert "sourcetype" in examples
        assert "access_combined" in examples["sourcetype"]

    async def test_generic_examples(self, enhancer_tool):
        """Test generic example generation"""
        parameters = {
            "string_param": {"type": "str", "required": True},
            "int_param": {"type": "int", "required": False},
            "bool_param": {"type": "bool", "required": False},
        }

        examples = enhancer_tool._generate_generic_examples(parameters)

        assert "string_param" in examples
        assert isinstance(examples["string_param"], list)

        assert "int_param" in examples
        assert isinstance(examples["int_param"], list)
        assert all(isinstance(x, int) for x in examples["int_param"])

        assert "bool_param" in examples
        assert True in examples["bool_param"]
        assert False in examples["bool_param"]

    async def test_enhanced_description_generation(self, enhancer_tool):
        """Test enhanced description generation"""
        # Mock analysis data
        analysis = {
            "parameters": {
                "tool_name": {
                    "type": "str",
                    "required": True,
                    "default": None,
                    "description": "Name of the tool to enhance",
                },
                "generate_examples": {
                    "type": "bool",
                    "required": False,
                    "default": "True",
                    "description": "Whether to generate examples",
                },
            },
            "examples": {
                "tool_name": ["get_configurations", "list_indexes"],
                "generate_examples": [True, False],
            },
            "response_format": {"type": "object", "common_fields": ["status"]},
        }

        enhanced_desc = await enhancer_tool._generate_enhanced_description(
            None,
            "test_tool",
            enhancer_tool.METADATA,
            analysis,  # ctx not needed
        )

        # Verify enhanced description structure
        assert "Args:" in enhanced_desc
        assert "tool_name (str):" in enhanced_desc
        assert "generate_examples (bool), optional:" in enhanced_desc
        assert "Example Values:" in enhanced_desc
        assert "Response Format:" in enhanced_desc

    async def test_recommendations_generation(self, enhancer_tool):
        """Test recommendation generation"""
        # Test with analysis that has undocumented parameters
        analysis = {
            "metadata": {"category": "admin", "requires_connection": True},
            "parameters": {
                "documented_param": {"description": "This is documented"},
                "undocumented_param": {"description": ""},
            },
            "examples": {},
        }

        recommendations = enhancer_tool._generate_recommendations(analysis)

        assert len(recommendations) > 0
        assert any("undocumented_param" in rec for rec in recommendations)

        # Test with well-documented analysis
        well_documented_analysis = {
            "metadata": {"category": "search", "requires_connection": False},
            "parameters": {
                "query": {"description": "Search query to execute"},
                "max_results": {"description": "Maximum number of results"},
            },
            "examples": {"query": ["index=main"], "max_results": [100]},
        }

        good_recommendations = enhancer_tool._generate_recommendations(well_documented_analysis)
        # For search category, we should get query validation suggestion
        assert any("query validation" in rec for rec in good_recommendations)

    async def test_parameter_description_extraction(self, enhancer_tool):
        """Test parameter description extraction from docstrings"""

        def sample_method(self, ctx, param1: str, param2: int = 100):
            """
            Sample method for testing.

            Args:
                param1 (str): First parameter description
                param2 (int, optional): Second parameter with default value

            Returns:
                Dict with results
            """
            pass

        # Test extraction for param1
        desc1 = enhancer_tool._extract_param_description_from_docstring(sample_method, "param1")
        assert "First parameter description" in desc1

        # Test extraction for param2
        desc2 = enhancer_tool._extract_param_description_from_docstring(sample_method, "param2")
        assert "Second parameter" in desc2

        # Test for non-existent parameter
        desc3 = enhancer_tool._extract_param_description_from_docstring(sample_method, "param3")
        assert desc3 == ""

    async def test_response_format_analysis(self, enhancer_tool):
        """Test response format analysis"""

        def sample_method(self) -> dict[str, Any]:
            """Sample method"""
            return {}

        response_format = enhancer_tool._analyze_response_format(sample_method)

        assert "type" in response_format
        assert "common_fields" in response_format
        assert "status" in response_format["common_fields"]
        assert response_format["type"] == "object"
