package nc.bs.uapbd.util;


import com.alibaba.fastjson.JSONObject;
import com.sm.misc.BASE64Decoder;
import com.sm.misc.BASE64Encoder;
import nc.bs.dao.DAOException;
import nc.bs.logging.Logger;
import nc.bs.trade.business.HYSuperDMO;
import nc.vo.opm.thirdapp.ThirdappVO;
import nc.ws.opm.pub.utils.security.SecurityUtil;
import org.apache.commons.httpclient.Header;

import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.X509EncodedKeySpec;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @description: openapi请求
 * @author: mzr
 * @date: 20250611
 */
public class BaseOpenApiReq {
    public String BASE_URL_DEV = "http://127.0.0.1:9080";
    /**
     * APP ID
     */
    public String CLIENT_ID = "BIP2312";
    /**
     * APP Secret
     */
    public String CLIENT_SECRET = "";
    /**
     * 公钥
     */
    public String PUBLIC_KEY = "";
    /**
     * 账套编码
     */
    public String BIZ_CENTER = "01";
    /**
     * 用户编码
     */
    public String USER_CODE = "BIP";

    public HttpClientWapper client = new HttpClientWapper();

    /**
     * 调用openAPI给客户分配组织
     */
    public void assignOrgApi(String url, JSONObject param) {
        ThirdappVO apiInfo = getApiInfo();
        if (apiInfo == null) {
            return;
        }
        // BASE_URL_DEV = SysParaInitQuery.getParaString("GLOBLE00000000000000", "GJBURL");
        CLIENT_ID = apiInfo.getApp_id();
        CLIENT_SECRET = apiInfo.getApp_secret();
        PUBLIC_KEY = apiInfo.getPublic_key();
        USER_CODE = apiInfo.getUser_code();
        try {
            String result = requestOpenApi(url, param);
            Logger.error("CustomerSaveAction-assignOrg-result = " + result);
        } catch (Exception e) {
            Logger.error("assignOrgApi-exp:" + e.getMessage());
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取openAPI的应用信息
     */
    private ThirdappVO getApiInfo() {
        ThirdappVO result = new ThirdappVO();
        String strWhere = " code = 'BIP2312' and dr=0";
        try {
            ThirdappVO[] vos = (ThirdappVO[]) new HYSuperDMO().queryByWhereClause(ThirdappVO.class, strWhere);
            if (vos != null) {
                result = vos[0];
            }
        } catch (DAOException e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * @param url
     * @param param
     * @return
     * @throws Exception
     */
    public String requestOpenApi(String url, Map<String, Object> param) throws Exception {
        return requestOpenApi(url, new JSONObject(param));
    }

    /**
     * @param url
     * @param param
     * @return
     * @throws Exception
     */
    public String requestOpenApi(String url, JSONObject param) throws Exception {
        return requestOpenApi(url, param.toJSONString());
    }

    public String requestOpenApi(String url, String param) throws Exception {
        String accessToken = this.getAccessTokenByClient();
        Logger.info("requestOpenApi-param:" + param.replace("	", ""));
        String sign = digest(CLIENT_ID + PUBLIC_KEY);
        List<Header> headers = new ArrayList<>();
        headers.add(new Header("Content-Type", "application/json;charset=UTF-8"));
        headers.add(new Header("signature", sign));
        headers.add(new Header("ucg_flag", "y"));
        headers.add(new Header("access_token", accessToken));
        headers.add(new Header("client_id", CLIENT_ID));
        HttpClientWapper.Response response;
        try {
            response = client.post(BASE_URL_DEV + url, headers.toArray(new Header[headers.size()]), null, param);
            return response.getData();
        } catch (Exception e) {
            Logger.error("requestOpenApi-exp:" + e.getMessage());
            return e.getMessage();
        }
    }

    /**
     * @param seed 种子，用于生成公钥
     * @param src  明文
     * @return
     * @throws Exception
     * @description RSA加密
     */
    public String pubEncrypt(String seed, String src) throws Exception {
        String target = null;
        ByteArrayOutputStream out = null;
        try {
            Key key = genPublicKey(PUBLIC_KEY);
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(1, key);
            byte[] data = src.getBytes();
            int inputLen = data.length;
            out = new ByteArrayOutputStream();
            int offSet = 0;
            int i = 0;
            while (inputLen - offSet > 0) {
                byte[] cache;
                ;
                if (inputLen - offSet > 117) {
                    cache = cipher.doFinal(data, offSet, 117);
                } else {
                    cache = cipher.doFinal(data, offSet, inputLen - offSet);
                }
                out.write(cache, 0, cache.length);
                i++;
                offSet = i * 117;
            }
            target = new BASE64Encoder().encodeBuffer(out.toByteArray());
        } catch (Exception e) {
            throw new Exception("加密失败" + e.getMessage());
        } finally {
            if (out != null) {
                out.close();
            }
        }
        return target;
    }

    /**
     * @param str
     * @return
     * @description 信息摘要
     */
    public static String digest(String str) {
        String encodestr = "";
        try {
            MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
            messageDigest.update(str.getBytes(StandardCharsets.UTF_8));
            encodestr = byte2Hex(messageDigest.digest());
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
        return encodestr;
    }

    private static String byte2Hex(byte[] bytes) {
        StringBuffer stringBuffer = new StringBuffer();
        String temp = null;
        for (int i = 0; i < bytes.length; i++) {
            temp = Integer.toHexString(bytes[i] & 0xFF);
            if (temp.length() == 1) {
                stringBuffer.append("0");
            }
            stringBuffer.append(temp);
        }
        return stringBuffer.toString();
    }

    /**
     * @return
     * @throws Exception
     * @description 根据种子生成密钥对
     */
    public static Key genPublicKey(String seed) throws Exception {
        Key key = null;
        try {
            byte[] keyBytes = new BASE64Decoder().decodeBuffer(seed);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
            key = keyFactory.generatePublic(x509KeySpec);
        } catch (Exception e) {
            throw new Exception("无效的密钥  " + e.getMessage());
        }
        return key;
    }


    public static String getSHA256(String str, String key) throws Exception {
        byte[] salt = new byte[16];
        SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
        random.setSeed(key.getBytes());
        random.nextBytes(salt);
        String salt_value = new BASE64Encoder().encodeBuffer(salt);
        return digest(str + salt_value.replaceAll("\r|\n", ""));
    }

    /**
     * @return
     * @throws Exception
     * @description 获取AccessToken
     */
    @SuppressWarnings("static-access")
    public String getAccessTokenByClient() throws Exception {
        String url = BASE_URL_DEV + "/nccloud/opm/accesstoken";
        List<Header> headers = new ArrayList<Header>();
        headers.add(new Header("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8"));
        // 获取信息摘要
        String signature = getSHA256(CLIENT_ID + CLIENT_SECRET + PUBLIC_KEY, PUBLIC_KEY);
        // 使用PUBLIC_KEY生成公钥，对CLIENT_SECRET加密
        SecurityUtil securityUtil = new SecurityUtil();
        String CLIENT_SECRETEn = URLEncoder.encode(securityUtil.pubEncrypt(PUBLIC_KEY, CLIENT_SECRET), StandardCharsets.UTF_8);
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("client_id", CLIENT_ID);
        params.put("userCode", USER_CODE);
        params.put("grant_type", "client_credentials");
        params.put("biz_center", BIZ_CENTER);
        params.put("signature", signature);
        params.put("client_secret", CLIENT_SECRETEn);
        try {
            HttpClientWapper.Response response = client.post(url, headers.toArray(new Header[headers.size()]), null, client.getURLParam(params));
            JSONObject result = JSONObject.parseObject(response.getData());
            boolean success = result.getBoolean("success");
            if (success) {
                return result.getJSONObject("data").getString("access_token");
            }
        } catch (Exception e) {
            Logger.error("getAccessTokenByClient-exp:" + e.getMessage());
        }
        return null;
    }
}

