package com.ruoyi.system.domain.task.utils;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONException;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.zqt.ZQTHttpHelper;
import org.apache.commons.lang3.StringUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.stereotype.Component;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.AlgorithmParameters;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.Security;
import java.util.*;
import com.ruoyi.system.domain.task.utils.HttpClient2Util.ZqtongResult;

@Component
public class WxUtil {

    private static AccessToken myAccessToken;

    /**
     * 获取用户授权 得到openId和sessionKey
     *
     * @param code
     * @param appId
     * @param appSecret
     * @return
     */
    public static JSONObject getOpenIdAndSessionKey(String code, String appId, String appSecret) {
        if (StringUtils.isBlank(code)) {
            throw new ServiceException("微信code不能为空");
        }
        String tokenUrl = "https://api.weixin.qq.com/sns/jscode2session?grant_type=authorization_code";
        tokenUrl = tokenUrl + "&appid=" + appId + "&secret=" + appSecret + "&js_code=" + code;
        try {
            ZqtongResult result = HttpClient2Util.doGet(tokenUrl, null);
            if (result == null || 200 != result.getStatus()) {
                throw new ServiceException("请求失败,请求状态码不为200:" + result.getStatus());
            }
            JSONObject jsonObject = JSON.parseObject(result.getData().toString());
            if (jsonObject.getString("errcode") == null) {
                return jsonObject;
            } else {
                throw new ServiceException(result.getData().toString());
            }
        } catch (JSONException e2) {
            e2.printStackTrace();
        }
        return null;
    }

    /**
     * 调用吴继明唯一类型token获取
     */
    public static String getAccessTokenOther(String appId, String appSecret) {
        try {
            String url = "https://api-tokenrefresh.app.zqtong.com/api/newFreeLogin/weixin/oauth";
            Map<String, Object> params = new HashMap<>();
            params.put("appId", appId);
            params.put("appSecret", appSecret);
            ZqtongResult result = HttpClient2Util.doPost(url, JSON.toJSONString(params), null);
            if (result == null || 200 != result.getStatus()) {
                throw new ServiceException("请求失败,请求状态码不为200:" + result.getStatus());
            }
            JSONObject jsonObject = JSON.parseObject(result.getData().toString()).getJSONObject("data");
            return jsonObject.getString("accessToken");
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取accessToken
     *
     * @param appId
     * @param appSecret
     * @return
     */
    public static String getAccessToken(String appId, String appSecret) {
        try {
            // 这里为了保险设置成7000秒过期，而不是7200秒
            if (myAccessToken != null && StringUtils.isNotBlank(myAccessToken.getAccessToken()) && ((new Date().getTime() - myAccessToken.getDate().getTime()) / 1000) <= 7000) {
                System.out.println(myAccessToken.getDate());
                return myAccessToken.getAccessToken();
            } else {
                // accessToken过期,重新申请
                String tokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential";
                tokenUrl = tokenUrl + "&appid=" + appId + "&secret=" + appSecret;
                ZqtongResult result = HttpClient2Util.doGet(tokenUrl, null);
                if (result == null || 200 != result.getStatus()) {
                    throw new ServiceException("请求失败,请求状态码不为200:" + result.getStatus());
                }
                JSONObject jsonObject = JSON.parseObject(result.getData().toString());
                if (jsonObject.containsKey("access_token")) {
                    AccessToken accessToken = new AccessToken();
                    accessToken.setAccessToken(jsonObject.getString("access_token"));
                    accessToken.setDate(new Date());
                    myAccessToken = accessToken;
                    return myAccessToken.getAccessToken();
                } else {
                    throw new ServiceException(result.getData().toString());
                }
            }
        } catch (JSONException e2) {
            e2.printStackTrace();
        }
        return null;
    }

    /**
     * 获取用户手机号
     *
     * @param appId
     * @param appSecret
     * @return
     */
    public static String getPhoneNumber(String code, String appId, String appSecret) {
        try {
            String tokenUrl = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" + getAccessTokenOther(appId, appSecret);
            Map<String, Object> params = new HashMap<>();
            params.put("code", code);
            ZqtongResult result = HttpClient2Util.doPost(tokenUrl, JSON.toJSONString(params), null);
            if (result == null || 200 != result.getStatus()) {
                throw new ServiceException("请求失败,请求状态码不为200:" + result.getStatus());
            }
            JSONObject jsonObject = JSON.parseObject(result.getData().toString());
            if (jsonObject.containsKey("phone_info")) {
                JSONObject phoneInfo = jsonObject.getJSONObject("phone_info");
                String phone = phoneInfo.getString("purePhoneNumber");
                return phone;
            } else {
                throw new ServiceException(result.getData().toString());
            }
        } catch (JSONException e2) {
            e2.printStackTrace();
        }
        return null;
    }

    /**
     * 解密数据
     *
     * @param encryptedData
     * @param sessionKey
     * @param iv
     * @return
     */
    public static JSONObject getUserInfo(String encryptedData, String sessionKey, String iv) {
        // 被加密的数据
        byte[] dataByte = Base64.getDecoder().decode(encryptedData);
        // 加密秘钥
        byte[] keyByte = Base64.getDecoder().decode(sessionKey);
        // 偏移量
        byte[] ivByte = Base64.getDecoder().decode(iv);

        try {
            // 如果密钥不足16位，那么就补足.  这个if 中的内容很重要
            int base = 16;
            if (keyByte.length % base != 0) {
                int groups = keyByte.length / base + (keyByte.length % base != 0 ? 1 : 0);
                byte[] temp = new byte[groups * base];
                Arrays.fill(temp, (byte) 0);
                System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
                keyByte = temp;
            }
            // 初始化
            Security.addProvider(new BouncyCastleProvider());
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
            SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
            AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
            parameters.init(new IvParameterSpec(ivByte));
            cipher.init(Cipher.DECRYPT_MODE, spec, parameters);// 初始化
            byte[] resultByte = cipher.doFinal(dataByte);
            if (null != resultByte && resultByte.length > 0) {
                String result = new String(resultByte, "UTF-8");
                return JSONObject.parseObject(result);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 小程序码获取,返回base64
     *
     * @param appId
     * @param appSecret
     * @return
     */
    public static String getUnlimited(String scene, String page, String appId, String appSecret, String env_version) {
        try {
            String tokenUrl = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=" + getAccessTokenOther(appId, appSecret);
            Map<String, Object> params = new HashMap<>();
            // 业务参数
            params.put("scene", scene);
            // 默认跳主页面
            if (StringUtils.isNotBlank(page)) {
                params.put("page", page);
            }
            // 检查 page 是否存在，为 true 时 page 必须是已经发布的小程序存在的页面
            params.put("check_path", false);
            // 正式版为 release，体验版为 trial，开发版为 develop
            params.put("env_version", env_version);
            ZqtongResult result = HttpClient2Util.doPost(tokenUrl, JSON.toJSONString(params), null);
            if (result == null || 200 != result.getStatus()) {
                throw new ServiceException("请求失败,请求状态码不为200:" + result.getStatus());
            }
            byte[] data = (byte[])result.getData();
//            ByteArrayOutputStream byam = new ByteArrayOutputStream();
//            ObjectOutputStream oos = new ObjectOutputStream(byam);
//            oos.writeObject(result.getData());
//            byte[] data = byam.toByteArray();
            return "data:image/jpeg;base64," + Base64.getEncoder().encodeToString(data);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    public static String getCommonAccessToken(String wxAppid, String wxSecret) {
        String url = "https://api.weixin.qq.com/cgi-bin/token?appid=" + wxAppid + "&secret=" + wxSecret + "&grant_type=client_credential";
        String s = null;
        try {
            s = ZQTHttpHelper.doGet(url);
            JSONObject jsonObject = JSONObject.parseObject(s);
            return (String) jsonObject.get("access_token");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String getJsTicket(String accessToken) {
        String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + accessToken + "&type=jsapi";
        String s = null;
        try {
            s = ZQTHttpHelper.doGet(url);
            JSONObject jsonObject = JSONObject.parseObject(s);
            return (String) jsonObject.get("ticket");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static Map<String, String> sign(String jsapi_ticket, String url) {
        Map<String, String> ret = new HashMap<String, String>();
        String nonce_str = create_nonce_str();
        String timestamp = create_timestamp();
        String string1;
        String signature = "";

        //注意这里参数名必须全部小写，且必须有序
        string1 = "jsapi_ticket=" + jsapi_ticket +
                "&noncestr=" + nonce_str +
                "&timestamp=" + timestamp +
                "&url=" + url;
        System.out.println(string1);

        try {
            MessageDigest crypt = MessageDigest.getInstance("SHA-1");
            crypt.reset();
            crypt.update(string1.getBytes("UTF-8"));
            signature = byteToHex(crypt.digest());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        ret.put("url", url);
        ret.put("jsapi_ticket", jsapi_ticket);
        ret.put("nonceStr", nonce_str);
        ret.put("timestamp", timestamp);
        ret.put("signature", signature);

        return ret;
    }

    private static String byteToHex(final byte[] hash) {
        Formatter formatter = new Formatter();
        for (byte b : hash) {
            formatter.format("%02x", b);
        }
        String result = formatter.toString();
        formatter.close();
        return result;
    }

    private static String create_nonce_str() {
        return UUID.randomUUID().toString();
    }

    private static String create_timestamp() {
        return Long.toString(System.currentTimeMillis() / 1000);
    }


    public static void main(String[] args) {

        //getAccessTokenOther("wx0ba181c43468fc52", "c7b672d9197323b7762c591c468a6c46");

    }


}
