package com.infoepoch.pms.agent.platform.agent.adapter.out.tool;

import com.infoepoch.pms.agent.platform.agent.adapter.out.tool.support.ChatbotBuiltInToolDefinition;
import com.infoepoch.pms.agent.platform.agent.adapter.out.tool.support.ChatbotBuiltInToolType;
import com.infoepoch.pms.agent.platform.agent.adapter.out.tool.support.ChatbotWorkspaceRootResolver;
import com.infoepoch.pms.agent.platform.chatbot.application.port.out.ChatbotBuiltInToolQueryPort;
import org.springframework.ai.support.ToolCallbacks;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.nio.file.Path;
import java.util.*;

/**
 * 聊天机器人内置工具注册表。
 */
@Component
public class ChatbotBuiltInToolRegistry implements ChatbotBuiltInToolQueryPort {

    public static final String CHATBOT_CONTEXT_KEY = "chatbot";

    private final Map<String, ChatbotBuiltInToolDefinition> configurableTools;
    private final Map<String, ToolCallbackProvider> toolCallbackProviders;

    public ChatbotBuiltInToolRegistry() {
        this.configurableTools = createConfigurableTools();
        this.toolCallbackProviders = Map.of();
    }

    /**
     * 创建内置工具注册表。
     *
     * @param getCurrentTimeTool       当前时间工具
     * @param webFetchTool             网页抓取工具
     * @param globSearchTool  知识库通配搜索工具
     * @param grepSearchTool  知识库正则搜索工具
     */
    @Autowired
    public ChatbotBuiltInToolRegistry(GetCurrentTimeTool getCurrentTimeTool,
                                      WebFetchTool webFetchTool,
                                      GlobSearchTool globSearchTool,
                                      GrepSearchTool grepSearchTool) {
        this.configurableTools = createConfigurableTools();
        this.toolCallbackProviders = createToolCallbackProviders(getCurrentTimeTool, webFetchTool,
                globSearchTool, grepSearchTool);
    }

    /**
     * 查询全部可配置内置工具。
     *
     * @return 可配置内置工具列表
     */
    @Override
    public List<ChatbotBuiltInToolDefinition> listConfigurableTools() {
        return List.copyOf(configurableTools.values());
    }

    /**
     * 判断指定工具是否为可配置内置工具。
     *
     * @param toolKey 工具标识
     * @return 是否为可配置内置工具
     */
    @Override
    public boolean isConfigurableTool(String toolKey) {
        return StringUtils.hasText(toolKey) && configurableTools.containsKey(toolKey.trim());
    }

    /**
     * 按工具标识查询工具回调提供器。
     *
     * @param toolKey 工具标识
     * @return 工具回调提供器
     */
    public Optional<ToolCallbackProvider> findToolCallbackProvider(String toolKey) {
        if (!StringUtils.hasText(toolKey)) {
            return Optional.empty();
        }
        return Optional.ofNullable(toolCallbackProviders.get(toolKey.trim()));
    }

    static Path resolveWorkspaceRootForTesting(String configuredWorkspaceRoot, Path currentPath) {
        return ChatbotWorkspaceRootResolver.resolve(configuredWorkspaceRoot, currentPath);
    }

    private Map<String, ChatbotBuiltInToolDefinition> createConfigurableTools() {
        Map<String, ChatbotBuiltInToolDefinition> tools = new LinkedHashMap<>();
        for (ChatbotBuiltInToolType type : ChatbotBuiltInToolType.values()) {
            tools.put(type.getKey(), new ChatbotBuiltInToolDefinition(type.getKey(), type.getName(), type.getDescription()));
        }
        return Collections.unmodifiableMap(tools);
    }

    private Map<String, ToolCallbackProvider> createToolCallbackProviders(GetCurrentTimeTool getCurrentTimeTool,
                                                                          WebFetchTool webFetchTool,
                                                                          GlobSearchTool globSearchTool,
                                                                          GrepSearchTool grepSearchTool) {
        Map<String, ToolCallbackProvider> providers = new LinkedHashMap<>();
        providers.put(ChatbotBuiltInToolType.GET_CURRENT_TIME.getKey(), ToolCallbackProvider.from(ToolCallbacks.from(getCurrentTimeTool)));
        providers.put(ChatbotBuiltInToolType.WEB_FETCH.getKey(), ToolCallbackProvider.from(webFetchTool.createToolCallback()));
        providers.put(ChatbotBuiltInToolType.GLOB_SEARCH.getKey(), ToolCallbackProvider.from(globSearchTool.createToolCallback()));
        providers.put(ChatbotBuiltInToolType.GREP_SEARCH.getKey(), ToolCallbackProvider.from(grepSearchTool.createToolCallback()));
        return Collections.unmodifiableMap(providers);
    }
}
