package com.ruoyi.hezhi.api.kaoshi;

import com.alibaba.fastjson2.JSONObject;
import com.kuaidi100.sdk.response.SubscribeResp;
import com.kuaidi100.sdk.utils.SignUtils;
import com.ruoyi.common.annotation.RepeatSubmit;
import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.kd100.Kd100Util;
import com.ruoyi.common.weixin.message.MessageUtil;
import com.ruoyi.common.weixin.utils.WeiXinGzhUtils;
import com.ruoyi.hezhi.domain.TbExamRegistration;
import com.ruoyi.hezhi.mapper.TbExamRegistrationMapper;
import io.swagger.annotations.Api;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 微信相关接口
 */
@Api("微信")
@RestController
@RequestMapping("/api/weiXin")
public class ApiWeiXinController {

    protected final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Resource
    private WeiXinGzhUtils weiXinGzhUtils;

    @Resource
    private RedisCache redisCache;

    @Resource
    private Kd100Util kd100Util;

    @Resource
    private TbExamRegistrationMapper tbExamRegistrationMapper;

    /**
     * 获取微信授权登录二维码
     * @return 结果
     */
    @RepeatSubmit
    @GetMapping("/getWeiXinQrCode")
    public AjaxResult getWeiXinQrCode(){
        JSONObject qrCodeByTicket = weiXinGzhUtils.getQrCodeByTicket();
        System.out.println(qrCodeByTicket);
        return AjaxResult.success(qrCodeByTicket);
    }

    /**
     * 接受微信通知
     * @param request 请求
     * @return 结果
     * @throws Exception
     */
    @RequestMapping(value = "/notifyMsg")
    @ResponseBody
    public String checkSign (HttpServletRequest request, HttpServletResponse response){
        // 设置编码格式
        response.setCharacterEncoding("utf-8");
        // 检验消息是否从微信服务器发出
        // 签名
        String signature = request.getParameter("signature");
        // 时间戳
        String timestamp = request.getParameter("timestamp");
        // 随机数
        String nonce = request.getParameter("nonce");
        // 随机字符串
        String echostr = request.getParameter("echostr");
        // 加密类型
        String encryptType = request.getParameter("encrypt_type");
        if (StringUtils.isBlank(echostr)){
            echostr = "SUCCESS";
        }

        logger.info("开始校验此次消息是否来自微信服务器，param-> \nsignature:{},\ntimestamp:{},\nnonce:{},\nechostr:{}",
                signature, timestamp, nonce, echostr);
        if (weiXinGzhUtils.checkSignature(signature, timestamp, nonce)) {
            String result = "";
            try {
                InputStream inStream = request.getInputStream();
                ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
                byte[] buffer = new byte[1024];
                int len = 0;
                while ((len = inStream.read(buffer)) != -1) {
                    outSteam.write(buffer, 0, len);
                }
                outSteam.close();
                inStream.close();
                result = outSteam.toString("UTF-8");
                logger.info("callBackMap 接收微信参数 原文 -> {}", result);
                // 获取的回调消息
                if (StringUtils.isNotBlank(result)){

                    Map<String, String> callBackMap = weiXinGzhUtils.xmlToMap(result);
                    // 开发者微信号
                    String toUserName = callBackMap.get("ToUserName");
                    // 发送方账号(一个OpenID)
                    String fromUserName = callBackMap.get("FromUserName");
                    // 接收消息类型: 普通消息(text)、事件推送
                    String msgType = callBackMap.get("MsgType");
                    logger.info("callBackMap 接收微信参数 转换 -> {}，开发者账号 ToUserName -> {}，发送方账号 FromUserName -> {}，接收消息类型 MsgType -> {}", callBackMap, toUserName, fromUserName, msgType);

                    // 公众号回复的消息
                    String message =null;
                    if (StringUtils.isNotBlank(fromUserName)){
                        if ("event".equals(msgType)){
                            // uuid
                            String eventKey = callBackMap.get("EventKey");
                            // 事件类型
                            String event = callBackMap.get("Event");

                            String uuid = "";

                            if ("SCAN".equals(event)){
                                uuid = eventKey;
                                logger.info("接收到事件 扫码 FromUserName -> {}", fromUserName);
                            }
                            if ("subscribe".equals(event)){
                                if (StringUtils.isNotBlank(eventKey) && eventKey.startsWith("qrscene")){
                                    logger.info("接收到事件 扫码关注 FromUserName -> {}", fromUserName);
                                    String[] split = eventKey.split("_");
                                    uuid = split[1];
                                }
                            }

                            if (StringUtils.isNotBlank(uuid)){

                                // 设置uuid缓存
                                String redisKey = CacheConstants.CODE_LOGIN_TOKEN_KEY + uuid;
                                if (!redisCache.hasKey(redisKey)){
                                    redisCache.setCacheObject(redisKey, fromUserName, 300, TimeUnit.SECONDS);
                                }

                                //回复文本内容
                                message = MessageUtil.replyContent(fromUserName, toUserName, "你好");

                                if (StringUtils.isNotBlank(message)){
                                    return message;
                                }

                            }
                        }
                    }
                }
            }catch (Exception e){
                e.printStackTrace();
                return "FAIL";
            }
            // 处理用户关注公众号
            return echostr;
        }else {
            logger.info("校验失败，param-> \nsignature:{},\ntimestamp:{},\nnonce:{},\nechostr:{}",
                    signature, timestamp, nonce, echostr);
            return "FAIL";
        }
    }

    /**
     * 接收快递100下单回调
     * @return 结果
     */
    @PostMapping("/kuaiDiCallBack")
    public SubscribeResp kuaiDiCallBack(HttpServletRequest request){

        String param = request.getParameter("param");
        String sign = request.getParameter("sign");
        //建议记录一下这个回调的内容，方便出问题后双方排查问题
        logger.debug("快递100订阅推送回调结果|{}|{}",param,sign);
        //订阅时传的salt,没有可以忽略
        String salt = System.currentTimeMillis() +kd100Util.getKey()+kd100Util.getSecret();
        String ourSign = SignUtils.sign(param + salt);
        SubscribeResp subscribeResp = new SubscribeResp();
        subscribeResp.setResult(Boolean.TRUE);
        subscribeResp.setReturnCode("200");
        subscribeResp.setMessage("成功");
        //加密如果相等，属于快递100推送；否则可以忽略掉当前请求
        if (ourSign.equals(sign)){
            //TODO 业务处理

            JSONObject result = JSONObject.parseObject(param);
            if ("200".equals(result.getString("status"))){

                String kuaidicom = result.getString("kuaidicom");//快递公司编号
                String kuaidinum = result.getString("kuaidinum");//快递单号
                JSONObject data = result.getJSONObject("data");
                String orderId = data.getString("orderId");
                Integer status = data.getInteger("status");

                TbExamRegistration tbExamRegistration = tbExamRegistrationMapper.getByShippingOrderId(orderId);
                if (ObjectUtils.isNotEmpty(tbExamRegistration)){

                    tbExamRegistration.setShippingStatus(status.toString());
                    tbExamRegistration.setShippingMark(kuaidicom);
                    tbExamRegistration.setShippingCode(kuaidinum);
                    if (status == 0){
                        tbExamRegistration.setCertificateStatus(2);
                        tbExamRegistration.setConsignAt(DateUtils.getTime());
                    }
                    if (status == 13){
                        tbExamRegistration.setCertificateStatus(3);
                    }
                    tbExamRegistrationMapper.updateTbExamRegistration(tbExamRegistration);
                }
            }

            return subscribeResp;
        }
        return null;
    }

}
