package com.jeeplus.weChat.util;

import com.alibaba.fastjson.JSONObject;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.jeeplus.weChat.config.WechatAccountConfig;
import com.jeeplus.weChat.domain.SignatureInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.flowable.ui.common.service.exception.BadRequestException;
import java.security.MessageDigest;

import java.util.UUID;
import java.util.Formatter;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Timer;

/**
 * @author 王强
 * @version 1.0
 * @date 2024-07-22 9:26
 */
@Slf4j
public class HttpUtils {

    // 获取jsapi_ticket的URL
    private static final String TICKET_URL = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";

    public static String access_token;
    public static String requestPost(String url,String jsonParam){

        System.out.println(jsonParam);

        // 获取连接客户端工具
        CloseableHttpClient httpClient = HttpClients.createDefault();

        String entityStr = null;
        CloseableHttpResponse response = null;

        try {
            // 创建POST请求对象s
            HttpPost httpPost = new HttpPost(url);
            if (!"".equals(jsonParam)){
                // 创建请求参数
                StringEntity s = new StringEntity(jsonParam, "utf-8");
                //设置参数到请求对象中
                httpPost.setEntity(s);
            }
            //添加请求头信息
            httpPost.addHeader("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)");
            httpPost.addHeader("Content-Type", "application/json");
            // 执行请求
            response = httpClient.execute(httpPost);
            // 获得响应
            HttpEntity entity = response.getEntity();
            // 将响应结果转换成字符串
            entityStr = EntityUtils.toString(entity, "UTF-8");

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 释放连接
            if (null != response) {
                try {
                    response.close();
                    httpClient.close();
                } catch (IOException e) {
                    log.info("释放连接出错");
                    e.printStackTrace();
                }
            }
        }

        // 打印响应内容
        System.out.println(entityStr);
        return entityStr;
    }

    public static void getAccessToken(){
        Timer timer=new Timer();
        timer.schedule(new java.util.TimerTask() {
            @Override
            public void run() {
                dogetToken();
            }
        },3000,60*100*1000);    // 三秒后执行，一百分钟执行一次
    }

    //请求access_token的方法
    public static String dogetToken() {
        String url = WechatAccountConfig.accesstokenURL;
        //将配置文件中的appid和appsecret值填到url中
        String realURL = url.replaceAll("APPID", WechatAccountConfig.appID).replaceAll("APPSECRET",WechatAccountConfig.appsecret);
        System.out.println(realURL);
        //调用获得access_token的接口
        String result = requestPost(realURL, "");
        System.out.println(result);

        JSONObject obj = JSONObject.parseObject(result);
        Map<String, Object> map = obj;
        try {
            //从结果中取出access_token
            String access_token = map.get("access_token").toString();
            HttpUtils.access_token = access_token;  //把得到的token存在静态变量中
            return access_token;
        } catch (Exception e) {
            //如果返回的结果中有errcode和errmsg，说明接口调用失败
            String errcode = map.get("errcode").toString();
            String errmsg = map.get("errmsg").toString();
            // 记录错误日志并返回null或空字符串
            System.err.println("微信公众平台获得access_token失败，错误码为：" + errcode + " 错误信息为：" + errmsg);
            return null; // 或 return ""; 根据你后续逻辑需要选择
        }
    }

    // 获取jsapi_ticket
    public static String dogetJsapiTicket(String accessToken) {
        String result = null;
        try (CloseableHttpClient client = HttpClients.createDefault()) {
            String url = TICKET_URL.replace("ACCESS_TOKEN", accessToken);
            HttpGet httpGet = new HttpGet(url);
            HttpResponse response = client.execute(httpGet);
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                String responseStr = EntityUtils.toString(entity, "UTF-8");
                // 解析出jsapi_ticket
                Map<String, Object> responseMap = parseJson(responseStr);
                result = (String) responseMap.get("ticket");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    // 生成签名
    public static String generateSignature(String jsapiTicket, String nonceStr, String timestamp, String url) {
        String signature = "";
        String string1;
        try {
            string1 = "jsapi_ticket=" + jsapiTicket +
                    "&noncestr=" + nonceStr +
                    "&timestamp=" + timestamp +
                    "&url=" + url;

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

    public static SignatureInfo dogetSignature(String url) {
        String accessToken = dogetToken();
        String jsapiTicket = dogetJsapiTicket(accessToken);

        String nonceStr = UUID.randomUUID().toString(); // 生成随机字符串
        String timestamp = Long.toString(System.currentTimeMillis() / 1000); // 生成时间戳
//        url = "http://xrd3cp.natappfree.cc/h5/"; // 调用接口的页面URL

        String signature = generateSignature(jsapiTicket, nonceStr, timestamp, url);

        SignatureInfo signatureInfo = new SignatureInfo();
        signatureInfo.setNonceStr(nonceStr);
        signatureInfo.setTimestamp(timestamp);
        signatureInfo.setSignature(signature);
        // 如果需要将这些参数返回给前端，可以将它们封装成对象或JSON
        System.out.println("nonceStr: " + nonceStr);
        System.out.println("timestamp: " + timestamp);
        System.out.println("signature: " + signature);

        return signatureInfo; // 返回生成的签名
    }

    // 解析JSON字符串为Map
    private static Map<String, Object> parseJson(String jsonStr) {
        // 这里你可以使用任何一种JSON解析库，如Gson、Jackson等
        Map<String, Object> map = new HashMap<>();
        // ... 实现解析逻辑
        JsonObject jsonObject = JsonParser.parseString(jsonStr).getAsJsonObject();
        if (jsonObject.has("ticket")) {
            map.put("ticket", jsonObject.get("ticket").getAsString());
        }
        return map;
    }

    // 字节转为16进制
    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;
    }
}

