package com.jjt.nccloud.utils;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.google.gson.Gson;
import org.apache.commons.lang3.StringUtils;

import java.io.*;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

/**
 * NccloudUtils$
 *
 * @author wukai
 * @date 2024/12/29 21:36
 */
public class NccloudUtils {
    /**
     * appid
     */
    private static final String CLIENT_ID = "xfxt";
    /**
     * app私钥
     */
    private static final String CLIENT_SECRET = "b9ec6c1c1f454e8f8dfc";
    /**
     * 公钥
     */
    private static final String PUB_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgth5E9X8m4SMHBKEcPs8b8M7IClHdRcHwQHg2NiUgauZcHUOpCjZhT+NwAkQ/9tG5T6WiwS3CSTftueauNnQJ9lycZUYCunvlIutYpTRpLAygSNQUz2gOKriX0aj9r5tTOE9QHsH4C7lF5Sfokme8aPK7ddXIKTy0Q3l2ziDjcCJ+uLX4ysrz5qlYIFCKUqOVswZNSScbjknL1lD00j7unYDC5Km2URtPi1usrMTF8AsCWqeb/2BVSwC/cQL3GmMc2esarJ/7k4JPJYYywFMjISlyIIZ7BK/KijfZgHpgYk2hc1631/dmfa2H3IsLmG1i+PeIkvv7K0/CHHPlQRwcwIDAQAB";
    /**
     * ncc账户
     */
    private static final String BUSI_CENTER = "truelove";
    private static final String USER_CODE = "xfxt";
    /**
     * 服务器ip：port
     */
    private static final String BASE_URL = "http://192.168.33.52:8081";
    /**
     * 返回值压缩加密级别
     */
    private static final String SECRET_LEVEL = "L0";
    /**
     * openapi请求路径
     */
    private static final String API_URL = "/nccloud/api/so/saleorder/querybyscheme";

    private static String token = null;

    public static void main(String[] args) throws Exception {
        String requestBody = "{\"pk_org\":\"100101\",\"dbilldate\":\"2024-12-16 00:00:00~2024-12-17 00:00:00\"}";
        String jsonStr = getData(requestBody);
        JSONObject jsonObject = JSONUtil.parseObj(jsonStr);
        if (!jsonObject.getBool("success")) {
            return;
        }
        JSONArray jsonArray = jsonObject.getJSONArray("data");

        // 输出 JsonArray 内容
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject obj = jsonArray.getJSONObject(i);
            JSONObject order = obj.getJSONObject("so.so_saleorder");
            //客户号
            System.err.print("\t客户号:" + order.getByPath("ccustomerid.code", String.class));
            //客户名称
            System.err.print("\t客户名称:" + order.getByPath("ccustomerid.name", String.class));
            System.err.print("\t订单号：" + order.getByPath("vbillcode", String.class));
            System.err.println("\t制单时间：" + order.getByPath("dmakedate", String.class));

//
            JSONArray childOrder = obj.getJSONArray("so.so_saleorder_b");
            for (int j = 0; j < childOrder.size(); j++) {
                JSONObject co = childOrder.getJSONObject(j);
                System.err.print("\t计量单位：" + co.getByPath("castunitid.name", String.class));
                System.err.print("\t物料编码：" + co.getByPath("cmaterialvid.code", String.class));
                System.err.print("\t物料名称：" + co.getByPath("cmaterialvid.name", String.class));
                System.err.print("\t花色：" + co.getByPath("vfree1.name", String.class));
                System.err.print("\t主单位：" + co.getByPath("cunitid.name", String.class));
                System.err.print("\t含税单价：" + co.getByPath("nqttaxnetprice", BigDecimal.class));
                System.err.print("\t计税金额：" + co.getByPath("ntaxmny", BigDecimal.class));
                System.err.print("\t数量：" + co.getByPath("nastnum", Double.class));
                System.err.print("\t总重量：" + co.getByPath("nnum", Double.class));
                System.err.println();
            }
        }
    }

    /**
     * 获取access_token
     *
     * @return token
     * @throws Exception e
     */
    public static String getToken() throws Exception {
        // 客户端模式
        Map<String, String> paramMap = new HashMap<>();
        // 密码模式认证
        paramMap.put("grant_type", "client_credentials");
        // 第三方应用id
        paramMap.put("client_id", CLIENT_ID);
        // 第三方应用secret 公钥加密
        String secret_entryption = Encryption.pubEncrypt(PUB_KEY, CLIENT_SECRET);
//        System.out.println("secret_entryption：：" + secret_entryption);
        paramMap.put("client_secret", URLEncoder.encode(secret_entryption, "utf-8"));
        // 账套编码
        paramMap.put("biz_center", BUSI_CENTER);
//		paramMap.put("dsname", dsname);
        paramMap.put("usercode", USER_CODE);

        // 签名
        String sign = SHA256Util.getSHA256(CLIENT_ID + CLIENT_SECRET + PUB_KEY, PUB_KEY);
        paramMap.put("signature", sign);
//        System.out.println("##gettoken sign::" + sign);

        String url = BASE_URL + "/nccloud/opm/accesstoken";
        String mediaType = "application/x-www-form-urlencoded";
        return doPost(url, paramMap, mediaType, null, "");
    }

    /**
     * 请求openapi
     *
     * @throws Exception 异常
     */
    public static String getData(String requestBody) throws Exception {
        if (token == null) {
            token = getToken();
        }
        // token转对象，获取api访问所用token和secret
        ResultMessageUtil returnData = new Gson().fromJson(token, ResultMessageUtil.class);
        Map<String, Object> data = (Map<String, Object>) returnData.getData();
        String access_token = (String) data.get("access_token");
        String security_key = (String) data.get("security_key");
        String refresh_token = (String) data.get("refresh_token");
        long expire_in = new Double((double) data.get("expires_in")).longValue();
        long ts = new Double((double) data.get("ts")).longValue();
        if (ts + expire_in < System.currentTimeMillis()) {
            token = getToken();
            returnData = new Gson().fromJson(token, ResultMessageUtil.class);
            data = (Map<String, Object>) returnData.getData();
            access_token = (String) data.get("access_token");
            security_key = (String) data.get("security_key");
            refresh_token = (String) data.get("refresh_token");
        }
//        System.out.println("【ACCESS_TOKEN】:" + access_token);

        // 请求路径
        String url = BASE_URL + API_URL;
        // header 参数
        Map<String, String> headerMap = new HashMap<>();
        headerMap.put("access_token", access_token);
        headerMap.put("client_id", CLIENT_ID);

        StringBuilder sb = new StringBuilder();
        sb.append(CLIENT_ID);
        if (StringUtils.isNotBlank(requestBody)) {
            // sb.append(requestBody.replaceAll("\\s*|\t|\r|\n", "").trim());
            sb.append(requestBody);
        }
        sb.append(PUB_KEY);
        String sign = SHA256Util.getSHA256(sb.toString(), PUB_KEY);
        headerMap.put("signature", sign);

//        if (StringUtils.isNotBlank(busi_id)) {
//            headerMap.put("busi_id", busi_id);
//        }
//        if (StringUtils.isNotBlank(repeat_check)) {
//            headerMap.put("repeat_check", repeat_check);
//        }
//		headerMap.put("ucg_flag", "y");

        String mediaType = "application/json;charset=utf-8";

        // 表体数据json
        // 根据安全级别选择加密或压缩请求表体参数
        String json = dealRequestBody(requestBody, security_key, SECRET_LEVEL);

        // 返回值
        String result = doPost(url, null, mediaType, headerMap, json);
        return dealResponseBody(result, security_key, SECRET_LEVEL);
    }

    /**
     * 返回值进行过加密和压缩，对返回值进行解压和解密
     *
     * @param source
     * @param security_key
     * @param level
     * @return
     * @throws Exception
     */
    private static String dealResponseBody(String source, String security_key, String level) throws Exception {
        String result;
        if (StringUtils.isEmpty(level) || SecretConst.LEVEL0.equals(level)) {
            result = source;
        } else if (SecretConst.LEVEL1.equals(level)) {
            result = Decryption.symDecrypt(security_key, source);
        } else if (SecretConst.LEVEL2.equals(level)) {
            result = CompressUtil.gzipDecompress(source);
        } else if (SecretConst.LEVEL3.equals(level)) {
            result = CompressUtil.gzipDecompress(Decryption.symDecrypt(security_key, source));
        } else if (SecretConst.LEVEL4.equals(level)) {
            result = Decryption.symDecrypt(security_key, CompressUtil.gzipDecompress(source));
        } else {
            throw new Exception("无效的安全等级");
        }

        return result;
    }

    /**
     * 根据安全级别设置，表体是否加密或压缩
     */
    private static String dealRequestBody(String source, String security_key, String level) throws Exception {
        String result;
        if (StringUtils.isEmpty(level) || SecretConst.LEVEL0.equals(level)) {
            result = source;
        } else if (SecretConst.LEVEL1.equals(level)) {
            result = Encryption.symEncrypt(security_key, source);
        } else if (SecretConst.LEVEL2.equals(level)) {
            result = CompressUtil.gzipCompress(source);
        } else if (SecretConst.LEVEL3.equals(level)) {
            result = Encryption.symEncrypt(security_key, CompressUtil.gzipCompress(source));
        } else if (SecretConst.LEVEL4.equals(level)) {
            result = CompressUtil.gzipCompress(Encryption.symEncrypt(security_key, source));
        } else {
            throw new Exception("无效的安全等级");
        }

        return result;
    }


    /**
     * 发送post请求
     *
     * @param baseUrl   请求接口
     * @param paramMap  参数
     * @param mediaType content-type
     * @param headers   头信息
     * @param json      json
     * @return 结果
     */
    private static String doPost(String baseUrl, Map<String, String> paramMap, String mediaType, Map<String, String> headers, String json) throws Exception {
        HttpURLConnection urlConnection = null;
        InputStream in = null;
        OutputStream out = null;
        BufferedReader bufferedReader = null;
        String result;
        try {
            StringBuilder sb = new StringBuilder();
            sb.append(baseUrl);
            if (paramMap != null) {
                sb.append("?");
                for (Map.Entry<String, String> entry : paramMap.entrySet()) {
                    String key = entry.getKey();
                    String value = entry.getValue();
                    sb.append(key).append("=").append(value).append("&");
                }
                baseUrl = sb.substring(0, sb.toString().length() - 1);
            }

            URL urlObj = new URL(baseUrl);
            urlConnection = (HttpURLConnection) urlObj.openConnection();
            urlConnection.setConnectTimeout(50000);
            urlConnection.setRequestMethod("POST");
            urlConnection.setDoOutput(true);
            urlConnection.setDoInput(true);
            urlConnection.setUseCaches(false);
            urlConnection.addRequestProperty("content-type", mediaType);
            if (headers != null) {
                for (String key : headers.keySet()) {
                    urlConnection.addRequestProperty(key, headers.get(key));
                }
            }
            out = urlConnection.getOutputStream();
            out.write(json.getBytes(StandardCharsets.UTF_8));
            out.flush();
            int resCode = urlConnection.getResponseCode();
//            System.out.println("状态码：：" + resCode);
//			if (resCode == HttpURLConnection.HTTP_OK || resCode == HttpURLConnection.HTTP_CREATED || resCode == HttpURLConnection.HTTP_ACCEPTED) {
            in = urlConnection.getInputStream();
//			} else {
//				in = urlConnection.getErrorStream();
//			}
            bufferedReader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));
            StringBuilder temp = new StringBuilder();
            String line = bufferedReader.readLine();
            while (line != null) {
                temp.append(line).append("\r\n");
                line = bufferedReader.readLine();
            }
            String ecod = urlConnection.getContentEncoding();
            if (ecod == null) {
                ecod = StandardCharsets.UTF_8.name();
            }
            result = new String(temp.toString().getBytes(StandardCharsets.UTF_8), ecod);
//            System.out.println(result);
        } finally {
            if (null != bufferedReader) {
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != out) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != in) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            assert urlConnection != null;
            urlConnection.disconnect();
        }
        return result;
    }

}
