package com.qqchen.deploy.backend.workflow.delegate;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.qqchen.deploy.backend.workflow.model.NodeContext;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.JavaDelegate;
import org.flowable.common.engine.api.delegate.Expression;
import org.springframework.beans.factory.annotation.Autowired;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;

import static com.qqchen.deploy.backend.workflow.constants.WorkFlowConstants.WORKFLOW_NODE_EXECUTION_STATE_FAILURE;
import static com.qqchen.deploy.backend.workflow.constants.WorkFlowConstants.WORKFLOW_NODE_EXECUTION_STATE_SUCCESS;
import static com.qqchen.deploy.backend.workflow.constants.WorkFlowConstants.WORKFLOW_PREVIOUS_NODE_EXECUTION_STATE_VARIABLE_NAME;


/**
 * 任务委派者基类

 * 负责处理节点配置、输入映射和输出结果的统一处理
 *
 * @param <I> 输入映射类型 (InputMapping)
 * @param <O> 输出类型 (Outputs)
 * @author qqchen
 */
@Slf4j

public abstract class BaseNodeDelegate<I, O> implements JavaDelegate {

    @Autowired
    private ObjectMapper objectMapper;


    // Flowable自动注入的字段
    protected Expression nodeId;

    protected Expression configs;

    protected Expression inputMapping;

    protected Expression outputs;

    // 缓存泛型类型
    private Class<I> inputMappingClass;

    private Class<O> outputsClass;

    @Override
    public void execute(DelegateExecution execution) {

        String currentNodeId = null;
        try {
            // 1. 获取节点ID
            currentNodeId = getFieldValue(nodeId, execution);
            log.info("Executing node: {}", currentNodeId);

            // 2. 清除前一个节点的状态
            clearPreviousNodeStatus(execution);


            // 3. 解析配置（通用Map）
            Map<String, Object> configsMap = parseJsonField(configs, execution);

            // 4. 解析并转换InputMapping（强类型）
            I inputMappingObj = parseAndConvertInputMapping(execution);

            // 5. 执行具体的业务逻辑，返回强类型输出
            O outputsObj = executeInternal(execution, configsMap, inputMappingObj);

            // ✅ 6. 使用 NodeContext 保存节点数据
            NodeContext<I, O> nodeContext = new NodeContext<>();
            nodeContext.setConfigs(configsMap);
            nodeContext.setInputMapping(inputMappingObj);
            nodeContext.setOutputs(outputsObj);
            
            execution.setVariable(currentNodeId, nodeContext.toMap(objectMapper));
            log.info("Stored NodeContext for: {}", currentNodeId);

            // 7. 设置节点执行状态为成功
                setExecutionStatus(execution, WORKFLOW_NODE_EXECUTION_STATE_SUCCESS);

        } catch (Exception e) {
            setExecutionStatus(execution, WORKFLOW_NODE_EXECUTION_STATE_FAILURE);

            log.error("Node execution failed: {}", currentNodeId, e);
            throw new RuntimeException("Node execution failed: " + currentNodeId, e);
        }
    }

    /**

     * 执行具体的业务逻辑（子类实现）
     *
     * @param execution    Flowable执行上下文
     * @param configs      节点配置
     * @param inputMapping 输入映射（强类型）
     * @return 节点输出结果（强类型）
     */
    protected abstract O executeInternal(
        DelegateExecution execution,
        Map<String, Object> configs,
        I inputMapping
    );

    /**
     * 通过反射获取InputMapping的类型
     */
    @SuppressWarnings("unchecked")
    protected Class<I> getInputMappingClass() {
        if (inputMappingClass == null) {
            Type genericSuperclass = getClass().getGenericSuperclass();
            if (genericSuperclass instanceof ParameterizedType) {
                ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass;
                Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
                // 第一个泛型参数是 I (InputMapping)
                inputMappingClass = (Class<I>) actualTypeArguments[0];
            }
        }
        return inputMappingClass;
    }

    /**
     * 通过反射获取Outputs的类型（预留，未来可能需要）
     */
    @SuppressWarnings("unchecked")
    protected Class<O> getOutputsClass() {
        if (outputsClass == null) {
            Type genericSuperclass = getClass().getGenericSuperclass();
            if (genericSuperclass instanceof ParameterizedType) {
                ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass;
                Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
                // 第二个泛型参数是 O (Outputs)
                outputsClass = (Class<O>) actualTypeArguments[1];
            }
        }
        return outputsClass;
    }

    /**
     * 解析并转换InputMapping
     */
    protected I parseAndConvertInputMapping(DelegateExecution execution) {
        try {
            String inputMappingJson = getFieldValue(inputMapping, execution);
            Class<I> inputClass = getInputMappingClass();

            if (inputMappingJson == null || inputMappingJson.isEmpty()) {
                return inputClass.getDeclaredConstructor().newInstance();
            }

            // 先解析为Map
            Map<String, Object> inputMap = objectMapper.readValue(
                inputMappingJson,
                new TypeReference<Map<String, Object>>() {
                }
            );

            // 处理表达式
            Map<String, Object> resolvedMap = resolveExpressions(inputMap, execution);

            // 转换为强类型对象
            return objectMapper.convertValue(resolvedMap, inputClass);

        } catch (Exception e) {
            log.error("Failed to parse input mapping", e);
            throw new RuntimeException("Failed to parse input mapping", e);
        }
    }

    /**
     * 解析Map中的表达式
     * 使用简单的字符串替换方式，从execution变量中获取值
     */
    protected Map<String, Object> resolveExpressions(Map<String, Object> inputMap, DelegateExecution execution) {
        Map<String, Object> resolvedMap = new HashMap<>();

        for (Map.Entry<String, Object> entry : inputMap.entrySet()) {
            Object value = entry.getValue();

            if (value instanceof String) {
                String strValue = (String) value;
                if (strValue.contains("${")) {
                    try {
                        // 使用简单的变量替换：${sid_xxx.fieldName} -> 从execution中获取
                        String resolvedValue = resolveVariableExpression(strValue, execution);
                        resolvedMap.put(entry.getKey(), resolvedValue);
                    } catch (Exception e) {
                        log.warn("Failed to resolve expression: {}, using original value", strValue);
                        resolvedMap.put(entry.getKey(), value);
                    }
                } else {
                    resolvedMap.put(entry.getKey(), value);
                }
            } else {
                resolvedMap.put(entry.getKey(), value);
            }
        }

        return resolvedMap;
    }

    /**
     * 解析变量表达式
     * 例如：${sid_xxx.buildNumber} -> 从 execution.getVariable("sid_xxx") 中获取 buildNumber 字段
     */
    private String resolveVariableExpression(String expression, DelegateExecution execution) {
        String result = expression;

        // 匹配 ${xxx.yyy} 或 ${xxx} 格式
        java.util.regex.Pattern pattern = java.util.regex.Pattern.compile("\\$\\{([^}]+)\\}");
        java.util.regex.Matcher matcher = pattern.matcher(expression);

        while (matcher.find()) {
            String varExpression = matcher.group(1); // 例如：sid_xxx.buildNumber
            Object value = resolveVariable(varExpression, execution);

            if (value != null) {
                // 替换 ${xxx.yyy} 为实际值
                result = result.replace("${" + varExpression + "}", value.toString());
            }
        }

        return result;
    }

    /**
     * 从execution中解析变量
     * 支持：sid_xxx.buildNumber 格式
     */
    private Object resolveVariable(String varExpression, DelegateExecution execution) {
        String[] parts = varExpression.split("\\.", 2);

        if (parts.length == 1) {
            // 直接变量：${xxx}
            return execution.getVariable(parts[0]);
        } else {
            // 对象属性：${sid_xxx.buildNumber}
            String varName = parts[0];
            String fieldName = parts[1];

            Object varValue = execution.getVariable(varName);
            if (varValue instanceof Map) {
                @SuppressWarnings("unchecked")
                Map<String, Object> map = (Map<String, Object>) varValue;
                return map.get(fieldName);
            }
        }

        return null;
    }

    protected String getFieldValue(Expression expression, DelegateExecution execution) {
        if (expression == null) return null;
        Object value = expression.getValue(execution);
        return value != null ? value.toString() : null;
    }

    protected Map<String, Object> parseJsonField(Expression expression, DelegateExecution execution) {
        String jsonStr = getFieldValue(expression, execution);
        if (jsonStr == null || jsonStr.isEmpty()) {
            return new HashMap<>();
        }
        try {
            return objectMapper.readValue(jsonStr, new TypeReference<>() {
            });
        } catch (Exception e) {
            log.error("Failed to parse JSON field: {}", jsonStr, e);
            return new HashMap<>();
        }
    }

    protected void setExecutionStatus(DelegateExecution execution, String status) {
        execution.setVariable(WORKFLOW_PREVIOUS_NODE_EXECUTION_STATE_VARIABLE_NAME, status);
    }

    private void clearPreviousNodeStatus(DelegateExecution execution) {
        execution.removeVariable(WORKFLOW_PREVIOUS_NODE_EXECUTION_STATE_VARIABLE_NAME);
        log.debug("Cleared previous node status for node: {}", execution.getCurrentActivityId());
    }

} 