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

import cn.axzo.msg.center.dal.TodoBusinessDao;
import cn.axzo.msg.center.dal.TodoBusinesses;
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.domain.entity.TodoBusiness;
import cn.axzo.msg.center.message.domain.dto.TemplateModelV3;
import cn.axzo.msg.center.message.service.impl.v3.AppLink;
import cn.axzo.msg.center.message.service.impl.v3.NativeAppLinkUrlConfigVisitor;
import cn.axzo.msg.center.message.service.todo.TodoRespBuilder;
import cn.axzo.msg.center.message.service.todo.manage.TodoExt;
import cn.axzo.msg.center.message.service.youmeng.YoumengPush;
import cn.axzo.msg.center.message.service.youmeng.YoumengTemplateClient;
import cn.axzo.msg.center.nimpush.PushChannel;
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.domain.CardUrlConfig;
import cn.axzo.msg.center.service.domain.UrlConfig;
import cn.axzo.msg.center.service.domain.UrlConfigWalker;
import cn.axzo.msg.center.service.enums.PushTerminalEnum;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

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

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

    private final YoumengTemplateClient youmengTemplateClient;
    private final TodoBusinessDao todoBusinessDao;
    private final PushDeviceService pushDeviceService;
    private final TodoRespBuilder todoRespBuilder;

    @Override
    public void onApplicationEvent(@NotNull NewTodoEvent event) {
        log.info("Prepare sending todo push. event={}", event);
        MessageTemplateV3 template = event.getTemplateModel().getTemplate();
        if (!PushPriorityController.create(template).isPushViaTodo()) {
            log.info("Template is not pushable via todo. template={}", template);
            return;
        }

        PushData pushData = template.parsePushData();
        if (!pushData.determinePushable(log, event.getTemplateModel().getTemplateCode()))
            return;
        List<PushTerminalEnum> pushTerminals = template.determinePushTerminals();
        PushDeviceSnapshots deviceSnapshots = pushDeviceService.createDeviceSnapshots();
        ArrayList<YoumengPush> pushes = new ArrayList<>();
        for (Todo todo : event.getTodos()) {
            PushDevice pushDevice = deviceSnapshots.getDevice(todo.getExecutorPersonId());
            boolean doPush = pushTerminals.stream()
                    .anyMatch(pushTerminal -> pushDevice.shouldPush(pushTerminal, PushChannel.YOU_MENG));
            if (!doPush)
                continue;

            List<AppLink> navigations = determineNavigations(event.getTemplateModel(), todo);
            if (CollectionUtils.isEmpty(navigations))
                continue;
            YoumengPush push = new YoumengPush();
            push.setTitle(todo.getTitle());
            push.setContent(todo.getContent());
            push.setReceiverPersonId(todo.getExecutorPersonId());
            push.setReceiverOuId(todo.getOuId());
            push.setAppLinks(navigations);
            pushes.add(push);
        }
        if (CollectionUtils.isNotEmpty(pushes))
            youmengTemplateClient.asyncSend(template.getId(), pushes);
    }

    private List<AppLink> determineNavigations(TemplateModelV3 templateModel, Todo todo) {
        CardUrlConfig cardUrlConfig = templateModel.getTemplate().getCardUrlConfig();
        if (cardUrlConfig == null) return Collections.emptyList();
        UrlConfig urlConfig = cardUrlConfig.getUrlConfig();
        if (urlConfig == null)
            return Collections.emptyList();
        JSONObject routerParam = todo.getRouterParams();
        if (routerParam == null)
            routerParam = new JSONObject();
        TodoBusinesses businesses = todoBusinessDao.getBusinesses(todo);
        TodoBusiness business = businesses.findBusiness(todo).orElse(null);
        Map<String, Object> ctx = new HashMap<>();
        ctx.put("business", business);
        ctx.put("todo", todo);
        routerParam.put(TodoExt.CTX, ctx);

        UrlConfig parsedUrlConfig = parseUrlConfig(urlConfig, todo, routerParam);
        NativeAppLinkUrlConfigVisitor visitor = new NativeAppLinkUrlConfigVisitor();
        UrlConfigWalker.walkDown(parsedUrlConfig, visitor);
        return visitor.getLinks();
    }

    private UrlConfig parseUrlConfig(UrlConfig urlConfig,
                                     MessageEntity entity,
                                     JSONObject routerParam) {
        String json = JSON.toJSONString(urlConfig);
        UrlConfig copy = JSON.parseObject(json, UrlConfig.class);
        todoRespBuilder.createTodoUrlParser(entity, routerParam, routerParam).parseUrlConfig(copy);
        return copy;
    }
}