package cn.iocoder.yudao.module.identity.utils;

import cn.hutool.core.net.URLDecoder;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.crypto.PemUtil;
import cn.hutool.http.*;
import cn.hutool.json.JSONObject;
import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants;
import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
import cn.iocoder.yudao.framework.common.util.string.StrUtils;
import cn.iocoder.yudao.module.identity.controller.admin.scanrecord.vo.BrokenRespVO;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemWriter;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Slf4j
public class CodeRequestUtils {

    // 测试域名
//    public static final String URL = "https://decodert.315-china.cn/api/partner/tags/decode";

    // 生产域名
    public static final String URL = "https://decoder.315-china.cn/api/partner/tags/decode";

    // 测试APP_ID
//    public static final String APP_ID = "v1JHJLH6z7xjrNl1LxvY";

    // 生产APP_ID
    public static final String APP_ID = "frgiN5JOcwbAMZeZMPkN";
//    public static final String PRIVATE_KEY = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAIWP9hNkCJcSkkTSnphxAorUh2x98zG0RzDNEGqdUFC3vTU74Do9n15r1wht1Dii6322eNKjNgIPrvBim7YnQ9GwbNiJhRYnzu/4q3pvMBwoVNRW5gdO9PPU9tbEr5+Lxb4MN+7x0DZBYoHh2liIlInLg95wYRtdCOzxNMJId0zPAgMBAAECgYB0NP54fpfOwdTL1qkwn1sD6chuR+OZwm4ScskuyfMAV+1i7Na6NbV81L1CUzTLlkzokyPquSCbiIPAGTu7r8wbz5yJFC95owG0v8DhNvJbajzBb9QJnkdfEtt74y1o7EE2QOLSiuZM/XDYyHV07UOWjpKc6N8/PaSPew8hb6Vq0QJBAPDfRNeJJBO6NFBMul3AhJ4kIEc9+qCso7cUm/9o8cBU1gZ/qgu/+E+fkk5SFv4v4HYa0Kx/jkHPswGZ18GuCFkCQQCN817U7tmvNlIVUyPvWl0WXhFGizl2fr0M/KgGokwTfTbnWht89Ekv+7N1o7wm8T1j3I4MTmDCQlAKMtmdg1lnAkA7TUy+n+YA8VwF1Q4hHM/Ju20y/QBiZH6eCXXqqOS0DG7xBKdR4z54I/o6TB2bESB7E1kCzxiv/Tm+ECk9ZuJpAkBRyxEyuup+FlvX489KBRSsZcmoj2KuD7tZd2BOakhR1o3DY12Bc7WUS4GN4Kny+oC4QQcsuiDw7or2RXS1WVEzAkBU69zccritikK+kcjY0H0tNiduirY0/VTcF/oBevs8kRCejxtTQycVFg7ek/E67TS2Ks14YowOXQ0Mpm/ofPM6";

    // 生产 PRIVATE_KEY PKCS1格式
//    public static final String PRIVATE_KEY = "MIICXQIBAAKBgQDj+v1nQTEJhS9os/BPuvsymTtBc7AUZO4NKTEg+cQJ9Ejp3ShT2SNSMvfhoX2WjDyFLIprfELGBzUT+kIjpdf6n8RpIZs4LfhpMkDeNonce8iLL8MauX6N+6VWGiKOxq7n4GZIK9fZ7i++qdwfwu1cTxJD4NU5zubnjEzS6uXxEQIDAQABAoGANIuH1kGXTMtupuI6NBYziXD50FcasUil+VCSKziF74lnOMepYNH+KxbmPRHcgVNnK4adjLKCLWRB3o3iqpax1Xlz/2vSPikgnnZ23faT0duqD0AIx4QaY7v2zbujvRt/REj88DvxxSoHMgE+xse/bt3H4BDTk67d3hTc27zIcUECQQD+e9Ybon21UWPqBjvT4LBmv7jN60mzI76FONgvvMLll4Dp3NEJEzRx+Zt4Dz/eqdxRo14t4x4N3Gc72I5EjnB5AkEA5Va6YTVivfTnXhHIRg5lOQQ694cMwG3C1I+dAfs260VVxf54hwywz1Xhbb/KTtRLJHOyN0gyHjHsWHi7difPWQJBAKvwEWYUcCisd/wrAAsUWTriuELwgJf3Q4cRNAd02p1yslfPqLAf+KQ1CBSjAP04+LFz1nLca3bj/h/SHbU2I8kCQQCg0w7keFGEMCfHueSd7B5ju2m2h0gT8WS9NvC9oPNETVz2+Zp/6hBbdTgehG5UlV8UcuW5CrHKpuu8pv2ewBARAkBVxmP/Yap/tqK4ZU9U2LfRj7BZY0ehctaGB/z2jh/8GApwncLkyodA7Dys0c4n6xIy091+nG1zKLk9x842ea1f";

    // 测试 PRIVATE_KEY PKCS8 格式
//    public static final String PRIVATE_KEY = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKVqCUnlYcFU8RjT\n" +
//            "X+X3MyGTXHGJSr4okZy0O2MOvKihDlVVViWIXSaZiNSHuZKuxa38mI0H6CwHTlQ3\n" +
//            "agmcPCb+3a5jp33VCi7K/MfeiKiLWmrEizo1KpR4PEqEsdNehZUORtElU98g1dB0\n" +
//            "c4Hi+V6dSmFqSRthvaaCj5pAUqD7AgMBAAECgYAHdLIafJZdaoC7h7uI2A2b89J0\n" +
//            "46VU0OtPTuhmXKGwUCIfQotxgaYBOWZrffqlW+9ZGkud/789TM8BCMZkzIABh2pG\n" +
//            "ZKpwIfibLHG+ABAEY6yd6zc3kSB40j6n3wNjn1XgwiC9sPy21mPMek6KMLMjgpXN\n" +
//            "Mjmm+/6fjdw3VYZ8sQJBAM7NzyKS1gjlb5vymWczyY4Yfbd6RSgLtuTK1m4rEMHw\n" +
//            "L1VohpnLc4qhIesstDIZ8zFx2KFm8CkvBQUky1dgQUUCQQDMw6BBh1OzHu2LKz94\n" +
//            "Bfgl5srrsIVmjXNwehwRZApOHGirC7fDTuRMUIMFzv5JoS2RhFFRkBTkh2Pq+mP9\n" +
//            "wt0/AkAHgC14Go1Ky0+N/3GS7azsy3Sb2AJ0HmCm0biPTF6SOiztUxo2r8tkBs4d\n" +
//            "IoTyoEBS1cc+q2YgiEUNV7VMWQBlAkEAhSy2jef2CAmVdW4rWWSIgB4a3C9yk8Br\n" +
//            "1DuXBbiK+0J+0MBORDiLQxcaIC0ANeMeQAZO3T1YWUm1Mp6naePTAQJAPIpGhvUR\n" +
//            "S1dIRPBh5qGqgxC+2ZHeTcedb6Z5jjYFrpPkUhPMgC4nOuI2c3tzIicXybEkMQBp\n" +
//            "uYXgBA7ENta9Ag==";

    // 生产 PRIVATE_KEY PKCS8 格式
    public static final String PRIVATE_KEY = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAOP6/WdBMQmFL2iz\n" +
            "8E+6+zKZO0FzsBRk7g0pMSD5xAn0SOndKFPZI1Iy9+GhfZaMPIUsimt8QsYHNRP6\n" +
            "QiOl1/qfxGkhmzgt+GkyQN42idx7yIsvwxq5fo37pVYaIo7GrufgZkgr19nuL76p\n" +
            "3B/C7VxPEkPg1TnO5ueMTNLq5fERAgMBAAECgYA0i4fWQZdMy26m4jo0FjOJcPnQ\n" +
            "VxqxSKX5UJIrOIXviWc4x6lg0f4rFuY9EdyBU2crhp2MsoItZEHejeKqlrHVeXP/\n" +
            "a9I+KSCednbd9pPR26oPQAjHhBpju/bNu6O9G39ESPzwO/HFKgcyAT7Gx79u3cfg\n" +
            "ENOTrt3eFNzbvMhxQQJBAP571huifbVRY+oGO9PgsGa/uM3rSbMjvoU42C+8wuWX\n" +
            "gOnc0QkTNHH5m3gPP96p3FGjXi3jHg3cZzvYjkSOcHkCQQDlVrphNWK99OdeEchG\n" +
            "DmU5BDr3hwzAbcLUj50B+zbrRVXF/niHDLDPVeFtv8pO1Eskc7I3SDIeMexYeLt2\n" +
            "J89ZAkEAq/ARZhRwKKx3/CsACxRZOuK4QvCAl/dDhxE0B3TanXKyV8+osB/4pDUI\n" +
            "FKMA/Tj4sXPWctxrduP+H9IdtTYjyQJBAKDTDuR4UYQwJ8e55J3sHmO7abaHSBPx\n" +
            "ZL028L2g80RNXPb5mn/qEFt1OB6EblSVXxRy5bkKscqm67ym/Z7AEBECQFXGY/9h\n" +
            "qn+2orhlT1TYt9GPsFljR6Fy1oYH/PaOH/wYCnCdwuTKh0DsPKzRzifrEjLT3X6c\n" +
            "bXMouT3HzjZ5rV8=";

    public static String httpPOST(String bodyJson, String privateKey) {
        String nonce = StrUtils.getRandomUpperString(8);// 随机字符串
        long timestamp = new Date().getTime() / 1000;
        String signature = CodeRequestUtils.signJdk(timestamp + nonce + bodyJson, privateKey);

        if (signature == null) {
            return null;
        }
        log.info("url:" + URL);
        log.info("timestamp:" + timestamp);
        log.info("nonce:" + nonce);
        log.info("bodyJson:" + bodyJson);
        log.info("signature:" + signature);

        HttpResponse response;
        try {
            response = HttpRequest.post(URL)
                    .header("app-id", APP_ID)
                    .header("timestamp", timestamp + "")
                    .header("nonce", nonce)
                    .header("signature", signature)
                    .header("Accept", ContentType.JSON.getValue())
                    .header("Content-Type", ContentType.JSON.getValue())
                    .contentType(ContentType.JSON.getValue())
                    .charset(CharsetUtil.UTF_8)
                    .body(bodyJson)
                    .execute();
        } catch (HttpException e) {
            // Http 异常
            log.error("接口调用异常:", e);
            throw ServiceExceptionUtil.exception(GlobalErrorCodeConstants.THIRD_PARTY_INTERFACE_CALL_FAILED);
        }
        assert response != null;
        System.out.println(response);
        if (response.getStatus() != HttpStatus.HTTP_OK) {
            throw ServiceExceptionUtil.exception(GlobalErrorCodeConstants.THIRD_PARTY_INTERFACE_CALL_FAILED);
        }

        return URLDecoder.decode(response.body(), StandardCharsets.UTF_8);
    }

    private static String signJdk(String content, String privateKey) {
        try {
            privateKey = privateKey.replace("-----BEGIN ENCRYPTED PRIVATE KEY-----", "")
                    .replace("-----END ENCRYPTED PRIVATE KEY-----", "").replace("-----BEGIN PRIVATE KEY-----", "")
                    .replace("-----END PRIVATE KEY-----", "").replace("\n", "");
            PrivateKey priKey = KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey)));
            Signature signature = Signature.getInstance("SHA1WithRSA");

            signature.initSign(priKey);
            signature.update(content.getBytes(StandardCharsets.UTF_8));
            return Base64.getEncoder().encodeToString(signature.sign()).replace("\n", "");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String readPemFile(String filePath) throws IOException {
        StringBuilder pemContent = new StringBuilder();

        try (FileInputStream fis = new FileInputStream(filePath);
             InputStreamReader isr = new InputStreamReader(fis);
             BufferedReader br = new BufferedReader(isr)) {
            String line;
            while ((line = br.readLine()) != null) {
                pemContent.append(line).append("\n");
            }
        }

        return pemContent.toString();
    }

    /**
     * pkcs1私钥转化为pkcs8私钥
     */
    public static String formatPkcs1ToPkcs8ByHutool(File pkcs1Key) throws Exception {
        PrivateKey privKeyInfo = PemUtil.readPemPrivateKey(new FileInputStream(pkcs1Key));
        /**将PKCS8中的私钥转换为PEM**/
        PemObject pemObject = new PemObject("PRIVATE KEY", privKeyInfo.getEncoded());
        try(StringWriter stringWriter = new StringWriter()) {
            PemWriter pemWriter = new PemWriter(stringWriter);
            pemWriter.writeObject(pemObject);
            pemWriter.flush();
            return stringWriter.toString();
        }
    }

    public static void main(String[] args) throws Exception {
        String pubicKeyInPkcs1 = AsymmetricKeyUtils.readKeyFromPath("D:\\private-key-PKCS1.pem");
        System.out.println("读取到的PKCS1格式公钥为：\n" + pubicKeyInPkcs1);
//        String publicKeyInPkcs8 = AsymmetricKeyUtils.transformPubKeyFromPkcs1ToPkcs8(pubicKeyInPkcs1);
//        System.out.println("转换后的PKCS8格式公钥为：\n" + publicKeyInPkcs8);

        String publicKeyInPkcs8 = CodeRequestUtils.formatPkcs1ToPkcs8ByHutool(new File("D:\\private-key-PKCS1.pem"));
        System.out.println("转换后的PKCS8格式公钥为：\n" + publicKeyInPkcs8);

        Map<String, String> params = new HashMap<>();
//        params.put("type", "WD5502");
        params.put("type", "WD5502TT");

//        params.put("m", "4177C6C7DDA8DA1FC14945C6C90C2F7800");
        params.put("m", "87B100011A850B");
        System.out.println(new JSONObject(params));
        String result = CodeRequestUtils.httpPOST(new JSONObject(params).toString(), PRIVATE_KEY);
        System.out.println("返回结果为:" + result);
        String data = new JSONObject(result).getStr("data");
        System.out.println(new JSONObject(data).toBean(BrokenRespVO.class));


//        String privateKeyInPkcs1 = AsymmetricKeyUtils.readKeyFromPath("");
//        System.out.println("读取到的PKCS1格式私钥为：\n" + privateKeyInPkcs1);
//        String privateKeyInPkcs8 = AsymmetricKeyUtils.transformPrivateKeyFromPkcs1ToPkcs8(privateKeyInPkcs1);
//        System.out.println("转换后的PKCS8格式私钥为：\n" + privateKeyInPkcs8);
//        privateKeyInPkcs1 = AsymmetricKeyUtils.transformPrivateKeyFromPkcs8ToPkcs1(privateKeyInPkcs8);
//        System.out.println("转换后的PKCS1格式私钥为：\n" + privateKeyInPkcs1);
    }

}
