"""Tests for MCP tool registration wrappers in bridge/__init__.py."""

from __future__ import annotations

from unittest.mock import AsyncMock, patch

from godotiq.tools.bridge import (
    godotiq_scene_tree,
    godotiq_node_ops,
    godotiq_script_ops,
    godotiq_file_ops,
)


class TestSceneTreeRegistration:
    """scene_tree MCP wrapper exception handling."""

    async def test_catches_bridge_connection_error(self) -> None:
        """BridgeConnectionError is caught and returns a user-friendly message with hint."""
        from godotiq.bridge.connection import BridgeConnectionError

        with patch(
            "godotiq.tools.bridge.scene_tree.get_bridge",
            side_effect=BridgeConnectionError("not connected"),
        ):
            result = await godotiq_scene_tree()

        assert "error" in result
        assert "hint" in result

    async def test_catches_bridge_timeout_error(self) -> None:
        """BridgeTimeoutError is caught and returns a user-friendly message with hint."""
        from godotiq.bridge.connection import BridgeTimeoutError

        mock_bridge = AsyncMock()
        mock_bridge.request.side_effect = BridgeTimeoutError("timed out")
        with patch(
            "godotiq.tools.bridge.scene_tree.get_bridge",
            return_value=mock_bridge,
        ):
            result = await godotiq_scene_tree()

        assert "error" in result
        assert "hint" in result

    async def test_catches_bridge_error(self) -> None:
        """BridgeError is caught and returns error with code."""
        from godotiq.bridge.connection import BridgeError

        mock_bridge = AsyncMock()
        mock_bridge.request.side_effect = BridgeError("NOT_FOUND", "No scene open")
        with patch(
            "godotiq.tools.bridge.scene_tree.get_bridge",
            return_value=mock_bridge,
        ):
            result = await godotiq_scene_tree()

        assert "error" in result
        assert "NOT_FOUND" in result["error"]


class TestNodeOpsRegistration:
    """node_ops MCP wrapper exception handling."""

    async def test_catches_bridge_connection_error(self) -> None:
        """BridgeConnectionError is caught and returns a user-friendly message."""
        from godotiq.bridge.connection import BridgeConnectionError

        with patch(
            "godotiq.tools.bridge.node_ops.get_bridge",
            side_effect=BridgeConnectionError("not connected"),
        ):
            result = await godotiq_node_ops(
                operations=[{"op": "move", "node": "X", "position": [0, 0, 0]}]
            )

        assert "error" in result
        assert "hint" in result

    async def test_catches_bridge_timeout_error(self) -> None:
        """BridgeTimeoutError is caught and returns a user-friendly message."""
        from godotiq.bridge.connection import BridgeTimeoutError

        mock_bridge = AsyncMock()
        mock_bridge.request.side_effect = BridgeTimeoutError("timed out")
        with patch(
            "godotiq.tools.bridge.node_ops.get_bridge",
            return_value=mock_bridge,
        ):
            result = await godotiq_node_ops(
                operations=[{"op": "move", "node": "X", "position": [0, 0, 0]}]
            )

        assert "error" in result
        assert "hint" in result

    async def test_catches_bridge_error(self) -> None:
        """BridgeError is caught and returns error with code."""
        from godotiq.bridge.connection import BridgeError

        mock_bridge = AsyncMock()
        mock_bridge.request.side_effect = BridgeError("INVALID_OP", "Bad operation")
        with patch(
            "godotiq.tools.bridge.node_ops.get_bridge",
            return_value=mock_bridge,
        ):
            result = await godotiq_node_ops(
                operations=[{"op": "move", "node": "X", "position": [0, 0, 0]}]
            )

        assert "error" in result
        assert "INVALID_OP" in result["error"]

    async def test_catches_value_error(self) -> None:
        """ValueError from empty operations is caught."""
        result = await godotiq_node_ops(operations=[])

        assert "error" in result


class TestScriptOpsRegistration:
    """script_ops MCP wrapper exception handling."""

    async def test_catches_generic_exception(self) -> None:
        """Any unexpected Exception is caught and returns an error dict."""
        with patch(
            "godotiq.tools.bridge._script_ops",
            side_effect=RuntimeError("disk full"),
        ):
            result = await godotiq_script_ops(op="read", path="test.gd")

        assert "error" in result


class TestFileOpsRegistration:
    """file_ops MCP wrapper exception handling."""

    async def test_catches_generic_exception(self) -> None:
        """Any unexpected Exception is caught and returns an error dict."""
        with patch(
            "godotiq.tools.bridge._file_ops",
            side_effect=RuntimeError("permission denied"),
        ):
            result = await godotiq_file_ops(op="list", path=".")

        assert "error" in result
