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

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yida.data.common.core.entity.system.Dept;
import com.yida.data.common.core.entity.system.EduQywxServiceProvider;
import com.yida.data.common.core.entity.system.EduQywxServiceProviderSchool;
import com.yida.data.common.core.entity.system.enums.DeptTypeEnum;
import com.yida.data.common.core.enums.QywxCallbackTypeEnum;
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.dto.QywxCallbackHandleDTO;
import com.yida.data.system.service.*;
import io.seata.spring.annotation.GlobalTransactional;
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.xml.sax.InputSource;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.StringReader;

/**
 * 企业微信回调类
 *
 * @author ZYJ
 * @date 2023/10/27 17:15
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class QywxCallbackServiceImpl implements QywxCallbackService {

    private final IDeptService deptService;
    private final EduQywxServiceProviderService eduQywxServiceProviderService;
    private final EduQywxServiceProviderSchoolService eduQywxServiceProviderSchoolService;

    private final RabbitUtil rabbitUtil;

    @Override
    public String get(String corpId, String msgSignature, String timestamp, String nonce, String echostr) {
        Dept school =
                deptService.getOne(Wrappers.lambdaQuery(new Dept()).eq(Dept::getCorpId, corpId).eq(Dept::getDeptType, DeptTypeEnum.SCHOOL_TYPE.getValue()));
        log.info("部门验证url回调params:{},{},{},{},{}", corpId, msgSignature, timestamp, nonce, echostr);
        WXBizMsgCrypt wxCpt = new WXBizMsgCrypt(school.getWxCallToken(), school.getWxAesKey(),
                school.getCorpId());
        String result = wxCpt.VerifyURL(msgSignature, timestamp, nonce, echostr);
        log.info("部门验证url回调call valid result:{}", result);
        return result;
    }

    @Override
    @GlobalTransactional
    public String post(String corpId, String msgSignature, String timestamp, String nonce, String body) {
        Dept school = deptService.getOne(Wrappers.lambdaQuery(new Dept())
                .eq(Dept::getCorpId, corpId)
                .eq(Dept::getDeptType, DeptTypeEnum.SCHOOL_TYPE.getValue())
        );
        log.info("部门回调params:{},{},{},{},{}", corpId, msgSignature, timestamp, nonce, body);
        WXBizMsgCrypt wxCpt = new WXBizMsgCrypt(school.getWxCallToken(), school.getWxAesKey(),
                school.getCorpId());
        String msg = wxCpt.DecryptMsg(msgSignature, 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());
            return "fail";
        }
        // 发送消息给rabbitmq
        rabbitUtil.convertAndSendMsg(RabbitConstant.QYWX_HANDLE_EXCHANGE, RabbitConstant.QYWX_HANDLE_KEY,
                QywxCallbackHandleDTO.builder()
                        .root(document.getDocumentElement())
                        .corpId(corpId)
                        .school(school)
                        .qywxCallbackTypeEnum(QywxCallbackTypeEnum.POST)
                        .build()
        );
        return "success";
    }

    @Override
    public String getNormal(String corpId, String msgSignature, String timestamp, String nonce, String echostr) {
        EduQywxServiceProvider serviceProvider =
                eduQywxServiceProviderService.getOne(Wrappers.lambdaQuery(new EduQywxServiceProvider())
                        .eq(EduQywxServiceProvider::getCorpId, corpId));
        log.info("服务商验证url回调params:{},{},{},{},{}", corpId, msgSignature, timestamp, nonce, echostr);
        WXBizMsgCrypt wxCpt = new WXBizMsgCrypt(serviceProvider.getWxCallToken(), serviceProvider.getWxAesKey(),
                serviceProvider.getCorpId());
        String result = wxCpt.VerifyURL(msgSignature, timestamp, nonce, echostr, false);
        log.info("服务商验证url回调call valid result:{}", result);
        return result;
    }

    @Override
    public String postNormal(String corpId, String msgSignature, String timestamp, String nonce, String body) {
        EduQywxServiceProvider serviceProvider =
                eduQywxServiceProviderService.getOne(Wrappers.lambdaQuery(new EduQywxServiceProvider())
                        .eq(EduQywxServiceProvider::getCorpId, corpId));
        log.info("服务商代开发应用模板接口回调params:{},{},{},{},{}", corpId, msgSignature, timestamp, nonce, body);
        WXBizMsgCrypt wxCpt = new WXBizMsgCrypt(serviceProvider.getWxCallToken(), serviceProvider.getWxAesKey(),
                serviceProvider.getCorpId());
        String msg = wxCpt.DecryptMsg(msgSignature, timestamp, nonce, body, false);
        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());
            return "fail";
        }

        // 发送消息给rabbitmq
        rabbitUtil.convertAndSendMsg(RabbitConstant.QYWX_HANDLE_EXCHANGE, RabbitConstant.QYWX_HANDLE_KEY,
                QywxCallbackHandleDTO.builder()
                        .root(document.getDocumentElement())
                        .eduQywxServiceProvider(serviceProvider)
                        .qywxCallbackTypeEnum(QywxCallbackTypeEnum.POST_NORMAL)
                        .build()
        );
        return "success";
    }

    @Override
    public String getNormalCustomer(String providerCorpId, String corpId, String msgSignature, String timestamp,
                                    String nonce, String echostr) {
        Dept school = deptService.getOne(Wrappers.lambdaQuery(new Dept()).eq(Dept::getCorpId, corpId).eq(Dept::getDeptType, 0));
        log.info("服务商代开发应用客户验证url回调params:{},{},{},{},{},{}", providerCorpId, corpId, msgSignature, timestamp, nonce, echostr);

        EduQywxServiceProviderSchool providerSchool = eduQywxServiceProviderSchoolService.getOne(Wrappers.lambdaQuery(new EduQywxServiceProviderSchool())
                .eq(EduQywxServiceProviderSchool::getProviderCorpId, providerCorpId)
                .eq(EduQywxServiceProviderSchool::getDeptOriginalCorpId, corpId));

        WXBizMsgCrypt wxCpt = new WXBizMsgCrypt(school.getWxCallToken(), school.getWxAesKey(),
                providerSchool.getDeptEncryptionCorpId());
        String result = wxCpt.VerifyURL(msgSignature, timestamp, nonce, echostr);
        log.info("服务商代开发应用客户验证url回调call valid result:{}", result);
        return result;
    }

    @Override
    public String postNormalCustomer(String providerCorpId, String corpId, String msgSignature, String timestamp, String nonce, String body) {
        Dept school =
                deptService.getOne(Wrappers.lambdaQuery(new Dept()).eq(Dept::getCorpId, corpId).eq(Dept::getDeptType, DeptTypeEnum.SCHOOL_TYPE.getValue()));
        log.info("服务商代开发应用客户接口回调params: {},{},{},{},{},{}", providerCorpId, corpId, msgSignature, timestamp, nonce, body);
        EduQywxServiceProviderSchool providerSchool = eduQywxServiceProviderSchoolService.getOne(Wrappers.lambdaQuery(new EduQywxServiceProviderSchool())
                .eq(EduQywxServiceProviderSchool::getProviderCorpId, providerCorpId)
                .eq(EduQywxServiceProviderSchool::getDeptOriginalCorpId, corpId));

        WXBizMsgCrypt wxCpt = new WXBizMsgCrypt(school.getWxCallToken(), school.getWxAesKey(),
                providerSchool.getDeptEncryptionCorpId());
        String msg = wxCpt.DecryptMsg(msgSignature, timestamp, nonce, body);
        log.info("msg:{}", msg);
        return "success";
    }

    @Override
    public String getEvent(String providerCorpId, String corpId, String msgSignature, String timestamp, String nonce, String echostr) {
        Dept school = deptService.getOne(Wrappers.lambdaQuery(new Dept()).eq(Dept::getCorpId, corpId).eq(Dept::getDeptType, DeptTypeEnum.SCHOOL_TYPE.getValue()));
        log.info("服务商代开发家校沟通验证url回调params:{},{},{},{},{},{}", providerCorpId, corpId, msgSignature, timestamp, nonce, echostr);

        EduQywxServiceProviderSchool providerSchool = eduQywxServiceProviderSchoolService.getOne(Wrappers.lambdaQuery(new EduQywxServiceProviderSchool())
                .eq(EduQywxServiceProviderSchool::getProviderCorpId, providerCorpId)
                .eq(EduQywxServiceProviderSchool::getDeptOriginalCorpId, corpId));

        WXBizMsgCrypt wxCpt = new WXBizMsgCrypt(school.getWxCallToken(), school.getWxAesKey(),
                providerSchool.getDeptEncryptionCorpId());
        String result = wxCpt.VerifyURL(msgSignature, timestamp, nonce, echostr);
        log.info("服务商代开发应用家校沟通验证url回调call valid result:{}", result);
        return result;
    }

    @Override
    public String postEvent(String providerCorpId, String corpId, String msgSignature, String timestamp, String nonce, String body) {
        Dept school = deptService.getOne(Wrappers.lambdaQuery(new Dept()).eq(Dept::getCorpId, corpId).eq(Dept::getDeptType, DeptTypeEnum.SCHOOL_TYPE.getValue()));
        log.info("服务商代开发家校沟通回调params: {},{},{},{},{},{}", providerCorpId, corpId, msgSignature, timestamp, nonce, body);
        EduQywxServiceProviderSchool providerSchool = eduQywxServiceProviderSchoolService.getOne(Wrappers.lambdaQuery(new EduQywxServiceProviderSchool())
                .eq(EduQywxServiceProviderSchool::getProviderCorpId, providerCorpId)
                .eq(EduQywxServiceProviderSchool::getDeptOriginalCorpId, corpId));

        WXBizMsgCrypt wxCpt = new WXBizMsgCrypt(school.getWxCallToken(), school.getWxAesKey(),
                providerSchool.getDeptEncryptionCorpId());
        String msg = wxCpt.DecryptMsg(msgSignature, 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());
            return "false";
        }
        Element root = document.getDocumentElement();
        if (root.getElementsByTagName("Event").getLength() == 0) {
            log.info("暂不处理当前回调数据");
            return "success";
        }
        // 发送消息给rabbitmq
        rabbitUtil.convertAndSendMsg(RabbitConstant.QYWX_HANDLE_EXCHANGE, RabbitConstant.QYWX_HANDLE_KEY,
                QywxCallbackHandleDTO.builder()
                        .root(root)
                        .school(school)
                        .providerSchool(providerSchool)
                        .qywxCallbackTypeEnum(QywxCallbackTypeEnum.POST_EVENT)
                        .build()
        );
        return "success";
    }
}
