package com.agent.management.engine.executor;

import com.agent.management.engine.NodeExecutionResult;
import com.agent.management.engine.NodeExecutor;
import com.agent.management.engine.NodeWorkspace;
import com.agent.management.engine.WorkflowContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.stereotype.Component;

/**
 * 技能（skill）节点执行器
 *
 * <p>前端"技能"节点（type = "skill"）通过 {@code data.skillId} 关联一个 Skill 文件夹，
 * 语义等价于"智能体"节点（type = "agent"）：加载 SKILL.md 作为系统提示，由 Hermes Bridge
 * 或内置 LLM 执行。</p>
 *
 * <p>本类为轻量适配器，遵循 DRY 原则复用已有 Agent 执行链：将 skillId 复制为 agentId 后
 * 委托给已激活的 {@link HermesAgentExecutor}（hermes.enabled=true）或 {@link AgentExecutor}
 * （hermes.enabled=false）。两者通过 {@code @ConditionalOnProperty} 互斥激活，必有一个可用。</p>
 */
@Slf4j
@Component
public class SkillExecutor implements NodeExecutor {

    private final AgentExecutor builtinAgentExecutor;
    private final HermesAgentExecutor hermesAgentExecutor;

    public SkillExecutor(ObjectProvider<AgentExecutor> builtinProvider,
                         ObjectProvider<HermesAgentExecutor> hermesProvider) {
        this.builtinAgentExecutor = builtinProvider.getIfAvailable();
        this.hermesAgentExecutor = hermesProvider.getIfAvailable();
    }

    @Override
    public String getType() {
        return "skill";
    }

    @Override
    public NodeExecutionResult execute(String nodeId, JsonNode data, WorkflowContext context, NodeWorkspace workspace) {
        NodeExecutor delegate = hermesAgentExecutor != null ? hermesAgentExecutor : builtinAgentExecutor;
        if (delegate == null) {
            return NodeExecutionResult.failed(nodeId, "未找到可用的 Agent 执行器（hermes.enabled 配置异常）");
        }

        String skillId = data.path("skillId").asText("");
        if (skillId.isEmpty()) {
            return NodeExecutionResult.failed(nodeId, "技能节点未关联 Skill");
        }

        // 深拷贝避免污染原始 graphData；将 skillId 复制为 agentId 复用 Agent 执行器逻辑
        ObjectNode bridged = (ObjectNode) data.deepCopy();
        bridged.put("agentId", skillId);

        log.info("[Skill] 节点 {} 委托 {} 执行, skillId={}", nodeId, delegate.getClass().getSimpleName(), skillId);
        return delegate.execute(nodeId, bridged, context, workspace);
    }
}
