"""Tests for the code interpreter tool."""

from __future__ import annotations

from openjarvis.core.registry import ToolRegistry
from openjarvis.tools.code_interpreter import CodeInterpreterTool


class TestCodeInterpreterTool:
    def test_spec_name_and_category(self):
        tool = CodeInterpreterTool()
        assert tool.spec.name == "code_interpreter"
        assert tool.spec.category == "code"

    def test_spec_parameters_require_code(self):
        tool = CodeInterpreterTool()
        assert "code" in tool.spec.parameters["properties"]
        assert "code" in tool.spec.parameters["required"]

    def test_execute_simple_code(self):
        tool = CodeInterpreterTool()
        result = tool.execute(code="print(2 + 2)")
        assert result.success is True
        assert "4" in result.content

    def test_execute_with_imports(self):
        tool = CodeInterpreterTool()
        result = tool.execute(code="import math; print(round(math.pi, 5))")
        assert result.success is True
        assert "3.14159" in result.content

    def test_execute_multiline(self):
        tool = CodeInterpreterTool()
        code = "x = 10\ny = 20\nprint(x + y)"
        result = tool.execute(code=code)
        assert result.success is True
        assert "30" in result.content

    def test_timeout_protection(self):
        tool = CodeInterpreterTool(timeout=2)
        result = tool.execute(code="import time; time.sleep(10)")
        assert result.success is False
        assert "timed out" in result.content

    def test_syntax_error(self):
        tool = CodeInterpreterTool()
        result = tool.execute(code="def f(\n")
        assert result.success is False
        assert "SyntaxError" in result.content

    def test_runtime_error(self):
        tool = CodeInterpreterTool()
        result = tool.execute(code="print(1/0)")
        assert result.success is False
        assert "ZeroDivisionError" in result.content

    def test_dangerous_os_system_blocked(self):
        tool = CodeInterpreterTool()
        result = tool.execute(code="import os; os.system('ls')")
        assert result.success is False
        assert "Blocked" in result.content
        assert "os.system" in result.content

    def test_dangerous_subprocess_blocked(self):
        tool = CodeInterpreterTool()
        result = tool.execute(code="import subprocess; subprocess.run(['ls'])")
        assert result.success is False
        assert "Blocked" in result.content

    def test_dangerous_eval_blocked(self):
        tool = CodeInterpreterTool()
        result = tool.execute(code="eval('2+2')")
        assert result.success is False
        assert "Blocked" in result.content

    def test_dangerous_open_blocked(self):
        tool = CodeInterpreterTool()
        result = tool.execute(code="f = open('/etc/passwd')")
        assert result.success is False
        assert "Blocked" in result.content

    def test_no_code_provided(self):
        tool = CodeInterpreterTool()
        result = tool.execute(code="")
        assert result.success is False
        assert "No code" in result.content

    def test_no_code_param(self):
        tool = CodeInterpreterTool()
        result = tool.execute()
        assert result.success is False
        assert "No code" in result.content

    def test_output_truncation(self):
        tool = CodeInterpreterTool(max_output=50)
        result = tool.execute(code="print('A' * 200)")
        assert result.success is True
        assert "truncated" in result.content
        assert len(result.content) < 200

    def test_to_openai_function(self):
        tool = CodeInterpreterTool()
        fn = tool.to_openai_function()
        assert fn["type"] == "function"
        assert fn["function"]["name"] == "code_interpreter"
        assert "code" in fn["function"]["parameters"]["properties"]

    def test_returncode_in_metadata(self):
        tool = CodeInterpreterTool()
        result = tool.execute(code="print('ok')")
        assert result.success is True
        assert result.metadata["returncode"] == 0

    def test_returncode_nonzero_on_error(self):
        tool = CodeInterpreterTool()
        result = tool.execute(code="raise ValueError('boom')")
        assert result.success is False
        assert result.metadata["returncode"] != 0

    def test_no_output_produces_placeholder(self):
        tool = CodeInterpreterTool()
        result = tool.execute(code="x = 42")
        assert result.success is True
        assert result.content == "(no output)"

    def test_tool_id(self):
        tool = CodeInterpreterTool()
        assert tool.tool_id == "code_interpreter"

    def test_registry_registration(self):
        ToolRegistry.register_value("code_interpreter", CodeInterpreterTool)
        assert ToolRegistry.contains("code_interpreter")
