package com.linkwechat.web.controller.wecom;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.linkwechat.common.constant.Constants;
import com.linkwechat.common.core.domain.entity.WeCorpAccount;
import com.linkwechat.common.core.domain.model.LoginUser;
import com.linkwechat.common.utils.SecurityUtils;
import com.linkwechat.common.utils.StringUtils;
import com.linkwechat.common.utils.Threads;
import com.linkwechat.common.utils.wecom.WxCryptUtil;
import com.linkwechat.framework.web.service.SysLoginService;
import com.linkwechat.web.controller.common.CommonController;
import com.linkwechat.wecom.domain.vo.WxCpXmlMessageVO;
import com.linkwechat.wecom.factory.WeCallBackEventFactory;
import com.linkwechat.wecom.factory.WeEventHandle;
import com.linkwechat.wecom.service.IWeCorpAccountService;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.security.AnyTypePermission;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.util.xml.XStreamInitializer;
import me.chanjar.weixin.cp.bean.WxCpXmlMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;

/**
 * @author danmo
 * @description 企微回调通知接口
 * @date 2020/11/6 17:31
 **/
@Slf4j
@RestController
@RequestMapping("/wecom/callback")
public class WeCallBackController extends CommonController {
    @Autowired
    WeEventHandle weEventHandle;


    @Autowired
    IWeCorpAccountService iWeCorpAccountService;


    @Autowired
    SysLoginService sysLoginService;



    @PostMapping(value = "/recive")
    public String recivePost(@RequestBody String msg, @RequestParam(name = "msg_signature") String signature,
                         String timestamp, String nonce,String corpId) {
        if(StrUtil.isEmpty(corpId)){
            return "error";
        }

        WeCorpAccount weCorpAccount = iWeCorpAccountService.getOne(new LambdaQueryWrapper<WeCorpAccount>()
                .eq(WeCorpAccount::getCorpId, corpId)
                .eq(WeCorpAccount::getStatus, Constants.NORMAL_CODE)
                .eq(WeCorpAccount::getDelFlag, Constants.NORMAL_CODE));

        if(null != weCorpAccount){
//            //校验当前租户账号是否授权登录了,如果未登录,则无密钥登录
//            LoginUser loginUser
//                    = SecurityUtils.getLoginUser();
//            if(null == loginUser){
//                sysLoginService.noPwdLogin(weCorpAccount.getCorpAccount());
//            }

            WxCryptUtil wxCryptUtil = new WxCryptUtil(weCorpAccount.getToken(), weCorpAccount.getEncodingAesKey(), weCorpAccount.getCorpId());

            try {
                String decrypt = wxCryptUtil.decrypt(signature, timestamp, nonce, msg);

                WxCpXmlMessageVO wxCpXmlMessage = StrXmlToBean(decrypt);
                log.info("企微回调通知接口 wxCpXmlMessage:{}", JSONObject.toJSONString(wxCpXmlMessage));
                try {
                    WeCallBackEventFactory factory = weEventHandle.factory(wxCpXmlMessage.getEvent());
                    if (factory !=null){
                        Threads.SINGLE_THREAD_POOL.submit(() -> factory.eventHandle(wxCpXmlMessage));
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return decrypt;
            } catch (Exception e) {
                e.printStackTrace();;
                String sRespData = WxCryptUtil.getTextRespData("success");
                return wxCryptUtil.encrypt(sRespData);
            }
        }

        return "error";
    }


    @GetMapping(value = "/recive")
    public String reciveGet(String msg_signature,String timestamp,String nonce,String echostr, String corpId) {

        if(StrUtil.isEmpty(corpId)){
            return "error";
        }

        WeCorpAccount weCorpAccount = iWeCorpAccountService.getOne(new LambdaQueryWrapper<WeCorpAccount>()
                .eq(WeCorpAccount::getCorpId, corpId)
                .eq(WeCorpAccount::getStatus, Constants.NORMAL_CODE)
                .eq(WeCorpAccount::getDelFlag, Constants.NORMAL_CODE));
        if(null != weCorpAccount){
            WxCryptUtil wxCryptUtil = new WxCryptUtil(weCorpAccount.getToken(), weCorpAccount.getEncodingAesKey(), weCorpAccount.getCorpId());

            try {
                return wxCryptUtil.verifyURL(msg_signature, timestamp, nonce, echostr);
            } catch (Exception e) {
                return "error";
            }
        }
        return "error";
    }

    private WxCpXmlMessageVO StrXmlToBean(String xmlStr){
        XStream xstream = XStreamInitializer.getInstance();
        xstream.addPermission(AnyTypePermission.ANY);
        xstream.processAnnotations(WxCpXmlMessage.class);
        xstream.processAnnotations(WxCpXmlMessageVO.class);
        xstream.processAnnotations(WxCpXmlMessageVO.ScanCodeInfo.class);
        xstream.processAnnotations(WxCpXmlMessageVO.SendPicsInfo.class);
        xstream.processAnnotations(WxCpXmlMessageVO.SendPicsInfo.Item.class);
        xstream.processAnnotations(WxCpXmlMessageVO.SendLocationInfo.class);
        xstream.processAnnotations(WxCpXmlMessageVO.BatchJob.class);
        WxCpXmlMessageVO wxCpXmlMessage = (WxCpXmlMessageVO)xstream.fromXML(xmlStr);
        return wxCpXmlMessage;
    }
}
