package com.yida.data.system.service.impl;

import cc.mrbird.febs.common.redis.service.RedisService;
import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yida.data.common.core.entity.WxPublicQr;
import com.yida.data.common.core.entity.constant.WxPublicQrTypeConstant;
import com.yida.data.common.core.entity.system.Dept;
import com.yida.data.common.core.entity.system.EduDeptWxPublic;
import com.yida.data.common.core.entity.system.enums.DeptTypeEnum;
import com.yida.data.common.core.utils.WxPublicUtil;
import com.yida.data.rabbit.constant.RabbitConstant;
import com.yida.data.rabbit.util.RabbitUtil;
import com.yida.data.system.aes.WXBizMsgCrypt;
import com.yida.data.system.mapper.DeptMapper;
import com.yida.data.system.mapper.EduAgentWxPublicReceiverMapper;
import com.yida.data.system.mapper.EduDeptWxPublicMapper;
import com.yida.data.system.service.EduAgentService;
import com.yida.data.system.service.WxPublicService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.StringReader;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@RequiredArgsConstructor
@Service
public class WxPublicServiceImpl implements WxPublicService {

    private final EduAgentService eduAgentService;
    private final EduAgentWxPublicReceiverMapper eduAgentWxPublicReceiverMapper;
    private final EduDeptWxPublicMapper eduDeptWxPublicMapper;
    private final DeptMapper deptMapper;

    private final RabbitUtil rabbitUtil;
    private final WxPublicUtil wxPublicUtil;
    private final RedisService redisService;

    @Override
    public String get(String signature, String timestamp, String nonce, String echostr, String appId) {
        EduDeptWxPublic sysWxPublic = eduDeptWxPublicMapper.selectOne(Wrappers.<EduDeptWxPublic>lambdaQuery()
            .eq(EduDeptWxPublic::getAppId, appId));
        List<String> strings = Arrays.asList(timestamp, nonce, sysWxPublic.getToken());
        String str = strings.stream().sorted().collect(Collectors.joining());
        String encodeStr = SecureUtil.sha1(str);
        log.info("singature:[{}],time:[{}],nonce:[{}],token:[{}],encode:[{}],str:[{}]",
            signature, timestamp,
            nonce, sysWxPublic.getToken(), encodeStr, str);
        if (signature.equals(encodeStr)) {
            return echostr;
        } else {
            return null;
        }
    }

    @Override
    public void post(String signature, String timestamp, String nonce, String body, String appId) {
        EduDeptWxPublic wxPublic = eduDeptWxPublicMapper.selectOne(Wrappers.<EduDeptWxPublic>lambdaQuery()
            .eq(EduDeptWxPublic::getAppId, appId));
        WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(wxPublic.getToken(), wxPublic.getAesKey(),
            wxPublic.getAppId());
        log.info("signature:[{}],timestamp:[{}],nonce:[{}]，body:[{}]", signature, timestamp, nonce, body);
        String msg = wxcpt.DecryptMsg(signature, timestamp, nonce, body);
        log.info("msg:{}", msg);
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        StringReader sr = new StringReader(msg);
        InputSource is = new InputSource(sr);
        DocumentBuilder db = null;
        Document document = null;
        try {
            db = dbf.newDocumentBuilder();
            document = db.parse(is);
        } catch (Exception e) {
            log.error("解析微信公众号回调信息失败,msg:{}", e.getMessage());
        }
        Element root = document.getDocumentElement();

        NodeList nodelist1 = root.getElementsByTagName("FromUserName");
        String userOpenId = nodelist1.item(0).getTextContent();

        NodeList nodelist2 = root.getElementsByTagName("Event");
        String event = nodelist2.item(0).getTextContent();

        NodeList nodelist3 = root.getElementsByTagName("EventKey");
        String eventKey = null;
        if (nodelist3.getLength() > 0) {
            eventKey = nodelist3.item(0).getTextContent();
        }

        Dept dept = deptMapper.selectById(wxPublic.getDeptId());

        log.info("微信公众消息通知,msg:[{}]", root);
        switch (event) {
            case "subscribe":
                if (eventKey.length() > 8) {
                    subscribe(eventKey.substring(8), userOpenId, dept);
                }
                break;
            case "SCAN":
                subscribe(eventKey, userOpenId, dept);
                break;
        }

    }

    private void subscribe(String agentIdStr, String userOpenId, Dept dept) {
        String[] split = agentIdStr.split("-");
        // 发送的消息
        WxPublicQr wxPublicQr = new WxPublicQr();
        wxPublicQr.setFlag(split[1]);
        wxPublicQr.setUserId(Long.valueOf(split[2]));
        wxPublicQr.setUserOpenId(userOpenId);
        wxPublicQr.setSchoolId(DeptTypeEnum.SCHOOL_TYPE.getValue().equals(dept.getDeptType()) ? dept.getDeptId() : null);
        String msgKey = null;
        switch (split[0]) {
            case WxPublicQrTypeConstant.AGENT_RECEIVE_MSG:
                msgKey = RabbitConstant.AGENT_RECEIVE_MSG_KEY;
                break;
            case WxPublicQrTypeConstant.VISITOR_INVITE_CODE:
                msgKey = RabbitConstant.VISITOR_INVITE_CODE_KEY;
                break;
        }
        if (msgKey != null) {
            rabbitUtil.convertAndSendMsg(RabbitConstant.WXPUBLIC_QR_EXCHANGE, msgKey, wxPublicQr);
        }
    }
}
