package com.hfkj.channel.lakala.config;

import com.alibaba.fastjson.JSONObject;
import com.hfkj.common.exception.ErrorCode;
import com.hfkj.common.exception.ErrorHelp;
import com.hfkj.common.exception.SysCode;
import com.hfkj.common.utils.HttpsUtils;
import com.hfkj.config.CommonSysConst;
import org.apache.commons.collections4.MapUtils;

import java.io.FileInputStream;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

/**
 * 拉卡拉配置
 * @author hurui
 */
public class LaKaLaConfig {

    private static final Random RANDOM = new SecureRandom();

    private static final String SYMBOLS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

    /**
     *
     * 生成V2版本 Authorization 签名参数
     * @param body
     * @return
     */
    public static Map<String, Object> generateSignParamsV2(JSONObject body) {
        try {
            Map<String, Object> param = new HashMap<>();
            param.put("appid", CommonSysConst.getSysConfig().getLkl_v2_appid());
            param.put("serialNo", CommonSysConst.getSysConfig().getLkl_v2_serial_no());
            param.put("timestamp", System.currentTimeMillis()/1000);
            param.put("nonceStr", makeNonStr());

            String str = MapUtils.getString(param, "appid") + "\n" +
                    MapUtils.getString(param, "serialNo") + "\n" +
                    MapUtils.getString(param, "timestamp") + "\n" +
                    MapUtils.getString(param, "nonceStr") + "\n" +
                    body.toJSONString() + "\n";

            Path path = Paths.get(CommonSysConst.getSysConfig().getLkl_v2_private_key());
            String privateKey = new String(Files.readAllBytes(path), "utf-8");
            param.put("signature", RSAUtils.signByPrivateKey(str.getBytes(), privateKey));

            StringBuffer authorizationStr = new StringBuffer();
            authorizationStr.append("LKLAPI-SHA256withRSA").append(" ");
            authorizationStr.append("appid=").append("\"").append(MapUtils.getString(param, "appid")).append("\"").append(",");
            authorizationStr.append("serial_no=").append("\"").append(MapUtils.getString(param, "serialNo")).append("\"").append(",");
            authorizationStr.append("timestamp=").append("\"").append(MapUtils.getString(param, "timestamp")).append("\"").append(",");
            authorizationStr.append("nonce_str=").append("\"").append(MapUtils.getString(param, "nonceStr")).append("\"").append(",");
            authorizationStr.append("signature=").append("\"").append(MapUtils.getString(param, "signature")).append("\"");
            param.put("Authorization", authorizationStr);
            return param;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     *
     * 生成V3版本 Authorization 签名参数
     * @param body
     * @return
     */
    public static Map<String, Object> generateSignParamsV3(JSONObject body) {
        try {
            Map<String, Object> param = new HashMap<>();
            param.put("appid", CommonSysConst.getSysConfig().getLkl_v3_appid());
            param.put("serialNo", CommonSysConst.getSysConfig().getLkl_v3_serial_no());
            param.put("timestamp", System.currentTimeMillis()/1000);
            param.put("nonceStr", makeNonStr());

            String str = MapUtils.getString(param, "appid") + "\n" +
                    MapUtils.getString(param, "serialNo") + "\n" +
                    MapUtils.getString(param, "timestamp") + "\n" +
                    MapUtils.getString(param, "nonceStr") + "\n" +
                    body.toJSONString() + "\n";

            Path path = Paths.get(CommonSysConst.getSysConfig().getLkl_v3_private_key());
            String privateKey = new String(Files.readAllBytes(path), "utf-8");
            param.put("signature", RSAUtils.signByPrivateKey(str.getBytes(), privateKey));

            StringBuffer authorizationStr = new StringBuffer();
            authorizationStr.append("LKLAPI-SHA256withRSA").append(" ");
            authorizationStr.append("appid=").append("\"").append(MapUtils.getString(param, "appid")).append("\"").append(",");
            authorizationStr.append("serial_no=").append("\"").append(MapUtils.getString(param, "serialNo")).append("\"").append(",");
            authorizationStr.append("timestamp=").append("\"").append(MapUtils.getString(param, "timestamp")).append("\"").append(",");
            authorizationStr.append("nonce_str=").append("\"").append(MapUtils.getString(param, "nonceStr")).append("\"").append(",");
            authorizationStr.append("signature=").append("\"").append(MapUtils.getString(param, "signature")).append("\"");
            param.put("Authorization", authorizationStr);
            return param;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 查询卡BIN信息查询
     * @param cardNo
     * @return
     */
    public static JSONObject queryCardBin(String cardNo) {
        try {

            Map<String, Object> param = new HashMap<>();
            param.put("ver", "1.0.0");
            param.put("timestamp", System.currentTimeMillis());
            param.put("reqId", makeNonStr());

            Map<String, Object> reqData = new HashMap<>();
            reqData.put("version", "1.0");
            reqData.put("orderNo", makeNonStr());
            reqData.put("orgCode", CommonSysConst.getSysConfig().getLkl_org_code());
            reqData.put("cardNo", cardNo);
            param.put("reqData", reqData);

            // 生成签名
            Map<String, Object> reqParam = LaKaLaConfig.generateSignParamsV2(JSONObject.parseObject(JSONObject.toJSONString(param)));

            // 头部参数
            Map<String, Object> heard = new HashMap<>();
            heard.put("Authorization", reqParam.get("Authorization"));

            JSONObject responseBody = HttpsUtils.doPost(CommonSysConst.getSysConfig().getLkl_request_url() + "/api/v2/mms/openApi/cardBin", param, heard);
            if (!responseBody.getString("retCode").equals("000000")) {
                throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, responseBody.getString("retMsg"));
            }

            return responseBody.getJSONObject("respData");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static JSONObject uploadFile(String attType, String attExtName,String attContext) {
        try {
            Map<String, Object> param = new HashMap<>();
            param.put("ver", "1.0.0");
            param.put("timestamp", System.currentTimeMillis());
            param.put("reqId", makeNonStr());

            Map<String, Object> reqData = new HashMap<>();
            reqData.put("version", "1.0");
            reqData.put("orderNo", makeNonStr());
            reqData.put("orgCode", CommonSysConst.getSysConfig().getLkl_org_code());
            reqData.put("attType", attType);
            reqData.put("attExtName", attExtName);
            reqData.put("attContext", attContext);
            param.put("reqData", reqData);

            // 生成签名
            Map<String, Object> reqParam = LaKaLaConfig.generateSignParamsV2(JSONObject.parseObject(JSONObject.toJSONString(param)));

            // 头部参数
            Map<String, Object> heard = new HashMap<>();
            heard.put("Authorization", reqParam.get("Authorization"));

            JSONObject responseBody = HttpsUtils.doPost(CommonSysConst.getSysConfig().getLkl_request_url() + "/api/v2/mms/openApi/uploadFile", param, heard);
            System.out.println("body:" + JSONObject.toJSONString(param));
            System.out.println("response:" + responseBody.toJSONString());
            if (!responseBody.getString("retCode").equals("000000")) {
                throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, responseBody.getString("retMsg"));
            }

            return responseBody.getJSONObject("respData");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取12位随机字符串 Nonce Str
     *
     * @return String 随机字符串
     */
    public static String makeNonStr() {
        char[] nonceChars = new char[12];
        for (int index = 0; index < nonceChars.length; ++index) {
            nonceChars[index] = SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length()));
        }
        return new String(nonceChars);
    }




}
