package cn.axzo.workflow.core.engine.cmd;

import org.flowable.common.engine.impl.interceptor.Command;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.engine.HistoryService;
import org.flowable.engine.ManagementService;
import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.flowable.engine.impl.util.CommandContextUtil;
import org.flowable.variable.api.history.HistoricVariableInstance;
import org.flowable.variable.api.history.NativeHistoricVariableInstanceQuery;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.Collections;
import java.util.List;

/**
 * 特殊场景下使用的命令，不建议通用使用
 * <p>
 * 自定义指定实例下的指定名称的变量数据
 *
 * @author wangli
 * @since 2024-10-14 13:43
 */
public class CustomGetHistoricVariablesCmd implements Command<List<HistoricVariableInstance>> {

    private final String processInstanceId;
    private final List<String> variableNames;

    public CustomGetHistoricVariablesCmd(String processInstanceId, List<String> variableNames) {
        this.processInstanceId = processInstanceId;
        this.variableNames = variableNames;
    }

    @Override
    public List<HistoricVariableInstance> execute(CommandContext commandContext) {
        ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext);
        HistoryService historyService = processEngineConfiguration.getHistoryService();

        if (StringUtils.hasText(processInstanceId) && !CollectionUtils.isEmpty(variableNames)) {
            NativeHistoricVariableInstanceQuery query = historyService.createNativeHistoricVariableInstanceQuery()
                    .sql(buildQuerySql(commandContext))
                    .parameter("processInstanceId", processInstanceId);
            if (!CollectionUtils.isEmpty(variableNames)) {
                for (int i = 0; i < variableNames.size(); i++) {
                    query.parameter("variableName" + i, variableNames.get(i));
                }
            }
            return query.list();
        }
        return Collections.emptyList();
    }

    private String buildQuerySql(CommandContext commandContext) {
        ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext);
        ManagementService managementService = processEngineConfiguration.getManagementService();
        StringBuilder baseQuerySql = new StringBuilder("SELECT * ")
                .append(" FROM ")
                .append(managementService.getTableName(HistoricVariableInstance.class))
                .append(" WHERE 1 = 1")
                .append(" AND PROC_INST_ID_ = #{processInstanceId}");

        if (!CollectionUtils.isEmpty(variableNames)) {
            baseQuerySql.append(" AND (");
            for (int i = 0; i < variableNames.size(); i++) {
                if (i != 0) {
                    baseQuerySql.append(" OR ");
                }
                baseQuerySql.append(" NAME_ = #{variableName").append(i).append("}");
            }
        }
        return baseQuerySql.append(")").toString();
    }
}
