package cn.axzo.workflow.server.controller.listener.process;

import cn.axzo.framework.rocketmq.Event;
import cn.axzo.framework.rocketmq.EventProducer;
import cn.axzo.workflow.common.enums.ElasticSearchEventEnum;
import cn.axzo.workflow.core.common.context.ProcessOperationContext;
import cn.axzo.workflow.core.listener.AbstractBpmnEventListener;
import cn.axzo.workflow.core.listener.BpmnProcessEventListener;
import lombok.extern.slf4j.Slf4j;
import org.flowable.common.engine.api.delegate.event.FlowableEngineEntityEvent;
import org.flowable.engine.delegate.event.FlowableCancelledEvent;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * 流程实例结束后，同步最新数据至 ES
 *
 * @author wangli
 * @since 2024-10-18 11:09
 */
@Slf4j
@Component
@Scope("prototype")
public class SyncToEsProcessEventListener extends AbstractBpmnEventListener<ProcessOperationContext> implements BpmnProcessEventListener, Ordered {
    @Resource
    private EventProducer<?> eventProducer;
    @Value("${sendMq:true}")
    private Boolean sendMQ;

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

    /**
     * 流程实例被撤回后回调
     *
     * @param event
     */
    @Override
    public void onCancelled(FlowableCancelledEvent event) {
        syncToEs(event.getProcessInstanceId());
    }

    /**
     * 流程实例被驳回后回调
     *
     * @param event
     */
    @Override
    public void onRejected(FlowableCancelledEvent event) {
        syncToEs(event.getProcessInstanceId());
    }

    /**
     * 流程实例被中止后回调
     *
     * @param event
     */
    @Override
    public void onAborted(FlowableCancelledEvent event) {
        syncToEs(event.getProcessInstanceId());
    }

    /**
     * 流程实例运行完成后回调
     * <p>
     * 注意: 完成只是说明流程实例已停止运行
     *
     * @param event
     */
    @Override
    public void onCompleted(FlowableEngineEntityEvent event) {
        syncToEs(event.getProcessInstanceId());
    }

    public void syncToEs(String processInstanceId) {
        sendMessageQueue(processInstanceId, ElasticSearchEventEnum.ELASTIC_SEARCH_SYNC);
    }

    private void sendMessageQueue(String processInstanceId, ElasticSearchEventEnum eventEnum) {
        if (!sendMQ) {
            return;
        }
        eventProducer.send(Event.builder()
                .shardingKey(processInstanceId)
                .eventCode(eventEnum.getEventCode())
                .targetId(processInstanceId)
                .targetType(processInstanceId)
                .data(processInstanceId)
                .build());
    }

}
