package cn.axzo.msg.center.event.outer;

import cn.axzo.framework.rocketmq.Event;
import cn.axzo.framework.rocketmq.EventConsumer;
import cn.axzo.framework.rocketmq.EventHandler;
import cn.axzo.im.center.common.enums.AppTypeEnum;
import cn.axzo.msg.center.api.request.MsgBody4Guest;
import cn.axzo.msg.center.dal.CardDao;
import cn.axzo.msg.center.domain.entity.Card;
import cn.axzo.msg.center.domain.enums.NativeTypeEnum;
import cn.axzo.msg.center.event.payload.MessageHistoryUpdatedPayload;
import cn.axzo.msg.center.inside.notices.service.IYouMengMessageService;
import cn.axzo.msg.center.message.domain.dto.TemplateModelV3;
import cn.axzo.msg.center.message.service.card.CardSupport;
import cn.axzo.msg.center.message.service.impl.v3.AppLink;
import cn.axzo.msg.center.message.service.impl.v3.ModelV3Service;
import cn.axzo.msg.center.nimpush.PushChannel;
import cn.axzo.msg.center.nimpush.device.PushDevice;
import cn.axzo.msg.center.nimpush.device.PushDeviceService;
import cn.axzo.msg.center.push.PushData;
import cn.axzo.msg.center.service.enums.TerminalTypeEnum;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
@Component
public class PushYouMengMessageHandler implements EventHandler, InitializingBean {

    @Autowired
    private EventConsumer eventConsumer;
    @Autowired
    private CardDao cardDao;
    @Autowired
    private ModelV3Service modelV3Service;
    @Autowired
    private IYouMengMessageService youMengMessageService;
    @Autowired
    private PushDeviceService pushDeviceService;

    /**
     * 按照这个顺序解析routerType
     */
    private static final List<TerminalTypeEnum> ROUTER_TYPE_SORTED = Lists.newArrayList(
            TerminalTypeEnum.IOS,
            TerminalTypeEnum.ANDROID,
            TerminalTypeEnum.WEB_VIEW,
            TerminalTypeEnum.MINI_PROGRAM,
            TerminalTypeEnum.WECHAT_MINI_PROGRAM);

    /**
     * 按照这个顺序解析IOS的url
     */
    private static final List<TerminalTypeEnum> IOS_URL_SORTED = Lists.newArrayList(
            TerminalTypeEnum.IOS,
            TerminalTypeEnum.WEB_VIEW,
            TerminalTypeEnum.MINI_PROGRAM,
            TerminalTypeEnum.WECHAT_MINI_PROGRAM);

    /**
     * 按照这个顺序解析ANDROID的url
     */
    private static final List<TerminalTypeEnum> ANDROID_URL_SORTED = Lists.newArrayList(
            TerminalTypeEnum.ANDROID,
            TerminalTypeEnum.WEB_VIEW,
            TerminalTypeEnum.MINI_PROGRAM,
            TerminalTypeEnum.WECHAT_MINI_PROGRAM);


    @Override
    public void onEvent(Event event, EventConsumer.Context context) {
        log.info("begin push-handler rocketmq event: {}", event);
        MessageHistoryUpdatedPayload payload = event.normalizedData(MessageHistoryUpdatedPayload.class);
        if (Objects.isNull(payload) || StringUtils.isBlank(payload.getNewMessageHistory().getBizId())) {
            return;
        }

        if (!payload.getNewMessageHistory().getBizId().startsWith(CardSupport.BIZ_ID_PREFIX)) {
            log.info("push-handler 非msg-center的消息");
            return;
        }

        if (!payload.isSuccess()) {
            log.info("push-handler is not success, event: {}", event);
            return;
        }

        Long imMessageTaskId = payload.getNewMessageHistory().getImMessageTaskId();

        Card card = cardDao.lambdaQuery()
                .eq(Card::getImTaskId, imMessageTaskId)
                .last("LIMIT 1")
                .one();
        if (card == null) {
            log.info("push-handler, 非当前业务的im消息. event: {}", event);
            return;
        }

        Optional<TemplateModelV3> messageTemplateDTO = modelV3Service.findEnabledByCode(card.getTemplateCode());
        if (!messageTemplateDTO.isPresent()) {
            log.info("push-handler, 模板code:{},不存在. event={}", card.getTemplateCode(), event);
            return;
        }

        PushData pushData = messageTemplateDTO.get().getTemplate().parsePushData();
        if (!pushData.determinePushable(log, card.getTemplateCode())) {
            return;
        }

        MessageHistoryUpdatedPayload.MessageHistory newMessageHistory = payload.getNewMessageHistory();
        MessageHistoryUpdatedPayload.MessageBody messageBody = newMessageHistory.resolveMessageBody();

        AppTypeEnum appType = AppTypeEnum.isValidAppType(newMessageHistory.getAppType());
        if (appType == null) {
            log.info("push-handler, 模板code:{},appType不合法, event: {}", card.getTemplateCode(), event);
            return;
        }
        PushDevice device = pushDeviceService
                .createDeviceSnapshots()
                .getDevice(Long.parseLong(newMessageHistory.getReceivePersonId()));
        if(!device.shouldPush(appType, PushChannel.YOU_MENG)) {
            log.info("push-handler, 模板code:{}, 友盟push不适用, event: {}", card.getTemplateCode(), event);
            return;
        }

        youMengMessageService.sendPushMessage(MsgBody4Guest.builder()
                .ty(0)
                .f("0")
                .appClient(newMessageHistory.getAppType())
                .m(card.getContent())
                .m3(newMessageHistory.getReceivePersonId())
                .m2(resolveM2(messageBody, pushData))
                // 为了兼容老版本，保证老版本的工人端能收到push，所以新的push都alias都是person
                .t("not_identity" + newMessageHistory.getReceivePersonId())
                .ouId(newMessageHistory.getReceiveOuId())
                .pushType(pushData.getType())
                .build());

        log.info("end push-handler rocketmq event: {}", event);
    }

    private String resolveM2(MessageHistoryUpdatedPayload.MessageBody messageBody,
                             PushData pushData) {
        JSONObject jsonObject = new JSONObject()
                .fluentPut("t", messageBody.getMsgHeader())
                .fluentPut("type", 0);
        if (StringUtils.isNotBlank(pushData.getVoiceFile())) {
            jsonObject.fluentPut("audio", pushData.getVoiceFile());
        }

        MessageHistoryUpdatedPayload.CardDetailButton cardDetailButton = messageBody.resolveMsgBody().getCardDetailButton();
        if (cardDetailButton != null && CollectionUtils.isNotEmpty(cardDetailButton.getActionPaths())) {
            resolveRouter(jsonObject, cardDetailButton.getActionPaths());
        }
        return jsonObject.toJSONString();
    }

    /**
     *
     * @param jsonObject
     * @param actionPaths
     */
    public void resolveRouter(JSONObject jsonObject, List<AppLink> actionPaths) {

        Map<TerminalTypeEnum, AppLink> actionPathMap = actionPaths.stream()
                .collect(Collectors.toMap(AppLink::getPlatform, Function.identity()));
        Optional<AppLink> routerType = ROUTER_TYPE_SORTED.stream()
                .map(actionPathMap::get)
                .filter(Objects::nonNull)
                .findFirst();
        routerType.ifPresent(actionPath -> jsonObject.fluentPut("rt", NativeTypeEnum.getByCode(actionPath.getPlatform().getCode()).getMessage()));

        Optional<AppLink> ios = IOS_URL_SORTED.stream()
                .map(actionPathMap::get)
                .filter(Objects::nonNull)
                .findFirst();
        // IOS的跳转URL
        ios.ifPresent(actionPath -> jsonObject.fluentPut("ir", actionPath.getUrl()));

        Optional<AppLink> android = ANDROID_URL_SORTED.stream()
                .map(actionPathMap::get)
                .filter(Objects::nonNull)
                .findFirst();
        // ANDROID的跳转URL
        android.ifPresent(actionPath -> jsonObject.fluentPut("ar", actionPath.getUrl()));

    }

    @Override
    public void afterPropertiesSet() throws Exception {
        eventConsumer.registerHandler(EventTypeEnum.MESSAGE_HISTORY_UPDATED.getEventCode(), this);
    }
}
