package com.playlet.web.service.impl;

import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.playlet.common.constant.PlayletConstants;
import com.playlet.common.utils.http.HttpUtils;
import com.playlet.web.core.config.WxConfig;
import com.playlet.web.service.WxService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.security.MessageDigest;
import java.util.Formatter;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

@Slf4j
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class WxServiceImpl implements WxService {

    private final WxConfig wxConfig;

    @Override
    public String getAccessToken() {
        String accessTokenResult = HttpUtils.sendGet("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=wx2b7d9259c1188067&secret=919165aae35838480986555f6c03ae6f");
        log.info("accessTokenResult : {} ", accessTokenResult);
        return JSONObject.parseObject(accessTokenResult).getString("access_token");
    }

    private String getAccessToken(String appid, String secret) {
        String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appid + "&secret=" + secret;
        log.info("调用微信获取access_token,入参url:{}", url);
        String result = HttpUtils.sendGet(url);
        log.info("调用微信获取access_token,响应内容:{}", result);
        JSONObject json = JSONObject.parseObject(result);
        if(json.containsKey(PlayletConstants.ACCESS_TOKEN)){
            return json.getString(PlayletConstants.ACCESS_TOKEN);
        }
        return null;
    }

    private String getCompanyAccessToken() {
        String url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=ww5bfaf714b2e57900&corpsecret=0JvbBfgkvbsm_fYdFI6e18-qR1sXn9wuCepHYb19d6w";
        log.info("调用微信获取access_token,入参url:{}", url);
        String result = HttpUtils.sendGet(url);
        log.info("调用微信获取access_token,响应内容:{}", result);
        JSONObject json = JSONObject.parseObject(result);
        if(json.containsKey(PlayletConstants.ACCESS_TOKEN)){
            return json.getString(PlayletConstants.ACCESS_TOKEN);
        }
        return null;
    }

    @Override
    public String getOpenidByCode(String code) {
        String url = "https://api.weixin.qq.com/sns/jscode2session?appid="+ wxConfig.getAppId() + "&secret=" + wxConfig.getSecret() + "&js_code=" + code + "&grant_type=authorization_code";
        log.info("调用微信获取openId,入参url:{}", url);
        String result = HttpUtils.sendGet(url);
        log.info("调用微信获取openId,响应内容:{}", result);
        JSONObject json = JSONObject.parseObject(result);
        if(json.containsKey(PlayletConstants.OPEN_ID)){
            return json.getString(PlayletConstants.OPEN_ID);
        }
        return null;
    }

    @Override
    public String getCompanyOpenidByCode(String code) {
        String accessToken = this.getCompanyAccessToken();
        String url = "https://qyapi.weixin.qq.com/cgi-bin/auth/getuserinfo?access_token=" + accessToken + "&code=" + code;
        log.info("调用微信获取openId,入参url:{}", url);
        String result = HttpUtils.sendGet(url);
        log.info("调用微信获取openId,响应内容:{}", result);
        JSONObject json = JSONObject.parseObject(result);
        if(json.containsKey("errcode") && "0".equals(json.getString("errcode"))){
            return result;
        }
        return null;
    }

    @Override
    public String getCompanyByUserId(String userTicket) {
        String accessToken = this.getCompanyAccessToken();
        String url = "https://qyapi.weixin.qq.com/cgi-bin/auth/getuserdetail?access_token=" + accessToken;
        Map<String, String> headerMap = new HashMap<>();
        headerMap.put("Content-Type", "application/json");
        JSONObject body = new JSONObject();
        body.put("user_ticket", userTicket);
        log.info("调用企业微信获取敏感信息,入参url:{}, 请求内容:{}", url, body);
        HttpResponse result = HttpUtil.createPost(url).addHeaders(headerMap).body(JSONObject.toJSONString(body)).execute();
        log.info("调用微信获取openId,响应内容:{}", result);
        return result.body();
    }

    @Override
    public Boolean checkKeepStatusByOpenId(String openId, String appId, String secret) {
        String accessToken = this.getAccessToken(appId, secret);
        String url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=" + accessToken + "&openid=" + openId + "&lang=zh_CN";
        log.info("调用微信获取用户信息,校验是否关注微信公众号,入参url:{}", url);
        String result = HttpUtils.sendGet(url);
        log.info("调用微信获取用户信息,校验是否关注微信公众号,响应内容:{}", result);
        JSONObject json = JSONObject.parseObject(result);
        if(json.containsKey(PlayletConstants.SUBSCRIBE)){
            return "1".equals(json.getString(PlayletConstants.SUBSCRIBE));
        }
        return false;
    }

    @Override
    public String getOpenidByCode(String code, String appId, String secret) {
        String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid="+ appId + "&secret=" + secret + "&code=" + code + "&grant_type=authorization_code";
        log.info("调用微信获取openId,入参url:{}", url);
        String result = HttpUtils.sendGet(url);
        log.info("调用微信获取openId,响应内容:{}", result);
        return result;
    }

    @Override
    public String getWxInfo(String openId, String accessToken) {
        String url = "https://api.weixin.qq.com/sns/userinfo?access_token=" + accessToken + "&openid=" + openId + "&lang=zh_CN";
        log.info("调用微信获取用户信息,入参url:{}", url);
        String result = HttpUtils.sendGet(url);
        log.info("调用微信获取用户信息,响应内容:{}", result);
        return result;
    }

    @Override
    public Map<String, String> getWxTicket(String requestUrl) {
        String accessTokenResult = HttpUtils.sendGet("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=wx2b7d9259c1188067&secret=919165aae35838480986555f6c03ae6f");
        log.info("accessTokenResult : {} ", accessTokenResult);
        String accessToken = JSONObject.parseObject(accessTokenResult).getString("access_token");
        String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + accessToken + "&type=jsapi";
        log.info("调用微信获取Ticket,入参url:{}", url);
        String result = HttpUtils.sendGet(url);
        log.info("调用微信获取Ticket,响应内容:{}", result);
        String ticket = JSONObject.parseObject(result).getString("ticket");
        //生成11位时间戳
        long time11 = System.currentTimeMillis() / 1000;
        String timestamp = String.valueOf(time11);
        //生成16位随机字符串
        String nonce = create16String();
        String string1 = "jsapi_ticket=" + ticket + "&noncestr=" + nonce + "&timestamp=" + timestamp + "&url=" + requestUrl;
        // 2.1这里利用了hutool的加密工具类
        log.info("使用sha1加密前的细信息：===>【{}】", string1);
        String signature = "";
        try {
            MessageDigest crypt = MessageDigest.getInstance("SHA-1");
            crypt.reset();
            crypt.update(string1.getBytes("UTF-8"));
            signature = encryptSha1(crypt.digest());
        } catch (Exception e) {
            log.info(e.getMessage());
        }
        Map<String,String> resultMap = new HashMap();
        resultMap.put("signature", signature);
        resultMap.put("timestamp", timestamp);
        resultMap.put("nonce", nonce);
        resultMap.put("url", url);
        resultMap.put("ticket", ticket);
        return resultMap;
    }


    /***
     * 生成微信sha1方法签名
     **/
    public static String encryptSha1(final byte[] hash) {
        Formatter formatter = new Formatter();
        for (byte b : hash) {
            formatter.format("%02x", b);
        }
        String result = formatter.toString();
        formatter.close();
        return result;
    }


    /***
     * 生成16位随机大小写加数字的字符串
     **/
    public static String create16String(){
        String a = "ZXCVBNMASDFGHJKLQWERTYUIOPzxcvbnmasdfghjklqwertyuiop0123456789";
        StringBuilder con = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < 16; i++) {
            con.append(a.charAt(random.nextInt(62)));
        }
        return con.toString();
    }
}
