package com.ruoyi.web.controller.wx;

import com.google.gson.Gson;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginBody;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.wxMessage.WxMpPropertiesConfig;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.StringUtils;

import com.ruoyi.framework.web.service.SysLoginService;
import com.ruoyi.system.service.WxMsgService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.boot.configurationprocessor.json.JSONObject;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.*;

import static com.ruoyi.common.constant.Constants.OPENID;
import static com.ruoyi.common.constant.Constants.TOKEN;
import static com.ruoyi.common.constant.UserConstants.PWD;

/**
 * @author xh
 * @Date 2022/7/14
 */
//@RestController
@Slf4j
@RestController
@RequestMapping("/wx")
public class WxMsgController {

    /**
     * 获取微信配置信息
     */
    @Autowired
    private WxMsgService wxMsgService;

    @Autowired
    private SysLoginService loginService;



    /**
     * 测试接收微信官方通知
     *
     * @param request
     * @return
     */
    @GetMapping(value = "/weChatToken", produces = {"application/json;charset=utf-8"})
    @ResponseBody
    public String notify(HttpServletRequest request) {
        String token = "heart";
        // 判断是否是Get请求
        boolean isGet = request.getMethod().toLowerCase().equals("get");
        if (isGet) {
            // 微信加密签名
            String signature = request.getParameter("signature");
            // 时间戳
            String timestamp = request.getParameter("timestamp");
            // 随机数
            String nonce = request.getParameter("nonce");
            log.info("signature:{}, timestamp:{}, nonce:{}", signature, timestamp, nonce);
            // 随机字符串
            String echostr = request.getParameter("echostr");


            // 1）将token、timestamp、nonce三个参数进行字典序排序
            List<String> list = Arrays.asList(token, timestamp, nonce);
            Collections.sort(list);
            // 2）将三个参数字符串拼接成一个字符串进行sha1加密
            StringBuilder stringBuilder = new StringBuilder();
            for (String s : list){
                stringBuilder.append(s);
            }

            try {
                // 通过检验signature对请求进行校验，若校验成功则原样返回echostr，表示接入成功，否则接入失败
                MessageDigest instance =
                        MessageDigest.getInstance("sha1");
                //使⽤sha1进⾏加密，获得byte数组
                byte[] digest =
                        instance.digest(stringBuilder.toString().getBytes());
                StringBuilder sum = new StringBuilder();
                for (byte b : digest) {
                    sum.append(Integer.toHexString((b >> 4) & 15));
                    sum.append(Integer.toHexString(b & 15));
                }
                // 3）开发者获得加密后的字符串可与 signature 对⽐，标识该请求来源于微信
                if (!StringUtils.isEmpty(signature) &&
                        signature.equals(sum.toString())) {
                    return echostr;
                }

            } catch (Exception e) {
                log.info("测试微信公众号的接口配置信息发生异常：", e);
                return "系统异常！";
            }
        } else {
            return "非法请求！疑似黑客攻击，列入黑名单";
        }
        return null;
    }

    /**
     * 获取access_token，access_token是公众号的全局唯一接口调用凭据
     */
    @GetMapping("/get_wx_token")
    @ResponseBody
    public Map<String, Long> getWxToken() {
        RestTemplate restTemplate = new RestTemplate();
        Map<String, String> map = new HashMap<>();
        map.put("AppId", WxMpPropertiesConfig.getAppId());
        map.put("AppSecret", WxMpPropertiesConfig.getSecret());
        // 调用微信公众号接口
        ResponseEntity<String> forEntity = restTemplate.getForEntity("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={AppId}&secret={AppSecret}", String.class, map);
        // 解析JSON
        String body = forEntity.getBody();
        log.info("发送token获得到的body：{}", body);
        Gson gson = new Gson();
        HashMap<String, Object> jsonObject = gson.fromJson(body, HashMap.class);
        String accessToken = String.valueOf(jsonObject.get("access_token"));
        Double expiresIn = Double.parseDouble(String.valueOf(jsonObject.get("expires_in")));//时效--7200s
        return new HashMap<String, Long>() {{put(accessToken, expiresIn.longValue());}};
    }



    /**
     * 获取微信用户code，并重定向获取用户openId
     *
     * @return
     */
    @GetMapping("/getOpenIdUrl")
    @ResponseBody
    public AjaxResult getOpenIdUrl() {
        String url = WxMpPropertiesConfig.getUrl();
        String backUrl = url + "/api/getUserOpenId";
        String getOpenIdUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=" + backUrl + "&response_type=code&scope=snsapi_userinfo&state=1,0#wechat_redirect";
        getOpenIdUrl = getOpenIdUrl.replace("APPID", WxMpPropertiesConfig.getAppId());
        return AjaxResult.success(getOpenIdUrl);
    }

    @GetMapping("/wxlogin")
    public String wxlogin(){
        String url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + WxMpPropertiesConfig.getAppId() +
                "&redirect_uri=" + WxMpPropertiesConfig.getUrl()+ "/api/getUserOpenId" +
                "&response_type=code" +
                "&scope=snsapi_userinfo" +
                "&state=STATE#wechat_redirect";
        return "redirect:"+url;
    }

    /**
     * 根据用户openId创建账号
     *
     * @return
     * @throws IOException
     */
    @GetMapping(value = "/getUserOpenId")
    public AjaxResult getUserOpenId(String code){
        SysUser user = wxMsgService.creatUser(code);
        // 生成令牌
        AjaxResult ajax = AjaxResult.success();
        String token = "";
        if (!StringUtils.isEmpty(user.getUserName())) {
            token = loginService.login(user.getUserName(), PWD, "",
                    "");
        }

        ajax.put(TOKEN, token);
        ajax.put(OPENID, user.getOpenId());
        ajax.put(TOKEN, token);
        return ajax;
    }

    /**
     * 根据用户openId创建账号
     *
     * @return
     * @throws IOException
     */
    @GetMapping(value = "/gzhLogin")
    public AjaxResult gzhLogin(String openId, String phone){
        SysUser user = wxMsgService.gzhLogin(openId,phone);
        // 生成令牌
        AjaxResult ajax = AjaxResult.success();
        String token = loginService.login(user.getUserName(), PWD, "",
                "");
        ajax.put(TOKEN, token);
        ajax.put(OPENID, user.getOpenId());
        return ajax;
    }
}