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

import cn.axzo.workflow.common.model.request.bpmn.BpmnNoticeConf;
import cn.axzo.workflow.core.common.context.ProcessOperationContext;
import cn.axzo.workflow.core.common.utils.BpmnMetaParserHelper;
import cn.axzo.workflow.core.engine.event.MessagePushEventBuilder;
import cn.axzo.workflow.core.engine.event.MessagePushEventImpl;
import cn.axzo.workflow.core.engine.event.MessagePushEventType;
import cn.axzo.workflow.core.listener.AbstractBpmnEventListener;
import cn.axzo.workflow.core.listener.BpmnProcessEventListener;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.flowable.common.engine.api.delegate.event.FlowableEngineEntityEvent;
import org.flowable.common.engine.api.delegate.event.FlowableEngineEvent;
import org.flowable.common.engine.api.delegate.event.FlowableEventDispatcher;
import org.flowable.engine.delegate.event.FlowableCancelledEvent;
import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.flowable.engine.impl.util.CommandContextUtil;
import org.flowable.engine.impl.util.ProcessDefinitionUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.Objects;
import java.util.Optional;

/**
 * 流程实例的 MQ 发送监听
 *
 * @author wangli
 * @since 2023/7/10 18:22
 */
@Slf4j
@Component
@RefreshScope
public class MessagePushProcessEventListener extends AbstractBpmnEventListener<ProcessOperationContext> implements BpmnProcessEventListener, Ordered {
    @Value("${workflow.carbonCopyTemplateCode}")
    private String carbonCopyTemplateCode;
    @Override
    public void onCancelled(FlowableCancelledEvent event) {
        log.info("MessagePushProcessEventListener#onCancelled...{}", event.getProcessInstanceId());
        pendingComplete(event);
        log.info("MessagePushProcessEventListener#onCancelled...end: {}", event.getProcessInstanceId());
    }

    @Override
    public void onRejected(FlowableCancelledEvent event) {
        log.info("MessagePushProcessEventListener#onRejected...{}", event.getProcessInstanceId());
        pendingComplete(event);
        log.info("MessagePushProcessEventListener#onRejected...end: {}", event.getProcessInstanceId());
    }

    @Override
    public void onAborted(FlowableCancelledEvent event) {
        log.info("MessagePushProcessEventListener#onAborted...{}", event.getProcessInstanceId());
        pendingComplete(event);
        log.info("MessagePushProcessEventListener#onAborted...end: {}", event.getProcessInstanceId());
    }

    @Override
    public void onCompleted(FlowableEngineEntityEvent event) {
        log.info("MessagePushProcessEventListener#onCompleted...{}", event.getProcessInstanceId());
        pendingComplete(event);
        log.info("MessagePushProcessEventListener#onCompleted...end: {}", event.getProcessInstanceId());
    }

    private void pendingComplete(FlowableEngineEvent event) {
        ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration();
        FlowableEventDispatcher eventDispatcher = processEngineConfiguration.getEventDispatcher();
        Optional<BpmnNoticeConf> optNoticeConfig =
                BpmnMetaParserHelper.getNoticeConfig(ProcessDefinitionUtil.getProcess(event.getProcessDefinitionId()));
        optNoticeConfig.ifPresent(noticeConfig -> {
            MessagePushEventImpl messagePushEvent =
                    MessagePushEventBuilder.createEvent(MessagePushEventType.PENDING_COMPLETE, null, noticeConfig,
                            event.getProcessInstanceId(), null, null);

            log.info("发送完成待办的消息: {}", JSONUtil.toJsonStr(messagePushEvent));

            eventDispatcher.dispatchEvent(messagePushEvent, processEngineConfiguration.getEngineCfgKey());
            if (Objects.nonNull(noticeConfig.getCarbonCopy())) {
                if (!StringUtils.hasText(noticeConfig.getCarbonCopy().getCarbonCopyMessageId())) {
                    noticeConfig.getCarbonCopy().setCarbonCopyMessageId(carbonCopyTemplateCode);
                }
                MessagePushEventImpl carbonCopyCompleteEvent =
                        MessagePushEventBuilder.createEvent(MessagePushEventType.CARBON_COPY_COMPLETE, null, noticeConfig,
                                event.getProcessInstanceId(), null, null);
                eventDispatcher.dispatchEvent(carbonCopyCompleteEvent, processEngineConfiguration.getEngineCfgKey());
                log.info("发送完成抄送的消息: {}", JSONUtil.toJsonStr(carbonCopyCompleteEvent));
            }

        });
    }

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