package cn.axzo.msg.center.message.service.todo.manage.event;

import cn.axzo.framework.domain.web.result.ApiResult;
import cn.axzo.im.center.api.feign.MessageApi;
import cn.axzo.im.center.api.vo.ApiChannel;
import cn.axzo.im.center.api.vo.req.CustomMessageInfo;
import cn.axzo.im.center.api.vo.resp.MessageCustomResp;
import cn.axzo.im.center.common.enums.AppTypeEnum;
import cn.axzo.msg.center.common.utils.BizAssertions;
import cn.axzo.msg.center.domain.entity.MessageEntity;
import cn.axzo.msg.center.domain.entity.MessageTemplateV3;
import cn.axzo.msg.center.domain.entity.Todo;
import cn.axzo.msg.center.inside.notices.service.impl.v3.msg.TerminalAppMapping;
import cn.axzo.msg.center.message.domain.dto.TemplateModelV3;
import cn.axzo.msg.center.message.service.impl.v3.ModelV3Parser;
import cn.axzo.msg.center.nimpush.NimPushService;
import cn.axzo.msg.center.nimpush.PushChannel;
import cn.axzo.msg.center.nimpush.PushExecutorConfig;
import cn.axzo.msg.center.nimpush.PushPeer;
import cn.axzo.msg.center.nimpush.PushPriorityController;
import cn.axzo.msg.center.nimpush.device.PushDevice;
import cn.axzo.msg.center.nimpush.device.PushDeviceService;
import cn.axzo.msg.center.nimpush.device.PushDeviceSnapshots;
import cn.axzo.msg.center.push.PushData;
import cn.axzo.msg.center.service.enums.PushTerminalEnum;
import cn.axzo.msg.center.service.pending.response.v3.model.ParsedModelV3;
import com.alibaba.fastjson.JSON;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutorService;

/**
 * @author yanglin
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class TodoPushSenderNim implements ApplicationListener<NewTodoEvent> {

    private final NimPushService nimPushService;
    private final MessageApi messageApi;
    private final ModelV3Parser modelV3Parser;
    private final TerminalAppMapping terminalAppMapping;
    private final PushDeviceService pushDeviceService;
    @Qualifier(PushExecutorConfig.PUSH_EXECUTOR)
    private final ExecutorService executor;

    @Override
    public void onApplicationEvent(NewTodoEvent event) {
        MessageTemplateV3 template = event.getTemplateModel().getTemplate();
        if (!PushPriorityController.create(template).isPushViaTodo()) {
            log.info("Template is not pushable via todo. template={}", template);
            return;
        }
        List<PushTerminalEnum> pushTerminals = template.determinePushTerminals();
        List<AppTypeEnum> appTypes = terminalAppMapping.toImTypes(pushTerminals);
        if (CollectionUtils.isEmpty(appTypes)) return;
        ParsedModelV3 parsedModelV3 = parseModelForTodoPush(
                        event.getTemplateModel(), event.getTodos().get(0));
        PushData pushData = parsedModelV3.getPushData();
        if (pushData != null && !pushData.determinePushable(log, parsedModelV3.getTemplateCode())) {
            return;
        }
        String imSenderAccount = BizAssertions.assertResponse(messageApi.getCustomMessageSendImAccount());
        PushDeviceSnapshots deviceSnapshots = pushDeviceService.createDeviceSnapshots();
        for (Todo todo : event.getTodos()) {
            executor.submit(() -> {
                for (AppTypeEnum appType : appTypes) {
                    PushDevice pushDevice = deviceSnapshots.getDevice(todo.getExecutorPersonId());
                    if (!pushDevice.shouldPush(appType, PushChannel.NIM))
                        continue;

                    PushPeer peer = new PushPeer();
                    peer.setSenderImAccount(imSenderAccount);
                    peer.setOuId(todo.getOuId());
                    peer.setWorkspaceId(todo.getOrgId());
                    peer.setAppType(appType);
                    peer.setApiChannel(ApiChannel.CUSTOM_MESSAGE);
                    String payload = nimPushService.buildPayloadString(parsedModelV3, peer);
                    if (StringUtils.isBlank(payload))
                        continue;
                    CustomMessageInfo pushRequest = new CustomMessageInfo();
                    pushRequest.setAppTypeList(Collections.singletonList(appType));
                    pushRequest.setToPersonId(todo.getExecutorPersonId() + "");
                    pushRequest.setOuId(todo.getOuId());
                    pushRequest.setPayload(payload);
                    pushRequest.setPush(true);
                    if (pushData != null && StringUtils.isNotBlank(pushData.getVoiceFile())) {
                        pushRequest.setSound(pushData.getVoiceFile());
                    }
                    ApiResult<List<MessageCustomResp>> pushResponse = null;
                    try {
                        pushResponse = messageApi.sendCustomMessage(pushRequest);
                    } catch (Exception e) {
                        log.warn("Nim push error", e);
                    } finally {
                        log.info("Nim push request={}, response={}",
                                JSON.toJSONString(pushRequest), JSON.toJSONString(pushResponse));
                    }
                }
            });
        }
    }

    public ParsedModelV3 parseModelForTodoPush(
            TemplateModelV3 templateModel, MessageEntity entity) {
        return modelV3Parser.parseModelForTodo(templateModel, entity,
                entity.bizParam(), entity.routerParam(),
                null, null);
    }
}