package com.ruoyi.interfaces.workflow;

import lombok.Getter;
import lombok.Setter;
import org.springframework.context.expression.MapAccessor;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.common.TemplateParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

import java.util.HashMap;
import java.util.Map;

/**
 * @author LinQiLong
 * @date 2025/7/15 16:16
 */
public class ExecutionContext {
    @Setter
    @Getter
    private Long workflowId;
    private Map<String, Object> input;
    private Map<String, Object> contextData = new HashMap<>();
    private Map<String, Map<String, Object>> stepOutputs = new HashMap<>();

    public ExecutionContext(Map<String, Object> input) {
        this.input = input;
        // 初始化时将输入数据放入上下文
        contextData.put("input", new HashMap<>(input));
    }

    // 设置步骤输出（按步骤名称存储）
    public void setStepOutput(String stepName, Map<String, Object> output) {
        stepOutputs.put(stepName, output);
        // 同时将输出数据放入顶层上下文
        contextData.put(stepName, output);
    }

    // 将特定值放入上下文
    public void setContextValue(String key, Object value) {
        contextData.put(key, value);
    }

    // 获取完整的上下文数据
    public Map<String, Object> getAllContextData() {
        return contextData;
    }

    // 使用SpEL表达式渲染模板
    public String renderTemplate(String template) {
        ExpressionParser parser = new SpelExpressionParser();
        StandardEvaluationContext evalContext = new StandardEvaluationContext();
        evalContext.setRootObject(contextData);
        evalContext.addPropertyAccessor(new MapAccessor());
        return parser.parseExpression(template, new TemplateParserContext())
                .getValue(evalContext, String.class);
    }

    // 使用SpEL解析JSON对象
    public Map<String, Object> parseTemplate(Map<String, Object> template) {
        Map<String, Object> result = new HashMap<>();
        template.forEach((key, value) -> {
            if (value instanceof String) {
                result.put(key, renderTemplate((String) value));
            } else if (value instanceof Map) {
                result.put(key, parseTemplate((Map<String, Object>) value));
            } else {
                result.put(key, value);
            }
        });
        return result;
    }
}
