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

import cn.axzo.framework.rocketmq.Event;
import cn.axzo.framework.rocketmq.EventProducer;
import cn.axzo.workflow.common.enums.MessagePushEventEnum;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceQueryDTO;
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstanceVO;
import cn.axzo.workflow.common.model.response.mq.MessagePushDTO;
import cn.axzo.workflow.core.engine.event.MessagePushEvent;
import cn.axzo.workflow.core.listener.BpmnMessagePushEventListener;
import cn.axzo.workflow.core.service.BpmnProcessInstanceService;
import com.alibaba.fastjson.JSON;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.Objects;

import static cn.axzo.workflow.common.enums.MessagePushEventEnum.PROCESS_PUSH_NOTICE;
import static cn.axzo.workflow.common.enums.MessagePushEventEnum.PROCESS_PUSH_PENDING;
import static cn.axzo.workflow.common.enums.MessagePushEventEnum.PROCESS_PUSH_SMS;

/**
 * 特殊的相外部传递需发送站内信/待办/短信的事件处理器
 *
 * @author wangli
 * @since 2023/11/22 10:52
 */
@Slf4j
@Component
@AllArgsConstructor
public class MessagePushEventListener implements BpmnMessagePushEventListener, Ordered {

    private final EventProducer<?> eventProducer;
    private final BpmnProcessInstanceService processInstanceService;

    @Override
    public void onNotice(MessagePushEvent event) {
        if (Objects.isNull(event.getNoticeConfig()) || !StringUtils.hasLength(event.getNoticeConfig().getNoticeMessageId()) || Objects.isNull(event.getAssigner())) {
            return;
        }
        BpmnProcessInstanceQueryDTO queryDTO = new BpmnProcessInstanceQueryDTO();
        queryDTO.setProcessInstanceId(event.getProcessInstanceId());
        queryDTO.setHasVariable(true);
        BpmnProcessInstanceVO processInstanceVO = processInstanceService.getProcessInstanceVO(queryDTO);
        MessagePushDTO dto = build(event.getNoticeConfig().getNoticeMessageId(), PROCESS_PUSH_NOTICE,
                processInstanceVO, event);
        log.info("MessagePushEventListener#onNotice MQ.Data: {}", JSON.toJSONString(dto));
        sendMessageQueue(dto, PROCESS_PUSH_NOTICE);
    }

    @Override
    public void onPending(MessagePushEvent event) {
        if (Objects.isNull(event.getNoticeConfig()) || !StringUtils.hasLength(event.getNoticeConfig().getPendingMessageId()) || Objects.isNull(event.getAssigner())) {
            return;
        }
        BpmnProcessInstanceQueryDTO queryDTO = new BpmnProcessInstanceQueryDTO();
        BpmnProcessInstanceVO processInstanceVO = processInstanceService.getProcessInstanceVO(queryDTO);
        MessagePushDTO dto = build(event.getNoticeConfig().getNoticeMessageId(), PROCESS_PUSH_PENDING,
                processInstanceVO, event);
        log.info("MessagePushEventListener#onPending MQ.Data: {}", JSON.toJSONString(dto));
        sendMessageQueue(dto, PROCESS_PUSH_PENDING);
    }

    @Override
    public void onSms(MessagePushEvent event) {
        if (Objects.isNull(event.getNoticeConfig()) || !StringUtils.hasLength(event.getNoticeConfig().getSmsId()) || Objects.isNull(event.getAssigner())) {
            return;
        }
        BpmnProcessInstanceQueryDTO queryDTO = new BpmnProcessInstanceQueryDTO();
        BpmnProcessInstanceVO processInstanceVO = processInstanceService.getProcessInstanceVO(queryDTO);
        MessagePushDTO dto = build(event.getNoticeConfig().getNoticeMessageId(), PROCESS_PUSH_SMS,
                processInstanceVO, event);
        log.info("MessagePushEventListener#onSms MQ.Data: {}", JSON.toJSONString(dto));
        sendMessageQueue(dto, PROCESS_PUSH_SMS);
    }

    public MessagePushDTO build(String templateId, MessagePushEventEnum type, BpmnProcessInstanceVO instance,
                                MessagePushEvent event) {
        return new MessagePushDTO()
                .setType(type)
                .setTemplateId(templateId)
                .setReceivePerson(event.getAssigner());
    }

    public void sendMessageQueue(MessagePushDTO dto, MessagePushEventEnum eventEnum) {
        eventProducer.send(Event.builder()
                .shardingKey(dto.getId())
                .eventCode(eventEnum.getEventCode())
                .targetId(dto.getId())
                .targetType(eventEnum.getTag())
                .data(dto)
                .build());
    }

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