# tests/test_toolset_langchain.py
from __future__ import annotations

import pytest

langchain_core = pytest.importorskip("langchain_core")

from unittest.mock import AsyncMock, MagicMock  # noqa: E402

from agentsh_secure_sandbox.toolset.langchain import SecureSandboxToolkit  # noqa: E402


async def test_toolkit_get_tools_returns_three(monkeypatch):
    mock_secure = AsyncMock(return_value=AsyncMock())
    monkeypatch.setattr(
        "agentsh_secure_sandbox.toolset._base.secure_sandbox", mock_secure,
    )
    toolkit = SecureSandboxToolkit(MagicMock())
    async with toolkit:
        tools = toolkit.get_tools()
    assert len(tools) == 3
    names = {t.name for t in tools}
    assert names == {"run_command", "write_file", "read_file"}


async def test_toolkit_tools_are_base_tool(monkeypatch):
    from langchain_core.tools import BaseTool

    mock_secure = AsyncMock(return_value=AsyncMock())
    monkeypatch.setattr(
        "agentsh_secure_sandbox.toolset._base.secure_sandbox", mock_secure,
    )
    toolkit = SecureSandboxToolkit(MagicMock())
    async with toolkit:
        for tool in toolkit.get_tools():
            assert isinstance(tool, BaseTool)


async def test_run_command_arun(monkeypatch):
    mock_sandbox = AsyncMock()
    mock_sandbox.exec = AsyncMock(return_value=MagicMock(
        exit_code=0, stdout="hello\n", stderr="",
    ))
    mock_secure = AsyncMock(return_value=mock_sandbox)
    monkeypatch.setattr(
        "agentsh_secure_sandbox.toolset._base.secure_sandbox", mock_secure,
    )
    toolkit = SecureSandboxToolkit(MagicMock())
    async with toolkit:
        tools = {t.name: t for t in toolkit.get_tools()}
        result = await tools["run_command"].ainvoke({"command": "echo hello"})
    assert result == "hello\n"


async def test_write_file_arun(monkeypatch):
    mock_sandbox = AsyncMock()
    mock_sandbox.write_file = AsyncMock(return_value=MagicMock(
        success=True, path="/workspace/test.txt",
    ))
    mock_secure = AsyncMock(return_value=mock_sandbox)
    monkeypatch.setattr(
        "agentsh_secure_sandbox.toolset._base.secure_sandbox", mock_secure,
    )
    toolkit = SecureSandboxToolkit(MagicMock())
    async with toolkit:
        tools = {t.name: t for t in toolkit.get_tools()}
        result = await tools["write_file"].ainvoke({"path": "/workspace/test.txt", "content": "hi"})
    assert "Written to" in result


async def test_read_file_arun(monkeypatch):
    mock_sandbox = AsyncMock()
    mock_sandbox.read_file = AsyncMock(return_value=MagicMock(
        success=True, content="file content",
    ))
    mock_secure = AsyncMock(return_value=mock_sandbox)
    monkeypatch.setattr(
        "agentsh_secure_sandbox.toolset._base.secure_sandbox", mock_secure,
    )
    toolkit = SecureSandboxToolkit(MagicMock())
    async with toolkit:
        tools = {t.name: t for t in toolkit.get_tools()}
        result = await tools["read_file"].ainvoke({"path": "/workspace/test.txt"})
    assert result == "file content"


async def test_sync_run_raises(monkeypatch):
    mock_secure = AsyncMock(return_value=AsyncMock())
    monkeypatch.setattr(
        "agentsh_secure_sandbox.toolset._base.secure_sandbox", mock_secure,
    )
    toolkit = SecureSandboxToolkit(MagicMock())
    async with toolkit:
        tools = {t.name: t for t in toolkit.get_tools()}
        with pytest.raises(NotImplementedError):
            tools["run_command"]._run(command="echo hello")


def test_toolkit_sandbox_not_provisioned():
    toolkit = SecureSandboxToolkit(MagicMock())
    with pytest.raises(RuntimeError, match="not provisioned"):
        _ = toolkit.sandbox
