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

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yida.data.common.core.entity.constant.AppConstant;
import com.yida.data.common.core.entity.constant.QywxConstant;
import com.yida.data.common.core.entity.system.Dept;
import com.yida.data.common.core.entity.system.EduApp;
import com.yida.data.common.core.utils.WxUtil;
import com.yida.data.common.service.CommonService;
import com.yida.data.system.aes.WXBizMsgCrypt;
import com.yida.data.system.service.IDeptService;
import com.yida.data.system.service.IUserService;
import com.yida.data.system.service.QywxCallbackService;
import com.yida.data.system.service.QywxService;
import com.yida.data.user.feign.RemoteStudentService;
import com.yida.data.user.feign.RemoteTeacherService;
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.w3c.dom.NodeList;
import org.xml.sax.InputSource;

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

@Slf4j
@Service
@RequiredArgsConstructor
public class QywxCallbackServiceImpl implements QywxCallbackService {

    private final IDeptService deptService;
    private final IUserService userService;
    private final QywxService qywxService;

    private final WxUtil wxUtil;
    private final CommonService commonService;
    private final RemoteTeacherService remoteTeacherService;
    private final RemoteStudentService remoteStudentService;

    @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, 0));
        log.info("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("call valid result:{}", result);
        return result;
    }

    @Override
    @GlobalTransactional
    public void 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, 0));
        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());
        }
        Element root = document.getDocumentElement();

        NodeList nodelist1 = root.getElementsByTagName("ChangeType");
        String changeType = nodelist1.item(0).getTextContent();

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

        if (QywxConstant.SCHOOL_CONTACT_EVENT.equals(event)) {

            EduApp app = commonService.getAppByCodeAndSchool(AppConstant.CONTACT_SCHOOL, null, school.getDeptId());
            String id = root.getElementsByTagName("Id").item(0).getTextContent();

            switch (changeType) {
                case QywxConstant.SCHOOL_DEPT_CREATE_TYPE:
                    qywxService.createSchoolDept(corpId, wxUtil.getAccessToken(app.getWxCorpId(),
                            app.getWxSecret()), Long.valueOf(id), school);
                    break;
                case QywxConstant.SCHOOL_DEPT_UPDATE_TYPE:
                    qywxService.updateSchoolDept(wxUtil.getAccessToken(app.getWxCorpId(),
                            app.getWxSecret()), Long.valueOf(id), school);
                    break;
                case QywxConstant.SCHOOL_DEPT_DELETE_TYPE:
                    qywxService.deleteSchoolDept(Long.valueOf(id), school);
                    break;
                case QywxConstant.STUDENT_CREATE_TYPE:
                case QywxConstant.STUDENT_UPDATE_TYPE:
                    qywxService.changeStudent(wxUtil.getAccessToken(app.getWxCorpId(),
                            app.getWxSecret()), id, school);
                    break;
                case QywxConstant.STUDENT_DELETE_TYPE:
                    qywxService.deleteStudent(id, school.getDeptId());
                    break;
                case QywxConstant.PARENT_CREATE_TYPE:
                    // 新增家长可能是创建学生时创建，等待2s确保学生创建完成
                    try {
                        Thread.sleep(2000);
                    } catch (Exception e) {

                    }
                case QywxConstant.PARENT_UPDATE_TYPE:
                    qywxService.updateParent(wxUtil.getAccessToken(app.getWxCorpId(),
                            app.getWxSecret()), id, school.getDeptId());
                    break;
                case QywxConstant.PARENT_DELETE_TYPE:
                    qywxService.deleteParent(id, school.getDeptId());
                    break;
                case QywxConstant.PARENT_SUBSCRIBE_TYPE:
                    log.info("进入家长关注事件回调");
                    // 调用家长关注发送通知方法
                    qywxService.sendParentSubscribeMessage(id, school.getDeptId());
                    break;
                case QywxConstant.PARENT_UNSUBSCRIBE_TYPE:
                    log.info("进入家长取消关注事件回调");
                    break;
                default:
                    break;
            }
        }

        if (QywxConstant.CONTACT_EVENT.equals(event)) {
            String userid = null, phone = null, name = null, gender = null, avatar = null, department = null,
                    isLeader = null, mainDepartment = null, email = null;
            if (root.getElementsByTagName("UserID").getLength() != 0) {
                userid = root.getElementsByTagName("UserID").item(0).getTextContent();
            }
            if (root.getElementsByTagName("Mobile").getLength() != 0) {
                phone = root.getElementsByTagName("Mobile").item(0).getTextContent();
            }
            if (root.getElementsByTagName("Name").getLength() != 0) {
                name = root.getElementsByTagName("Name").item(0).getTextContent();
            }
            if (root.getElementsByTagName("Gender").getLength() != 0) {
                gender = root.getElementsByTagName("Gender").item(0).getTextContent();
            }
            if (root.getElementsByTagName("Avatar").getLength() != 0) {
                avatar = root.getElementsByTagName("Avatar").item(0).getTextContent();
            }
            if (root.getElementsByTagName("Department").getLength() != 0) {
                department = root.getElementsByTagName("Department").item(0).getTextContent();
            }
            if (root.getElementsByTagName("IsLeaderInDept").getLength() != 0) {
                isLeader = root.getElementsByTagName("IsLeaderInDept").item(0).getTextContent();
            }
            if (root.getElementsByTagName("MainDepartment").getLength() != 0) {
                mainDepartment = root.getElementsByTagName("MainDepartment").item(0).getTextContent();
            }
            if (root.getElementsByTagName("Email").getLength() != 0) {
                email = root.getElementsByTagName("Email").item(0).getTextContent();
            }


            String deptId = null, deptName = null, deptParentId = null, order = null;
            if (root.getElementsByTagName("Id").getLength() != 0) {
                deptId = root.getElementsByTagName("Id").item(0).getTextContent();
            }
            if (root.getElementsByTagName("Name").getLength() != 0) {
                deptName = root.getElementsByTagName("Name").item(0).getTextContent();
            }
            if (root.getElementsByTagName("ParentId").getLength() != 0) {
                deptParentId = root.getElementsByTagName("ParentId").item(0).getTextContent();
            }
            if (root.getElementsByTagName("Order").getLength() != 0) {
                order = root.getElementsByTagName("Order").item(0).getTextContent();
            }

            switch (changeType) {
                case QywxConstant.USER_CREATE_TYPE:
                    qywxService.createUser(name, userid, phone, email, gender, avatar, department, isLeader,
                            mainDepartment, school);
                    break;
                case QywxConstant.USER_UPDATE_TYPE:
                    qywxService.updateUser(name, userid, phone, email, gender, avatar, department, isLeader,
                            mainDepartment, school);
                    break;
                case QywxConstant.USER_DELETE_TYPE:
                    qywxService.deleteUser(userid, school.getDeptId());
                    break;
                case QywxConstant.DEPT_CREATE_TYPE:
                    qywxService.createDept(deptId, deptName, deptParentId, order, school);
                    break;
                case QywxConstant.DEPT_UPDATE_TYPE:
                    qywxService.updateDept(deptId, deptName, deptParentId, school.getDeptId());
                    break;
                case QywxConstant.DEPT_DELETE_TYPE:
                    qywxService.deleteDept(deptId, school.getDeptId());
                    break;
            }
        }
    }
}
