package cn.axzo.workflow.core.listener.impl;

import cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
import cn.axzo.workflow.core.common.context.TaskOperationContext;
import cn.axzo.workflow.core.engine.event.ExtTaskInstCreateEvent;
import cn.axzo.workflow.core.engine.event.ExtTaskInstUpdateEvent;
import cn.axzo.workflow.core.listener.AbstractBpmnEventListener;
import cn.axzo.workflow.core.listener.BpmnTaskEventListener;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.flowable.common.engine.api.delegate.event.FlowableEventDispatcher;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.flowable.engine.impl.util.CommandContextUtil;
import org.flowable.task.service.delegate.DelegateTask;
import org.springframework.stereotype.Component;

import java.util.Objects;

import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_INITIATOR;
import static cn.axzo.workflow.common.constant.BpmnConstants.OLD_INTERNAL_INITIATOR;
import static cn.axzo.workflow.common.constant.BpmnConstants.TASK_COMPLETE_OPERATION_TYPE;
import static cn.axzo.workflow.common.enums.BpmnFlowNodeType.NODE_STARTER;
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.DELETED;
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.PROCESSING;

/**
 * Core 包内置的,可共用与 Jar 包集成和微服务集成
 *
 * @author wangli
 * @since 2023/12/9 22:56
 */
@Slf4j
@Component
@AllArgsConstructor
public class InternalExtAxTaskInstEvent_lo_Listener extends AbstractBpmnEventListener<TaskOperationContext> implements BpmnTaskEventListener {
    private final RuntimeService runtimeService;

    @Override
    public int getOrder() {
        return Integer.MIN_VALUE;
    }

    @Override
    public void onCreated(DelegateTask delegateTask) {
        String assignee;
        // 记录发起人
        if (Objects.equals(delegateTask.getTaskDefinitionKey(), NODE_STARTER.getType())) {
            BpmnTaskDelegateAssigner assigner = getContext().getInitiator(() ->
                    BpmnTaskDelegateAssigner.toObjectCompatible(runtimeService.getVariable(delegateTask.getProcessInstanceId(),
                            INTERNAL_INITIATOR)));
            if (Objects.isNull(assigner)) {
                // 兼容历史数据
                assigner = getContext().getInitiator(() ->
                        BpmnTaskDelegateAssigner.toObjectCompatible(runtimeService.getVariable(delegateTask.getProcessInstanceId(), OLD_INTERNAL_INITIATOR)));
            }
            assignee = assigner.buildAssigneeId();
        } else {
            assignee = delegateTask.getAssignee();
        }

        ProcessEngineConfigurationImpl processEngineConfiguration =
                CommandContextUtil.getProcessEngineConfiguration();
        FlowableEventDispatcher eventDispatcher = processEngineConfiguration.getEventDispatcher();
        eventDispatcher.dispatchEvent(new ExtTaskInstCreateEvent(delegateTask.getProcessInstanceId(),
                        delegateTask.getTaskDefinitionKey(), delegateTask.getId(), assignee, PROCESSING),
                processEngineConfiguration.getEngineCfgKey());
    }

    @Override
    public void onDeleted(DelegateTask delegateTask) {
        Object operationType = delegateTask.getTransientVariable(TASK_COMPLETE_OPERATION_TYPE + delegateTask.getId());
        log.info("taskId:{}, operationType:{}", delegateTask.getId(), operationType);

        // 多实例或签同意时,无法正确区分状态, 所以默认认为这种是无需展示在日志中的
        BpmnProcessInstanceResultEnum resultEnum = DELETED;

        if (Objects.nonNull(operationType)) {
            resultEnum = BpmnProcessInstanceResultEnum.valueOfStatus(String.valueOf(operationType));
        }

        ProcessEngineConfigurationImpl processEngineConfiguration =
                CommandContextUtil.getProcessEngineConfiguration();
        FlowableEventDispatcher eventDispatcher = processEngineConfiguration.getEventDispatcher();
        eventDispatcher.dispatchEvent(new ExtTaskInstUpdateEvent(delegateTask.getProcessInstanceId(),
                        delegateTask.getTaskDefinitionKey(), delegateTask.getId(), resultEnum),
                processEngineConfiguration.getEngineCfgKey());
    }
}
