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

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

import java.util.LinkedHashSet;
import java.util.Set;
import java.time.Duration;

/**
 * Agent 操作类工具声明。
 *
 * <p>操作类工具由 runtime 适配为与 AgentScope 1.x 契约兼容的受控工具。调用方必须按
 * agent、session 或 user 维度传入独立的绝对工作目录，并通过配额与 Shell 参数限制资源使用。
 */
public class AgentOperateToolSpec {

    private AgentOperateToolType type;
    private boolean enabled = true;
    private String baseDir;
    private Boolean approvalRequired;
    private AgentToolApprovalRequest approvalRequest;
    private WorkspaceQuotaLimits workspaceQuotaLimits = WorkspaceQuotaLimits.unlimited();
    private transient WorkspaceQuotaHook workspaceQuotaHook = WorkspaceQuotaHook.noop();
    private Set<String> shellAllowedCommands = new LinkedHashSet<>(ControlledShellTool.DEFAULT_ALLOWED_COMMANDS);
    private String shellCharset = "UTF-8";
    private Duration shellDefaultTimeout = Duration.ofSeconds(60);
    private Duration shellMaxTimeout = Duration.ofSeconds(300);
    private int shellMaxCommandLength = 4096;
    private long shellMaxOutputSize = 1024L * 1024L;
    private int shellMaxConcurrency = 2;
    private long patchMaxSize = 1024L * 1024L;
    private int patchMaxFiles = 100;
    private long patchMaxAffectedBytes = 16L * 1024L * 1024L;

    /**
     * 获取操作工具类型。
     *
     * @return 操作工具类型
     */
    public AgentOperateToolType getType() {
        return type;
    }

    /**
     * 设置操作工具类型。
     *
     * @param type 操作工具类型
     */
    public void setType(AgentOperateToolType type) {
        this.type = type;
    }

    /**
     * 返回是否启用该操作工具。
     *
     * @return 启用时为 true
     */
    public boolean isEnabled() {
        return enabled;
    }

    /**
     * 设置是否启用该操作工具。
     *
     * @param enabled 启用标记
     */
    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }

    /**
     * 获取操作工具工作目录。
     *
     * @return 绝对工作目录
     */
    public String getBaseDir() {
        return baseDir;
    }

    /**
     * 设置操作工具工作目录。
     *
     * @param baseDir 绝对工作目录
     */
    public void setBaseDir(String baseDir) {
        this.baseDir = baseDir;
    }

    /**
     * 获取工作区配额。
     *
     * @return 工作区配额
     */
    public WorkspaceQuotaLimits getWorkspaceQuotaLimits() {
        return workspaceQuotaLimits;
    }

    /**
     * 设置工作区配额。
     *
     * @param workspaceQuotaLimits 工作区配额，null 表示不限制
     */
    public void setWorkspaceQuotaLimits(WorkspaceQuotaLimits workspaceQuotaLimits) {
        this.workspaceQuotaLimits = workspaceQuotaLimits == null
                ? WorkspaceQuotaLimits.unlimited() : workspaceQuotaLimits;
    }

    /**
     * 获取业务侧附加配额校验 Hook。
     *
     * @return 配额校验 Hook
     */
    public WorkspaceQuotaHook getWorkspaceQuotaHook() {
        return workspaceQuotaHook;
    }

    /**
     * 设置业务侧附加配额校验 Hook。
     *
     * @param workspaceQuotaHook 配额校验 Hook，null 表示无附加校验
     */
    public void setWorkspaceQuotaHook(WorkspaceQuotaHook workspaceQuotaHook) {
        this.workspaceQuotaHook = workspaceQuotaHook == null ? WorkspaceQuotaHook.noop() : workspaceQuotaHook;
    }

    /**
     * 获取审批开关覆盖值。
     *
     * @return 审批覆盖值，null 表示使用工具类型默认值
     */
    public Boolean getApprovalRequired() {
        return approvalRequired;
    }

    /**
     * 设置审批开关覆盖值。
     *
     * @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;
    }

    /**
     * 获取 Shell 命令白名单。
     *
     * @return Shell 命令白名单
     */
    public Set<String> getShellAllowedCommands() {
        return shellAllowedCommands;
    }

    /**
     * 设置 Shell 命令白名单。
     *
     * @param shellAllowedCommands Shell 命令白名单
     */
    public void setShellAllowedCommands(Set<String> shellAllowedCommands) {
        this.shellAllowedCommands = shellAllowedCommands == null ? new LinkedHashSet<>() : new LinkedHashSet<>(shellAllowedCommands);
    }

    /**
     * 获取 Shell 输出字符集名称。
     *
     * @return 字符集名称
     */
    public String getShellCharset() {
        return shellCharset;
    }

    /**
     * 设置 Shell 输出字符集名称。
     *
     * @param shellCharset 字符集名称
     */
    public void setShellCharset(String shellCharset) {
        this.shellCharset = shellCharset;
    }

    /**
     * 获取 Shell 默认超时。
     *
     * @return 默认超时
     */
    public Duration getShellDefaultTimeout() {
        return shellDefaultTimeout;
    }

    /**
     * 设置 Shell 默认超时。
     *
     * @param shellDefaultTimeout 默认超时
     */
    public void setShellDefaultTimeout(Duration shellDefaultTimeout) {
        this.shellDefaultTimeout = shellDefaultTimeout;
    }

    /**
     * 获取 Shell 最大超时。
     *
     * @return 最大超时
     */
    public Duration getShellMaxTimeout() {
        return shellMaxTimeout;
    }

    /**
     * 设置 Shell 最大超时。
     *
     * @param shellMaxTimeout 最大超时
     */
    public void setShellMaxTimeout(Duration shellMaxTimeout) {
        this.shellMaxTimeout = shellMaxTimeout;
    }

    /**
     * 获取 Shell 命令最大长度。
     *
     * @return 最大字符数
     */
    public int getShellMaxCommandLength() {
        return shellMaxCommandLength;
    }

    /**
     * 设置 Shell 命令最大长度。
     *
     * @param shellMaxCommandLength 最大字符数
     */
    public void setShellMaxCommandLength(int shellMaxCommandLength) {
        this.shellMaxCommandLength = shellMaxCommandLength;
    }

    /**
     * 获取 Shell 单次标准输出和错误输出各自的最大字节数。
     *
     * @return 最大字节数
     */
    public long getShellMaxOutputSize() {
        return shellMaxOutputSize;
    }

    /**
     * 设置 Shell 单次标准输出和错误输出各自的最大字节数。
     *
     * @param shellMaxOutputSize 最大字节数
     */
    public void setShellMaxOutputSize(long shellMaxOutputSize) {
        this.shellMaxOutputSize = shellMaxOutputSize;
    }

    /**
     * 获取 JVM 实例级 Shell 最大并发数。
     *
     * @return 最大并发数
     */
    public int getShellMaxConcurrency() {
        return shellMaxConcurrency;
    }

    /**
     * 设置 JVM 实例级 Shell 最大并发数。
     *
     * @param shellMaxConcurrency 最大并发数
     */
    public void setShellMaxConcurrency(int shellMaxConcurrency) {
        this.shellMaxConcurrency = shellMaxConcurrency;
    }

    /**
     * 获取 Patch 输入最大字节数。
     *
     * @return 最大字节数
     */
    public long getPatchMaxSize() {
        return patchMaxSize;
    }

    /**
     * 设置 Patch 输入最大字节数。
     *
     * @param patchMaxSize 最大字节数
     */
    public void setPatchMaxSize(long patchMaxSize) {
        this.patchMaxSize = patchMaxSize;
    }

    /**
     * 获取 Patch 最大影响文件数。
     *
     * @return 最大文件数
     */
    public int getPatchMaxFiles() {
        return patchMaxFiles;
    }

    /**
     * 设置 Patch 最大影响文件数。
     *
     * @param patchMaxFiles 最大文件数
     */
    public void setPatchMaxFiles(int patchMaxFiles) {
        this.patchMaxFiles = patchMaxFiles;
    }

    /**
     * 获取 Patch 影响内容最大总字节数。
     *
     * @return 最大字节数
     */
    public long getPatchMaxAffectedBytes() {
        return patchMaxAffectedBytes;
    }

    /**
     * 设置 Patch 影响内容最大总字节数。
     *
     * @param patchMaxAffectedBytes 最大字节数
     */
    public void setPatchMaxAffectedBytes(long patchMaxAffectedBytes) {
        this.patchMaxAffectedBytes = patchMaxAffectedBytes;
    }
}
