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

import cn.axzo.workflow.common.model.request.bpmn.activity.BpmnActivityTimeoutCallbackDTO;
import cn.axzo.workflow.common.exception.WorkflowEngineException;
import cn.axzo.workflow.core.engine.event.BizCallbackEventImpl;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.flowable.common.engine.api.delegate.event.FlowableEventDispatcher;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.flowable.engine.impl.util.CommandContextUtil;
import org.flowable.job.service.JobHandler;
import org.flowable.job.service.impl.persistence.entity.JobEntity;
import org.flowable.task.api.Task;
import org.flowable.variable.api.delegate.VariableScope;
import org.springframework.util.CollectionUtils;

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

import static cn.axzo.workflow.common.code.BpmnInstanceRespCode.PROCESS_INSTANCE_ID_NOT_EXISTS;

/**
 * 业务节点的触发离开的任务处理器
 *
 * @author wangli
 * @since 2024-08-16 16:29
 */
@Slf4j
public class AsyncActivityCallbackJobHandler extends AbstractJobHandler implements JobHandler {
    public static final String TYPE = "business-node-callback";

    @Override
    public String getType() {
        return TYPE;
    }

    @Override
    public void execute(JobEntity job, String configuration, VariableScope variableScope, CommandContext commandContext) {
        log.warn("AsyncActivityLeaveJobHandler exec start...");
        BpmnActivityTimeoutCallbackDTO dto = JSON.parseObject(job.getCustomValues(), BpmnActivityTimeoutCallbackDTO.class);
        ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext);
        FlowableEventDispatcher eventDispatcher = processEngineConfiguration.getEventDispatcher();
        TaskService taskService = processEngineConfiguration.getTaskService();
        Task task = taskService.createTaskQuery().executionId(dto.getTriggerId()).singleResult();

        HistoryService historyService = processEngineConfiguration.getHistoryService();
        HistoricProcessInstance processInstance = historyService.createHistoricProcessInstanceQuery().includeProcessVariables()
            .processInstanceId(task.getProcessInstanceId()).singleResult();
        if (Objects.isNull(processInstance)) {
            throw new WorkflowEngineException(PROCESS_INSTANCE_ID_NOT_EXISTS, task.getProcessInstanceId());
        }
        RuntimeService runtimeService = processEngineConfiguration.getRuntimeService();
        runtimeService.setVariables(processInstance.getId(), dto.getVariables());

        Map<String, Object> processVariables = new HashMap<>(processInstance.getProcessVariables());
        if (!CollectionUtils.isEmpty(dto.getVariables())) {
            processVariables.putAll(dto.getVariables());
        }
        eventDispatcher.dispatchEvent(new BizCallbackEventImpl(BizCallbackEventImpl.BizCallbackEventType.CALLBACK,
                task.getTaskDefinitionKey(), task.getName(),
                task.getProcessInstanceId(), task.getProcessDefinitionId(),
                processInstance.getBusinessKey(), dto.getTriggerId(),
                processVariables),
            processEngineConfiguration.getEngineCfgKey());
    }
}
