package com.easyagents.agent.runtime.tool.operate;

import com.easyagents.agent.runtime.AgentRuntimeException;
import com.easyagents.agent.runtime.tool.AgentToolSpec;
import io.agentscope.core.tool.Toolkit;
import org.junit.Assert;
import org.junit.Test;

import java.util.List;
import java.util.Set;

/**
 * 测试 Agent 操作类工具适配器。
 */
public class AgentOperateToolAdapterTest {

    private final AgentOperateToolAdapter adapter = new AgentOperateToolAdapter();

    @Test
    public void shouldRegisterReadFileToolsWithDefaultHitlDisabled() {
        Toolkit toolkit = new Toolkit();
        AgentOperateToolSpec spec = spec(AgentOperateToolType.READ_FILE);

        List<AgentToolSpec> toolSpecs = adapter.register(List.of(spec), toolkit);

        Assert.assertNotNull(toolkit.getTool(AgentOperateToolAdapter.VIEW_TEXT_FILE_TOOL));
        Assert.assertNotNull(toolkit.getTool(AgentOperateToolAdapter.LIST_DIRECTORY_TOOL));
        Assert.assertEquals(2, toolSpecs.size());
        Assert.assertTrue(toolSpecs.stream().noneMatch(AgentToolSpec::isApprovalRequired));
    }

    @Test
    public void shouldRegisterWriteFileToolsWithDefaultHitlEnabled() {
        Toolkit toolkit = new Toolkit();
        AgentOperateToolSpec spec = spec(AgentOperateToolType.WRITE_FILE);

        List<AgentToolSpec> toolSpecs = adapter.register(List.of(spec), toolkit);

        Assert.assertNotNull(toolkit.getTool(AgentOperateToolAdapter.WRITE_TEXT_FILE_TOOL));
        Assert.assertNotNull(toolkit.getTool(AgentOperateToolAdapter.INSERT_TEXT_FILE_TOOL));
        Assert.assertEquals(2, toolSpecs.size());
        Assert.assertTrue(toolSpecs.stream().allMatch(AgentToolSpec::isApprovalRequired));
    }

    @Test
    public void shouldRegisterShellToolWithEmptyWhitelist() {
        Toolkit toolkit = new Toolkit();
        AgentOperateToolSpec spec = spec(AgentOperateToolType.SHELL);
        spec.setShellAllowedCommands(Set.of());

        List<AgentToolSpec> toolSpecs = adapter.register(List.of(spec), toolkit);

        Assert.assertNotNull(toolkit.getTool(AgentOperateToolAdapter.EXECUTE_SHELL_COMMAND_TOOL));
        Assert.assertEquals(1, toolSpecs.size());
        Assert.assertTrue(toolSpecs.get(0).isApprovalRequired());
    }

    @Test
    public void shouldSkipDisabledOperateTool() {
        Toolkit toolkit = new Toolkit();
        AgentOperateToolSpec spec = spec(AgentOperateToolType.SHELL);
        spec.setEnabled(false);

        List<AgentToolSpec> toolSpecs = adapter.register(List.of(spec), toolkit);

        Assert.assertNull(toolkit.getTool(AgentOperateToolAdapter.EXECUTE_SHELL_COMMAND_TOOL));
        Assert.assertTrue(toolSpecs.isEmpty());
    }

    @Test(expected = AgentRuntimeException.class)
    public void shouldRejectMissingBaseDir() {
        AgentOperateToolSpec spec = spec(AgentOperateToolType.READ_FILE);
        spec.setBaseDir(null);

        adapter.register(List.of(spec), new Toolkit());
    }

    @Test(expected = AgentRuntimeException.class)
    public void shouldRejectRelativeBaseDir() {
        AgentOperateToolSpec spec = spec(AgentOperateToolType.READ_FILE);
        spec.setBaseDir("relative/workspace");

        adapter.register(List.of(spec), new Toolkit());
    }

    @Test(expected = AgentRuntimeException.class)
    public void shouldRejectToolNameConflict() {
        Toolkit toolkit = new Toolkit();
        AgentOperateToolSpec first = spec(AgentOperateToolType.READ_FILE);
        AgentOperateToolSpec second = spec(AgentOperateToolType.READ_FILE);

        adapter.register(List.of(first, second), toolkit);
    }

    private AgentOperateToolSpec spec(AgentOperateToolType type) {
        AgentOperateToolSpec spec = new AgentOperateToolSpec();
        spec.setType(type);
        spec.setBaseDir(System.getProperty("java.io.tmpdir"));
        return spec;
    }
}
