"""Tests for vmcluster_mcp.server — structured_tool_handler decorator."""

import pytest

from vmcluster_mcp.models import ToolResult
from vmcluster_mcp.server import structured_tool_handler


class TestStructuredToolHandler:
    @pytest.mark.asyncio
    async def test_catches_value_error(self):
        @structured_tool_handler
        async def failing_tool():
            raise ValueError("test error")

        result = await failing_tool()
        assert result.success is False
        assert result.error is not None
        assert result.error.code == "INTERNAL_ERROR"
        assert "ValueError" in result.error.message
        assert "test error" in result.error.message
        assert result.error.recoverable is False

    @pytest.mark.asyncio
    async def test_catches_runtime_error(self):
        @structured_tool_handler
        async def failing_tool():
            raise RuntimeError("runtime boom")

        result = await failing_tool()
        assert result.success is False
        assert result.error.code == "INTERNAL_ERROR"
        assert "RuntimeError" in result.error.message

    @pytest.mark.asyncio
    async def test_passthrough_normal_return(self):
        @structured_tool_handler
        async def ok_tool():
            return ToolResult(success=True, result="all good")

        result = await ok_tool()
        assert result.success is True
        assert result.result == "all good"
        assert result.error is None

    @pytest.mark.asyncio
    async def test_preserves_functools_wraps(self):
        @structured_tool_handler
        async def my_named_tool():
            """My docstring."""
            return ToolResult(success=True, result="ok")

        assert my_named_tool.__name__ == "my_named_tool"
        assert my_named_tool.__doc__ == "My docstring."

    @pytest.mark.asyncio
    async def test_error_node_is_none(self):
        @structured_tool_handler
        async def failing_tool():
            raise Exception("generic")

        result = await failing_tool()
        assert result.error.node is None
