package cn.axzo.msg.center.inside.notices.service.impl.v4;

import cn.axzo.basics.common.exception.ServiceException;
import cn.axzo.msg.center.api.request.v4.MessageSendBasicInfoV4;
import cn.axzo.msg.center.api.request.v4.MessageSendRequestV4;
import cn.axzo.msg.center.api.request.v4.TemplateInfo;
import cn.axzo.msg.center.api.response.v3.MessageSendRespV3;
import cn.axzo.msg.center.common.utils.BizAssertions;
import cn.axzo.msg.center.inside.notices.service.MessageServiceV4;
import cn.axzo.msg.center.inside.notices.service.impl.v3.EventMappingProcessor;
import cn.axzo.msg.center.inside.notices.service.impl.v3.msg.CardMappingProcessor;
import cn.axzo.msg.center.inside.notices.service.impl.v3.todo.TodoMappingProcessor;
import cn.axzo.msg.center.inside.notices.utils.FunctionalTransactionTemplate;
import cn.axzo.msg.center.message.domain.dto.TemplateModelV3;
import cn.axzo.msg.center.message.service.impl.v3.ModelV3Service;
import cn.axzo.msg.center.service.enums.Channel;
import cn.axzo.msg.center.utils.UUIDUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * @author yanglin
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class MessageServiceV4Impl implements MessageServiceV4 {

    private final ModelV3Service modelV3Service;
    private final FunctionalTransactionTemplate transactionTemplate;
    private final ApplicationContext beanFactory;

    @Override
    public MessageSendRespV3 send(MessageSendRequestV4 request) {
        log.info("received sending message request. req={}", request);
        BizAssertions.assertNotNull(request.getTemplates(), "模版信息不能为空");
        MessageSendBasicInfoV4 sendBasicInfo = request.getSendBasicInfo();
        BizAssertions.assertNotNull(sendBasicInfo, "发送IM和待办的基本信息不能为空");
        sendBasicInfo.validate();
        String sendRequestNo = UUIDUtil.uuidString();
        List<EventMappingProcessor> processors = new ArrayList<>();
        for (TemplateInfo info : request.getTemplates()) {
            BizAssertions.assertNotEmpty(info.getTemplateCodes(), "模版编码不能为空");
            for (String templateCode : info.getTemplateCodes()) {
                TemplateModelV3 templateModel = modelV3Service
                        .findEnabledByCode(templateCode)
                        .orElseThrow(() -> new ServiceException(String.format(
                                "未查询到对应的模板, templateCode=%s", templateCode)));
                if (info.getChannel() == Channel.NOTIFICATION) {
                    // @Scope("prototype") -> we're good
                    CardMappingProcessor imProcessor = beanFactory.getBean(CardMappingProcessor.class);
                    imProcessor.setSendBasicInfo(sendBasicInfo);
                    imProcessor.setChannel(info.getChannel());
                    imProcessor.setTemplateModel(templateModel);
                    processors.add(imProcessor);
                } else if (info.getChannel() == Channel.PENDING) {
                    // @Scope("prototype") -> we're good
                    TodoMappingProcessor todoProcessor = beanFactory.getBean(TodoMappingProcessor.class);
                    todoProcessor.setSendRequestNo(sendRequestNo);
                    todoProcessor.setReq(request);
                    todoProcessor.setTemplateModel(templateModel);
                    todoProcessor.setChannel(info.getChannel());
                    processors.add(todoProcessor);
                }
            }
        }

        transactionTemplate.exec(() -> processors.forEach(EventMappingProcessor::saveRecords));
        processors.forEach(EventMappingProcessor::maybeAsyncSend);
        MessageSendRespV3 resp = new MessageSendRespV3(sendRequestNo, new HashMap<>());
        processors.forEach(p -> resp.addResult(p.buildTemplateSendResult()));
        return resp;
    }

}