"""Tests for exec tool."""

import pytest
from unittest.mock import AsyncMock, patch

from godotiq.tools.bridge.exec_code import exec_code


class TestExecCodeTool:
    @pytest.mark.asyncio
    async def test_empty_code(self):
        result = await exec_code(code="")
        assert result["status"] == "ERROR"

    @pytest.mark.asyncio
    async def test_no_code(self):
        result = await exec_code()
        assert result["status"] == "ERROR"
        assert "No code" in result["error"]

    @pytest.mark.asyncio
    async def test_valid_code(self):
        mock_bridge = AsyncMock()
        mock_bridge.request = AsyncMock(return_value={
            "status": "OK",
            "result": "42",
            "error": "",
        })
        with patch("godotiq.tools.bridge.exec_code.get_bridge", return_value=mock_bridge):
            result = await exec_code(code="func run():\n\treturn 42")
            assert result["status"] == "OK"
            assert result["result"] == "42"

    @pytest.mark.asyncio
    async def test_blocked_on_server(self):
        mock_bridge = AsyncMock()
        mock_bridge.request = AsyncMock(return_value={
            "status": "BLOCKED",
            "result": "",
            "error": "Code must start with 'func run():'",
        })
        with patch("godotiq.tools.bridge.exec_code.get_bridge", return_value=mock_bridge):
            result = await exec_code(code="print('hello')")
            assert result["status"] == "BLOCKED"

    @pytest.mark.asyncio
    async def test_compile_error(self):
        mock_bridge = AsyncMock()
        mock_bridge.request = AsyncMock(return_value={
            "status": "COMPILE_ERROR",
            "result": "",
            "error": "Compilation failed",
        })
        with patch("godotiq.tools.bridge.exec_code.get_bridge", return_value=mock_bridge):
            result = await exec_code(code="func run():\n\tvar x = :")
            assert result["status"] == "COMPILE_ERROR"

    @pytest.mark.asyncio
    async def test_default_timeout(self):
        mock_bridge = AsyncMock()
        mock_bridge.request = AsyncMock(return_value={"status": "OK"})
        with patch("godotiq.tools.bridge.exec_code.get_bridge", return_value=mock_bridge):
            await exec_code(code="func run():\n\treturn 1")
            call_kwargs = mock_bridge.request.call_args
            assert call_kwargs.kwargs.get("timeout") == 10.0 or call_kwargs[1].get("timeout") == 10.0

    @pytest.mark.asyncio
    async def test_custom_timeout(self):
        mock_bridge = AsyncMock()
        mock_bridge.request = AsyncMock(return_value={"status": "OK"})
        with patch("godotiq.tools.bridge.exec_code.get_bridge", return_value=mock_bridge):
            await exec_code(code="func run():\n\treturn 1", timeout_ms=3000)
            call_params = mock_bridge.request.call_args[1]["params"]
            assert call_params["timeout_ms"] == 3000

    @pytest.mark.asyncio
    async def test_params_passed_correctly(self):
        mock_bridge = AsyncMock()
        mock_bridge.request = AsyncMock(return_value={"status": "OK"})
        with patch("godotiq.tools.bridge.exec_code.get_bridge", return_value=mock_bridge):
            await exec_code(code="func run():\n\treturn 1", timeout_ms=7000)
            call_args = mock_bridge.request.call_args
            assert call_args[0][0] == "exec"
            params = call_args[1]["params"]
            assert params["code"] == "func run():\n\treturn 1"
            assert params["timeout_ms"] == 7000
