package com.gzzm.lobster.tool;

import com.gzzm.lobster.common.LobsterException;
import com.gzzm.lobster.common.ToolCategory;
import com.gzzm.lobster.llm.ToolSpec;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * ToolRegistry —— 工具注册中心 / Central tool registry.
 *
 * <p>内置工具通过 {@link #register(BuiltinToolDefinition, ToolExecutor)} 注册；
 * MCP 工具通过 {@link com.gzzm.lobster.tool.mcp.McpToolBridge} 动态注入。
 * Built-in tools register here; MCP tools are injected dynamically by {@code McpToolBridge}.
 *
 * <p><b>为什么 state 是 static：</b>nest DI 对 {@code @Inject ToolRegistry} 每次注入一个
 * 独立实例。用实例字段时，{@code LobsterBootstrap} 启动时注册的 18 个工具只留在它那份实例里；
 * 运行时 {@code AgentRuntime.toolRegistry} 是另一份实例，空的，LLM 永远拿不到工具。
 * 改成 static 共享状态，多少个外壳实例都操作同一份 map。
 */
public class ToolRegistry {

    private static final Map<String, BuiltinToolDefinition> definitions = new ConcurrentHashMap<>();
    private static final Map<String, ToolExecutor> executors = new ConcurrentHashMap<>();

    /** 注册一个工具 / Register one tool. */
    public void register(BuiltinToolDefinition def, ToolExecutor executor) {
        if (def == null || executor == null) throw new LobsterException("tool.register", "null tool");
        if (!ToolNamePolicy.isValidLlmToolName(def.getToolName())) {
            throw new LobsterException("tool.invalid_name",
                    "Invalid LLM tool name: " + def.getToolName());
        }
        definitions.put(def.getToolName(), def);
        executors.put(def.getToolName(), executor);
    }

    public void unregister(String toolName) {
        definitions.remove(toolName);
        executors.remove(toolName);
    }

    public BuiltinToolDefinition find(String toolName) {
        return definitions.get(toolName);
    }

    public ToolExecutor executor(String toolName) {
        return executors.get(toolName);
    }

    public Collection<BuiltinToolDefinition> all() {
        return Collections.unmodifiableCollection(definitions.values());
    }

    public Collection<BuiltinToolDefinition> byCategory(ToolCategory category) {
        List<BuiltinToolDefinition> list = new ArrayList<>();
        for (BuiltinToolDefinition d : definitions.values()) if (d.getCategory() == category) list.add(d);
        return list;
    }

    /**
     * 过滤可用工具（基于 AgentProfile.enabledTools + 组织开关）。
     * Return the tools available for the given run.
     */
    public List<BuiltinToolDefinition> listFor(ToolListFilter filter) {
        List<BuiltinToolDefinition> result = new ArrayList<>();
        for (BuiltinToolDefinition d : definitions.values()) {
            if (filter == null || filter.accept(d)) result.add(d);
        }
        return result;
    }

    /** 转为 LLM 可识别的 ToolSpec 列表 / Convert to the list of LLM ToolSpec. */
    public List<ToolSpec> toToolSpecs(ToolListFilter filter) {
        List<ToolSpec> specs = new ArrayList<>();
        for (BuiltinToolDefinition d : listFor(filter)) {
            if (!ToolNamePolicy.isValidLlmToolName(d.getToolName())) continue;
            specs.add(new ToolSpec(d.getToolName(), d.getDescription(), d.getInputSchema()));
        }
        return specs;
    }

    /** 用当前注册的工具名集合构造一个 name -> def 的副本 / snapshot. */
    public Map<String, BuiltinToolDefinition> snapshot() {
        return new LinkedHashMap<>(definitions);
    }

    /** 过滤器接口 / Filter interface for available tools. */
    public interface ToolListFilter {
        boolean accept(BuiltinToolDefinition def);
    }
}
