package com.easyagents.agent.runtime.mcp;

import com.easyagents.agent.runtime.hitl.AgentToolApprovalRequest;

import java.time.Duration;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * MCP 运行时声明。
 */
public class McpSpec {

    private String name;
    private String description;
    private McpTransportType transportType = McpTransportType.STDIO;
    private String command;
    private List<String> args = new ArrayList<>();
    private Map<String, String> env = new LinkedHashMap<>();
    private String url;
    private Map<String, String> headers = new LinkedHashMap<>();
    private Map<String, String> queryParams = new LinkedHashMap<>();
    private Duration timeout = Duration.ofSeconds(120);
    private Duration initializationTimeout = Duration.ofSeconds(30);
    private List<String> enableTools = new ArrayList<>();
    private List<String> disableTools = new ArrayList<>();
    private String groupName;
    private Map<String, Map<String, Object>> presetParameters = new LinkedHashMap<>();
    private Map<String, String> toolAliases = new LinkedHashMap<>();
    private String toolNamePrefix;
    private boolean approvalRequired;
    private AgentToolApprovalRequest approvalRequest = new AgentToolApprovalRequest();
    private Map<String, AgentToolApprovalRequest> toolApprovalRequests = new LinkedHashMap<>();
    private String skillId;
    private List<McpToolManifestEntry> frozenToolManifest = new ArrayList<>();
    private String frozenToolManifestHash;
    private Map<String, Object> metadata = new LinkedHashMap<>();

    /**
     * 获取 MCP client 名称。
     *
     * @return MCP client 名称
     */
    public String getName() {
        return name;
    }

    /**
     * 设置 MCP client 名称。
     *
     * @param name MCP client 名称
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取 MCP 描述。
     *
     * @return MCP 描述
     */
    public String getDescription() {
        return description;
    }

    /**
     * 设置 MCP 描述。
     *
     * @param description MCP 描述
     */
    public void setDescription(String description) {
        this.description = description;
    }

    /**
     * 获取连接方式。
     *
     * @return 连接方式
     */
    public McpTransportType getTransportType() {
        return transportType;
    }

    /**
     * 设置连接方式。
     *
     * @param transportType 连接方式
     */
    public void setTransportType(McpTransportType transportType) {
        this.transportType = transportType == null ? McpTransportType.STDIO : transportType;
    }

    /**
     * 通过字符串设置连接方式。
     *
     * @param transportType 连接方式文本
     */
    public void setTransportType(String transportType) {
        this.transportType = McpTransportType.from(transportType);
    }

    /**
     * 获取 stdio 命令。
     *
     * @return stdio 命令
     */
    public String getCommand() {
        return command;
    }

    /**
     * 设置 stdio 命令。
     *
     * @param command stdio 命令
     */
    public void setCommand(String command) {
        this.command = command;
    }

    /**
     * 获取 stdio 参数。
     *
     * @return stdio 参数
     */
    public List<String> getArgs() {
        return args;
    }

    /**
     * 设置 stdio 参数。
     *
     * @param args stdio 参数
     */
    public void setArgs(List<String> args) {
        this.args = args == null ? new ArrayList<>() : new ArrayList<>(args);
    }

    /**
     * 获取 stdio 环境变量。
     *
     * @return stdio 环境变量
     */
    public Map<String, String> getEnv() {
        return env;
    }

    /**
     * 设置 stdio 环境变量。
     *
     * @param env stdio 环境变量
     */
    public void setEnv(Map<String, String> env) {
        this.env = env == null ? new LinkedHashMap<>() : new LinkedHashMap<>(env);
    }

    /**
     * 获取 HTTP 地址。
     *
     * @return HTTP 地址
     */
    public String getUrl() {
        return url;
    }

    /**
     * 设置 HTTP 地址。
     *
     * @param url HTTP 地址
     */
    public void setUrl(String url) {
        this.url = url;
    }

    /**
     * 获取 HTTP 请求头。
     *
     * @return HTTP 请求头
     */
    public Map<String, String> getHeaders() {
        return headers;
    }

    /**
     * 设置 HTTP 请求头。
     *
     * @param headers HTTP 请求头
     */
    public void setHeaders(Map<String, String> headers) {
        this.headers = headers == null ? new LinkedHashMap<>() : new LinkedHashMap<>(headers);
    }

    /**
     * 获取 HTTP 查询参数。
     *
     * @return HTTP 查询参数
     */
    public Map<String, String> getQueryParams() {
        return queryParams;
    }

    /**
     * 设置 HTTP 查询参数。
     *
     * @param queryParams HTTP 查询参数
     */
    public void setQueryParams(Map<String, String> queryParams) {
        this.queryParams = queryParams == null ? new LinkedHashMap<>() : new LinkedHashMap<>(queryParams);
    }

    /**
     * 获取请求超时时间。
     *
     * @return 请求超时时间
     */
    public Duration getTimeout() {
        return timeout;
    }

    /**
     * 设置请求超时时间。
     *
     * @param timeout 请求超时时间
     */
    public void setTimeout(Duration timeout) {
        this.timeout = timeout == null ? Duration.ofSeconds(120) : timeout;
    }

    /**
     * 获取初始化超时时间。
     *
     * @return 初始化超时时间
     */
    public Duration getInitializationTimeout() {
        return initializationTimeout;
    }

    /**
     * 设置初始化超时时间。
     *
     * @param initializationTimeout 初始化超时时间
     */
    public void setInitializationTimeout(Duration initializationTimeout) {
        this.initializationTimeout = initializationTimeout == null ? Duration.ofSeconds(30) : initializationTimeout;
    }

    /**
     * 获取启用工具白名单。
     *
     * @return 启用工具白名单
     */
    public List<String> getEnableTools() {
        return enableTools;
    }

    /**
     * 设置启用工具白名单。
     *
     * @param enableTools 启用工具白名单
     */
    public void setEnableTools(List<String> enableTools) {
        this.enableTools = enableTools == null ? new ArrayList<>() : new ArrayList<>(enableTools);
    }

    /**
     * 获取禁用工具黑名单。
     *
     * @return 禁用工具黑名单
     */
    public List<String> getDisableTools() {
        return disableTools;
    }

    /**
     * 设置禁用工具黑名单。
     *
     * @param disableTools 禁用工具黑名单
     */
    public void setDisableTools(List<String> disableTools) {
        this.disableTools = disableTools == null ? new ArrayList<>() : new ArrayList<>(disableTools);
    }

    /**
     * 获取工具分组名。
     *
     * @return 工具分组名
     */
    public String getGroupName() {
        return groupName;
    }

    /**
     * 设置工具分组名。
     *
     * @param groupName 工具分组名
     */
    public void setGroupName(String groupName) {
        this.groupName = groupName;
    }

    /**
     * 获取预置参数。
     *
     * @return 预置参数
     */
    public Map<String, Map<String, Object>> getPresetParameters() {
        return presetParameters;
    }

    /**
     * 设置预置参数。
     *
     * @param presetParameters 预置参数
     */
    public void setPresetParameters(Map<String, Map<String, Object>> presetParameters) {
        this.presetParameters = presetParameters == null ? new LinkedHashMap<>() : new LinkedHashMap<>(presetParameters);
    }

    /**
     * 获取 MCP 原始工具名到运行时工具名的别名映射。
     *
     * @return 工具别名映射
     */
    public Map<String, String> getToolAliases() {
        return toolAliases;
    }

    /**
     * 设置 MCP 原始工具名到运行时工具名的别名映射。
     *
     * @param toolAliases 工具别名映射
     */
    public void setToolAliases(Map<String, String> toolAliases) {
        this.toolAliases = toolAliases == null ? new LinkedHashMap<>() : new LinkedHashMap<>(toolAliases);
    }

    /**
     * 获取动态工具名前缀。
     *
     * @return 动态工具名前缀
     */
    public String getToolNamePrefix() {
        return toolNamePrefix;
    }

    /**
     * 设置动态工具名前缀。
     *
     * @param toolNamePrefix 动态工具名前缀
     */
    public void setToolNamePrefix(String toolNamePrefix) {
        this.toolNamePrefix = toolNamePrefix;
    }

    /**
     * 返回 MCP 工具是否默认需要人工审批。
     *
     * @return 需要审批时为 true
     */
    public boolean isApprovalRequired() {
        return approvalRequired;
    }

    /**
     * 设置 MCP 工具是否默认需要人工审批。
     *
     * @param approvalRequired 审批标记
     */
    public void setApprovalRequired(boolean approvalRequired) {
        this.approvalRequired = approvalRequired;
    }

    /**
     * 获取审批请求。
     *
     * @return 审批请求
     */
    public AgentToolApprovalRequest getApprovalRequest() {
        return approvalRequest;
    }

    /**
     * 设置审批请求。
     *
     * @param approvalRequest 审批请求
     */
    public void setApprovalRequest(AgentToolApprovalRequest approvalRequest) {
        this.approvalRequest = approvalRequest == null ? new AgentToolApprovalRequest() : approvalRequest;
    }

    /**
     * 获取运行时工具名到审批请求的映射。
     *
     * @return 工具审批请求映射
     */
    public Map<String, AgentToolApprovalRequest> getToolApprovalRequests() {
        return toolApprovalRequests;
    }

    /**
     * 设置运行时工具名到审批请求的映射。
     *
     * @param toolApprovalRequests 工具审批请求映射
     */
    public void setToolApprovalRequests(Map<String, AgentToolApprovalRequest> toolApprovalRequests) {
        this.toolApprovalRequests = toolApprovalRequests == null
                ? new LinkedHashMap<>()
                : new LinkedHashMap<>(toolApprovalRequests);
    }

    /**
     * 获取所属 Skill ID。
     *
     * @return Skill ID；未绑定 Skill 时为空
     */
    public String getSkillId() {
        return skillId;
    }

    /**
     * 设置所属 Skill ID。
     *
     * @param skillId Skill ID
     */
    public void setSkillId(String skillId) {
        this.skillId = skillId;
    }

    /**
     * 获取冻结 Tool 清单。
     *
     * @return 冻结 Tool 清单
     */
    public List<McpToolManifestEntry> getFrozenToolManifest() {
        return frozenToolManifest;
    }

    /**
     * 设置冻结 Tool 清单。
     *
     * @param frozenToolManifest 冻结 Tool 清单
     */
    public void setFrozenToolManifest(List<McpToolManifestEntry> frozenToolManifest) {
        this.frozenToolManifest = frozenToolManifest == null
                ? new ArrayList<>()
                : new ArrayList<>(frozenToolManifest);
    }

    /**
     * 获取冻结 Tool 清单 hash。
     *
     * @return 清单 hash
     */
    public String getFrozenToolManifestHash() {
        return frozenToolManifestHash;
    }

    /**
     * 设置冻结 Tool 清单 hash。
     *
     * @param frozenToolManifestHash 清单 hash
     */
    public void setFrozenToolManifestHash(String frozenToolManifestHash) {
        this.frozenToolManifestHash = frozenToolManifestHash;
    }

    /**
     * 获取元数据。
     *
     * @return 元数据
     */
    public Map<String, Object> getMetadata() {
        return metadata;
    }

    /**
     * 设置元数据。
     *
     * @param metadata 元数据
     */
    public void setMetadata(Map<String, Object> metadata) {
        this.metadata = metadata == null ? new LinkedHashMap<>() : new LinkedHashMap<>(metadata);
    }
}
