package com.agent.management.engine;

import com.fasterxml.jackson.databind.JsonNode;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * 工作流上下文变量 → 系统提示词的工具类。
 *
 * <p>用于把节点明确定义的输入变量自动注入到 LLM/智能操作/技能等节点的系统提示词中，
 * 让模型在用户未显式声明 {{var}} 占位符时也能"看到"当前节点真正需要的输入。
 * 不再把前置节点的全部工作空间变量无差别注入，避免上下文膨胀分散模型注意力。</p>
 *
 * <p>DRY 集中点：5 个执行器（LlmExecutor / SmartActionExecutor / AgentExecutor /
 * HermesSmartActionExecutor / HermesAgentExecutor）共享同一份格式化逻辑。</p>
 */
public final class ContextPromptHelper {

    /** 单个变量值的截断上限，避免长内容（如整篇文档）撑爆 prompt */
    private static final int MAX_VALUE_LENGTH = 2000;

    private ContextPromptHelper() {
    }

    /**
     * 根据节点 data.inputs 中明确定义的输入字段，从工作区取值并格式化为系统提示词片段。
     *
     * @param nodeData  节点 data（JSON）
     * @param workspace 当前节点工作区
     * @return 格式化后的提示词；无输入定义或全部为空时返回空串
     */
    public static String buildInputContextSystemPrompt(JsonNode nodeData, NodeWorkspace workspace) {
        if (nodeData == null || workspace == null) {
            return "";
        }
        JsonNode inputsNode = nodeData.path("inputs");
        if (!inputsNode.isArray() || inputsNode.isEmpty()) {
            return "";
        }
        Map<String, Object> inputValues = new LinkedHashMap<>();
        for (JsonNode field : inputsNode) {
            String name = field.path("name").asText("");
            if (name.isEmpty()) {
                continue;
            }
            Object value = workspace.getVariable(name);
            if (value != null) {
                inputValues.put(name, value);
            }
        }
        return buildContextSystemPrompt(inputValues, "节点输入变量");
    }

    /**
     * 把变量表格式化为系统提示词片段。
     *
     * @param variables 变量表（可能为 null）
     * @param title     提示词片段标题
     * @return 格式化后的提示词；如果变量表为空，返回空串
     */
    private static String buildContextSystemPrompt(Map<String, Object> variables, String title) {
        if (variables == null || variables.isEmpty()) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        sb.append("=== ").append(title).append(" ===\n");
        sb.append("以下是当前可用的变量值，可在回答中引用：\n\n");
        for (Map.Entry<String, Object> e : variables.entrySet()) {
            Object v = e.getValue();
            if (v == null) {
                continue;
            }
            sb.append("- ").append(e.getKey()).append("：").append(formatValue(v)).append("\n");
        }
        return sb.toString();
    }

    /**
     * 把节点明确定义的输入变量作为上下文系统提示词，合并到用户自定义的系统提示词后。
     *
     * @param userSystemPrompt 节点本身声明的 systemPrompt（已渲染）
     * @param nodeData         节点 data（JSON）
     * @param workspace        当前节点工作区
     * @return 合并后的完整 systemPrompt
     */
    public static String merge(String userSystemPrompt, JsonNode nodeData, NodeWorkspace workspace) {
        String inputContextPrompt = buildInputContextSystemPrompt(nodeData, workspace);
        return join(userSystemPrompt, inputContextPrompt);
    }

    private static String join(String userSystemPrompt, String contextPrompt) {
        boolean userEmpty = userSystemPrompt == null || userSystemPrompt.isBlank();
        boolean ctxEmpty = contextPrompt == null || contextPrompt.isEmpty();
        if (userEmpty && ctxEmpty) {
            return "";
        }
        if (userEmpty) {
            return contextPrompt;
        }
        if (ctxEmpty) {
            return userSystemPrompt;
        }
        return userSystemPrompt + "\n\n" + contextPrompt;
    }

    private static String formatValue(Object value) {
        if (value == null) {
            return "";
        }
        String s = value.toString();
        if (s.length() <= MAX_VALUE_LENGTH) {
            return s;
        }
        return s.substring(0, MAX_VALUE_LENGTH) + "...(已截断，共 " + s.length() + " 字符)";
    }
}
