package com.malk.boyang;

import com.alibaba.fastjson.JSONObject;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.MessageFormat;
import java.util.*;

import com.malk.boyang.service.BoyangService;
import com.malk.boyang.utils.HTTPHelper;
import com.malk.utils.UtilMap;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.digest.HmacAlgorithms;
import org.apache.commons.codec.digest.HmacUtils;
import org.json.JSONArray;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@Slf4j
@SpringBootTest
@RunWith(SpringRunner.class)
public class EqbTest {
    @Autowired
    private BoyangService boyangService;



    //测试环境
    // 应用ID
    /*final static String projectId = "1000004";
    // 应用密钥
    final static String secret = "96Uh7CR83NkN3TA6";
    // 接口调用域名
    final static String host = "http://122.227.225.202:9011/";*/

    //===============================================================================================

    //正式环境
    // 应用ID
    final static String projectId = "1000003";
    // 应用密钥
    final static String secret = "5V6xsY3q8JWZ9Qik";
    // 接口调用域名
    final static String host = "https://dzqz.beyond-it-service.com/";


    /*public static void main(String[] args) {
        // 请求签名鉴权-POST请求
//        testPost(projectId, secret, host);

        // 请求签名鉴权-GET请求
//        testGet(projectId, secret, host);

        // 请求签名鉴权-POST请求-文件上传
//        testUpload(projectId, secret, host);

    }*/

    @Test
    /***
     * 请求签名鉴权-POST请求
     *
     * @param projectId 项目Id
     * @param secret 项目密钥
     * @param host 网关地址
     */
    public void testPost() {
        // 查询查询内部组织详情地址
        String getInnerOrganizationsDetailApi = "/manage/v1/innerOrganizations/detail";
        // 查询查询内部组织详情请求地址
        String getInnerOrganizationsDetailApiUrl = host + getInnerOrganizationsDetailApi;

        try {
            // 构建请求Body体
            JSONObject reqBodyObj = new JSONObject(true);
            reqBodyObj.put("organizationCode", "");
            reqBodyObj.put("customOrgNo", "");
            reqBodyObj.put("name", "博洋");

            // 请求Body体数据
            String reqBodyData = reqBodyObj.toString();
            // 对请求Body体内的数据计算ContentMD5

            // 构建参与请求签名计算的明文
            String plaintext = reqBodyData;
            // 计算请求签名值
            String reqSignature = sign(plaintext, secret);

            // 构建请求头
            LinkedHashMap<String, String> header = new LinkedHashMap<>();
            // 构建待签名字符串
            String accept = "*/*";
            String contentType = "application/json; charset=UTF-8";
            header.put("X-timevale-project-id", projectId);
            header.put("X-timevale-signature", reqSignature);
            header.put("Accept", accept);
            header.put("Content-Type", contentType);

            // 发送POST请求
            String result = HTTPHelper.sendPOST(getInnerOrganizationsDetailApiUrl, reqBodyData, header, "UTF-8");
            JSONObject resultObj = JSONObject.parseObject(result);
            System.out.println("请求返回信息： " + resultObj.toString());
        } catch (Exception e) {
            e.printStackTrace();
            String msg = MessageFormat.format("请求签名鉴权方式调用接口出现异常: {0}", e.getMessage());
            System.out.println(msg);
        }
    }

    @Test
    /***
     * 使用文件发起签署（一步发起签署）
     *
     * @param projectId 项目Id
     * @param secret 项目密钥
     * @param host 网关地址
     */
    public void testPost2() {

        String api = "/esign-signs/v1/signFlow/createAndStart";

        String getInnerOrganizationsDetailApiUrl = host + api;

        try {
            // 构建请求Body体
            JSONObject reqBodyObj = new JSONObject(true);
            // 添加基本字段
            reqBodyObj.put("subject", "测试api直接发起签署");
            reqBodyObj.put("businessNo", "R9N-KN3tTOyNDTIWbxI7LA01161763691347");
            reqBodyObj.put("businessTypeCode", "889726e889ab84fea3514748d6df565c");
            reqBodyObj.put("remark", "测试");

            // 构建initiatorInfo对象
            JSONObject initiatorInfo = new JSONObject(true);
            initiatorInfo.put("userCode", "wanghh");
            initiatorInfo.put("departmentCode", "b60a9c18b8cc4ecc80e30f36b4267a68");
            initiatorInfo.put("organizationCode", "b60a9c18b8cc4ecc80e30f36b4267a68");
            reqBodyObj.put("initiatorInfo", initiatorInfo);

            // 添加其他字段
            reqBodyObj.put("redirectUrl", "https://www.baidu.com");
            reqBodyObj.put("signNotifyUrl", "http://3eb3815c.r23.cpolar.top/boyang/callback");

            // 构建signFiles数组
            JSONArray signFiles = new JSONArray();
            JSONObject signFile = new JSONObject(true);
            signFile.put("fileKey", "$832b183d-b3ac-4587-9488-553b82e11eec$2419219229");
            signFile.put("fileOrder", 1);
            signFiles.put(signFile);
            reqBodyObj.put("signFiles", signFiles);

            // 构建signerInfos数组
            JSONArray signerInfos = new JSONArray();
            JSONObject signerInfo = new JSONObject(true);
            signerInfo.put("userType", "1");
            signerInfo.put("userCode", "wanghh");
            signerInfo.put("departmentCode", "b60a9c18b8cc4ecc80e30f36b4267a68");
            signerInfo.put("organizationCode", "b60a9c18b8cc4ecc80e30f36b4267a68");
            signerInfo.put("signNode", 1);
            signerInfo.put("signMode", "0");
            signerInfo.put("signOrder", 1);
            signerInfos.put(signerInfo);
            reqBodyObj.put("signerInfos", signerInfos);


            // 请求Body体数据
            String reqBodyData = reqBodyObj.toString();
            // 对请求Body体内的数据计算ContentMD5

            // 构建参与请求签名计算的明文
            String plaintext = reqBodyData;
            // 计算请求签名值
            String reqSignature = sign(plaintext, secret);

            // 构建请求头
            LinkedHashMap<String, String> header = new LinkedHashMap<>();
            // 构建待签名字符串
            String accept = "*/*";
            String contentType = "application/json; charset=UTF-8";
            header.put("X-timevale-project-id", projectId);
            header.put("X-timevale-signature", reqSignature);
            header.put("Accept", accept);
            header.put("Content-Type", contentType);

            // 发送POST请求
            String result = HTTPHelper.sendPOST(getInnerOrganizationsDetailApiUrl, reqBodyData, header, "UTF-8");
            JSONObject resultObj = JSONObject.parseObject(result);
            System.out.println("请求返回信息： " + resultObj.toString());
        } catch (Exception e) {
            e.printStackTrace();
            String msg = MessageFormat.format("请求签名鉴权方式调用接口出现异常: {0}", e.getMessage());
            System.out.println(msg);
        }
    }

    /***
     * 请求签名鉴权-GET请求
     *
     * @param projectId 项目id
     * @param secret 项目密钥
     * @param host 网关地址
     */
    public static void testGet(String projectId, String secret, String host) {
        // 获取签署地址列表API地址
        String getSignFlowApi = "/esign-signs/v1/signFlow/signUrls?signFlowId=" + "24210df8420968c1e785a3b7582295b6";
        // 获取签署地址列表接口请求地址
        String hostGetSignFlowApi = host + getSignFlowApi;

        try {
            // 构建待签名字符串
            String accept = "*/*";
            String contentType = "application/json; charset=UTF-8";

            // 构建参与请求签名计算的明文
            int index = getSignFlowApi.indexOf("?");
            String plaintext = index == -1 ? "" : getSignFlowApi.substring(index + 1);
            // 计算请求签名值
            String reqSignature = sign(plaintext, secret);

            // 构建请求头
            LinkedHashMap<String, String> header = new LinkedHashMap<>();
            header.put("X-timevale-project-id", projectId);
            header.put("X-timevale-signature", reqSignature);
            header.put("Accept", accept);
            header.put("Content-Type", contentType);

            // 发送GET请求
            String result = HTTPHelper.sendGet(hostGetSignFlowApi, header, "UTF-8");
            JSONObject resultObj = JSONObject.parseObject(result);
            System.out.println("请求返回信息： " + resultObj.toString());
        } catch (Exception e) {
            e.printStackTrace();
            String msg = MessageFormat.format("请求签名鉴权方式调用接口出现异常: {0}", e.getMessage());
            System.out.println(msg);
        }
    }

    /***
     * 查询电子签署业务模板详情
     */
    @Test
    public void testGet2() {

        String api = "/esign-docs/v1/bizTemplates/889726e889ab84fea3514748d6df565c";

        String hostGetSignFlowApi = host + api;

        try {
            // 构建待签名字符串
            String accept = "*/*";
            String contentType = "application/json; charset=UTF-8";

            // 构建参与请求签名计算的明文
            int index = api.indexOf("?");
            String plaintext = index == -1 ? "" : api.substring(index + 1);
            // 计算请求签名值
            String reqSignature = sign(plaintext, secret);

            // 构建请求头
            LinkedHashMap<String, String> header = new LinkedHashMap<>();
            header.put("X-timevale-project-id", projectId);
            header.put("X-timevale-signature", reqSignature);
            header.put("Accept", accept);
            header.put("Content-Type", contentType);

            // 发送GET请求
            String result = HTTPHelper.sendGet(hostGetSignFlowApi, header, "UTF-8");
            JSONObject resultObj = JSONObject.parseObject(result);
            System.out.println("请求返回信息： " + resultObj.toString());
        } catch (Exception e) {
            e.printStackTrace();
            String msg = MessageFormat.format("请求签名鉴权方式调用接口出现异常: {0}", e.getMessage());
            System.out.println(msg);
        }
    }


    @Test
    public void testMembersList() {
        // 获取签署地址列表API地址
        String getSignFlowApi = "/manage/v1/innerOrganizations/members/list";
        // 获取签署地址列表接口请求地址
        String hostGetSignFlowApi = host + getSignFlowApi;

        try {
            // 构建请求Body体
            JSONObject reqBodyObj = new JSONObject(true);
            reqBodyObj.put("queryScope", "0");
            reqBodyObj.put("organizationCode", "b60a9c18b8cc4ecc80e30f36b4267a68");
            reqBodyObj.put("pageNo", 1);
            reqBodyObj.put("pageSize", "50");

            // 请求Body体数据
            String reqBodyData = reqBodyObj.toString();
            // 对请求Body体内的数据计算ContentMD5

            // 构建参与请求签名计算的明文
            String plaintext = reqBodyData;
            // 计算请求签名值
            String reqSignature = sign(plaintext, secret);

            // 构建请求头
            LinkedHashMap<String, String> header = new LinkedHashMap<>();
            // 构建待签名字符串
            String accept = "*/*";
            String contentType = "application/json; charset=UTF-8";
            header.put("X-timevale-project-id", projectId);
            header.put("X-timevale-signature", reqSignature);
            header.put("Accept", accept);
            header.put("Content-Type", contentType);

            // 发送GET请求
            String result = HTTPHelper.sendPOST(hostGetSignFlowApi,reqBodyData, header, "UTF-8");
            JSONObject resultObj = JSONObject.parseObject(result);
            System.out.println("请求返回信息： " + resultObj.toString());
        } catch (Exception e) {
            e.printStackTrace();
            String msg = MessageFormat.format("请求签名鉴权方式调用接口出现异常: {0}", e.getMessage());
            System.out.println(msg);
        }
    }

    @Test
    public void test4(){
        boyangService.signed("","");
    }

    @Test
    public void uploadEqbFile(){
        String fileName = "2.png";
        String filePath = "C:\\Users\\EDY\\Pictures\\2.png";
        try {
            //获得文件后缀名
            String suffix = fileName.substring(fileName.lastIndexOf(".")+1);

            //生成上传文件链接
            String api = host + "file/v1/generateUploadUrl";

            JSONObject reqBodyObj = new JSONObject(true);
            reqBodyObj.put("requestID", UUID.randomUUID().toString().replaceAll("-",""));//请求ID，长度：32位，
            reqBodyObj.put("type", 1);//获取上传链接类型  0为同步上传，适用于100M以内的pdf文件。 1为异步上传，适用于大于100M的pdf文件，以及其他类型的文件：ofd、doc、docx、xls、xlsx、jpg、jpeg、png、zip、rar。

            Map data = eqbPost(api, reqBodyObj);

            String url = UtilMap.getString(data, "url");
            url = url.replace("http://11.0.11.62:8199/",host);

            // 上传文件到指定链接
            Map<String,Object> body = new HashMap<>();
            body.put("file",fileName);

            // 构建请求头
            String reqSignature2 = sign(JSONObject.toJSONString(body), secret);
            LinkedHashMap<String, String> header2 = new LinkedHashMap<>();
            // 构建待签名字符串
            header2.put("X-timevale-project-id", projectId);
            header2.put("X-timevale-signature", reqSignature2);
            header2.put("Accept", "*/*");

            String result2 = HTTPHelper.uploadFile(url,  "file", filePath, body,  header2, "UTF-8");
            Map parse = (Map) JSONObject.parse(result2);

            Map data1 = UtilMap.getMap(parse, "data");
            String fileKey = UtilMap.getString(data1, "fileKey");


            //若文件不是pdf则需转换
            if(!"pdf".equals(suffix)){
                //文档格式转换
                Map body2 = new HashMap();
                body2.put("fileKey", fileKey);
                body2.put("targetType", "pdf");

                Map map = eqbPost(host + "file/v1/fileConvert", body2);

                fileKey = UtilMap.getString(map,"convertedFileKey");
            }

            System.out.println("fileKey： " + fileKey);
        } catch (Exception e) {
            e.printStackTrace();
            String msg = MessageFormat.format("请求签名鉴权方式调用接口出现异常: {0}", e.getMessage());
            System.out.println(msg);
        }
    }

    private Map eqbPost(String url,Map body){
        try {
            // 请求Body体数据
            String reqBodyData = JSONObject.toJSONString(body);

            // 计算请求签名值
            String reqSignature = sign(reqBodyData, secret);

            // 构建请求头
            LinkedHashMap<String, String> header = new LinkedHashMap<>();

            // 构建待签名字符串
            header.put("X-timevale-project-id", projectId);
            header.put("X-timevale-signature", reqSignature);
            header.put("Accept", "*/*");
            header.put("Content-Type", "application/json; charset=UTF-8");

            String result = HTTPHelper.sendPOST(url, reqBodyData, header, "UTF-8");

            Map resultObj = (Map) JSONObject.parse(result);

            Map data = UtilMap.getMap(resultObj, "data");

            return data;
        }catch (Exception e){
            throw new RuntimeException(e);
        }

    }

    @Test
    public void test5(){
        // 构建请求Body体
        JSONObject reqBodyObj = new JSONObject(true);
        reqBodyObj.put("hash", "0748da018502f6331f10d64e645bc0b8f20d44cc7d041a9752ce586149b843d7");
        reqBodyObj.put("filePwd", "");

        // 请求Body体数据
        String reqBodyData = reqBodyObj.toString();
        // 对请求Body体内的数据计算ContentMD5

        // 构建参与请求签名计算的明文
        String plaintext = reqBodyData;
        // 计算请求签名值
        String reqSignature = sign(plaintext, secret);

        System.out.println(reqSignature);

        // 构建请求头
        LinkedHashMap<String, String> header = new LinkedHashMap<>();
        // 构建待签名字符串
        String accept = "*/*";
        String contentType = "application/json; charset=UTF-8";
        header.put("X-timevale-project-id", projectId);
        header.put("X-timevale-signature", reqSignature);
        header.put("Accept", accept);
        header.put("Content-Type", contentType);
    }

    /**
     * hmac-sha256签名
     *
     * @param content 代签名的内容
     * @param key     签名的key
     * @return 签名
     */
    public static String sign(String content, String key) {
        byte[] bytes = new HmacUtils(HmacAlgorithms.HMAC_SHA_256, key).hmac(content);
        return new String(Hex.encodeHex(bytes));
    }

    /**
     * 计算文件的SHA-256哈希值
     */
    public static String calculateSha256(File file) throws Exception {
        byte[] fileBytes = new byte[(int) file.length()];
        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        byte[] hashBytes = digest.digest(fileBytes);

        // 转换为十六进制字符串
        StringBuilder hexString = new StringBuilder();
        for (byte b : hashBytes) {
            String hex = Integer.toHexString(0xff & b);
            if (hex.length() == 1) hexString.append('0');
            hexString.append(hex);
        }
        return hexString.toString();
    }


    /***
     * 请求签名鉴权-POST请求
     *
     */
    @Test
    public void testUpload() {
        String filePath = "d:\\母婴店.pdf";

        // 文件上传接口
        String uploadApi = "/file/v1/pdf/uploadAndSpilt";
//        String uploadApi = "/file/v1/uploadWithAuth";
        // 文件上传接口请求地址
        String uploadApiUrl = host + uploadApi;

        try {
            // 构建请求Body体
            JSONObject reqBodyObj = new JSONObject(true);
            reqBodyObj.put("file", "母婴店.pdf");

//            reqBodyObj.put("hash", calculateSha256(new File(filePath)));
//            reqBodyObj.put("hash", "17070b46957568b378c4c8970beceaf2d50b590ec13852a91f2eac0031bcdf96");
            reqBodyObj.put("filePwd", "");

            // 请求Body体数据
            String reqBodyData = reqBodyObj.toString();

            // 构建参与请求签名计算的明文
            String plaintext = reqBodyData;
            // 计算请求签名值
            String reqSignature = sign(plaintext, secret);

//            reqBodyObj.put("file","床上用品店.pdf");

            // 构建文件
            String fileFieldName = "file";

            // 构建请求头
            LinkedHashMap<String, String> header = new LinkedHashMap<>();
            // 构建待签名字符串
            String accept = "*/*";
            header.put("X-timevale-project-id", projectId);
            header.put("X-timevale-signature", reqSignature);
            header.put("Accept", accept);
            // 发送POST请求
            String result = HTTPHelper.uploadFile(uploadApiUrl,  fileFieldName, filePath, reqBodyObj,  header, "UTF-8");
            JSONObject resultObj = JSONObject.parseObject(result);
            System.out.println("请求返回信息： " + resultObj.toString());
        } catch (Exception e) {
            e.printStackTrace();
            String msg = MessageFormat.format("请求签名鉴权方式调用接口出现异常: {0}", e.getMessage());
            System.out.println(msg);
        }
    }

    @Test
    public void test11(){
        Map eqbUser = new HashMap();
        eqbUser.put("name", "张三");
        eqbUser.put("mobile", "15900010001");
        eqbUser.put("customAccountNo", "15900010001");
        eqbUser.put("mainOrganizationCode", "b60a9c18b8cc4ecc80e30f36b4267a68");//默认组织账号

        Map map = (Map) eqbPost2(host + "/manage/v1/innerUsers/create", Arrays.asList(eqbUser));

        System.out.println(map);
    }


    //e签宝-post请求（application/json）
    private Object eqbPost2(String url,Object body){
        try {
            // 请求Body体数据
            String reqBodyData = JSONObject.toJSONString(body);

            // 计算请求签名值
            String reqSignature = sign(reqBodyData, secret);

            // 构建请求头
            LinkedHashMap<String, String> header = new LinkedHashMap<>();

            // 构建待签名字符串
            header.put("X-timevale-project-id", projectId);
            header.put("X-timevale-signature", reqSignature);
            header.put("Accept", "*/*");
            header.put("Content-Type", "application/json; charset=UTF-8");

            String resultStr = HTTPHelper.sendPOST(url, reqBodyData, header, "UTF-8");

            Map result = (Map) JSONObject.parse(resultStr);


            Object data = result.get("data");

            return data;
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }


}