package com.citygis.web.dataEncrypt.utils;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import javax.xml.bind.DatatypeConverter;
import java.nio.charset.StandardCharsets;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;

/**
 * @Author: zyl
 * @CreateTime: 2025-02-19
 * @Description: 密码机服务
 * @Version: 1.0
 */
public class CipherMachineUtil {

    public static String generateToken(String generateTokenUrl, String pwd) throws Exception {


        // 创建信任所有证书的HTTP客户端
        CloseableHttpClient httpClient = createUnsafeHttpClient();

        HttpPost httpPost = new HttpPost(generateTokenUrl);

        // 使用Fastjson构建请求体
        JSONObject requestBody = new JSONObject();
        requestBody.put("pwd", DatatypeConverter.printBase64Binary(pwd.getBytes("UTF-8")));
        httpPost.setEntity(new StringEntity(requestBody.toJSONString(), "UTF-8"));
        httpPost.setHeader("Content-Type", "application/json");

        HttpResponse response = httpClient.execute(httpPost);
        String responseBody = EntityUtils.toString(response.getEntity(), "UTF-8");

        // 使用Fastjson解析响应
        JSONObject jsonResponse = JSON.parseObject(responseBody);
        return jsonResponse.getJSONObject("result")
                .getString("outData");
    }

    public static String encryptData(String token, String plainText, String encryptDataUrl, String paddingType, Integer keyIndex, String algType, String iv) throws Exception {
        CloseableHttpClient httpClient = createUnsafeHttpClient();
        HttpPost httpPost = new HttpPost(encryptDataUrl);

        // 构建请求头
        httpPost.setHeader("X-SW-Authorization-Token", token);
        httpPost.setHeader("Content-Type", "application/json");

        // 构建请求体
        JSONObject requestBody = new JSONObject();
//        对称秘钥索引位，这里选择1号索引位
        requestBody.put("keyIndex", keyIndex);
//        对称秘钥算法，这里选择 SGD_SM4_ECB
        requestBody.put("algType", algType);
//        iv向量(base64)，非ECB不能为空；分组长度【8或者16】,当前选择ECB，留空
        requestBody.put("iv", iv);
        requestBody.put("inData", DatatypeConverter.printBase64Binary(plainText.getBytes("UTF-8"))); // 原文Base64编码
//        填充模式: [PKCS7PADDING，NOPADDING]
        requestBody.put("paddingType", paddingType);
        // ECB模式无需iv参数，故不添加

        httpPost.setEntity(new StringEntity(requestBody.toJSONString(), "UTF-8"));

        HttpResponse response = httpClient.execute(httpPost);
        int statusCode = response.getStatusLine().getStatusCode();
        if (statusCode != 200) {
            throw new RuntimeException("Request failed with code: " + statusCode);
        }

        String responseBody = EntityUtils.toString(response.getEntity(), "UTF-8");
        JSONObject jsonResponse = JSON.parseObject(responseBody);

        // 解析加密结果
        return jsonResponse.getJSONObject("result")
                .getString("outData");
    }

    public static String decryptData(String token, String encryptedBase64, String decryptDataUrl, String paddingType, Integer keyIndex, String algType, String iv) throws Exception {
        CloseableHttpClient httpClient = createUnsafeHttpClient();
        HttpPost httpPost = new HttpPost(decryptDataUrl);

        // 设置请求头
        httpPost.setHeader("X-SW-Authorization-Token", token);
        httpPost.setHeader("Content-Type", "application/json");

        // 构建请求体
        JSONObject requestBody = new JSONObject();
        requestBody.put("keyIndex", keyIndex);
        requestBody.put("algType", algType);
        requestBody.put("iv", iv);
        requestBody.put("inData", encryptedBase64); // 密文已经是Base64格式
        requestBody.put("paddingType", paddingType);
        // ECB模式不需要iv参数

        httpPost.setEntity(new StringEntity(requestBody.toJSONString(), StandardCharsets.UTF_8));

        HttpResponse response = httpClient.execute(httpPost);
        int statusCode = response.getStatusLine().getStatusCode();
        if (statusCode != 200) {
            throw new RuntimeException("解密请求失败，状态码: " + statusCode);
        }

        // 解析响应
        String responseBody = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
        JSONObject jsonResponse = JSON.parseObject(responseBody);

        // 获取解密结果并解码
        String outDataBase64 = jsonResponse.getJSONObject("result")
                .getString("outData");
        byte[] decryptedBytes = DatatypeConverter.parseBase64Binary(outDataBase64);
        return new String(decryptedBytes, StandardCharsets.UTF_8);
    }


    public static String generateHmac(String hmacUrl, String token, String originalData, int keyIndex, String hmacAlgType) throws Exception {
        CloseableHttpClient httpClient = createUnsafeHttpClient();
        HttpPost httpPost = new HttpPost(hmacUrl);

        // 设置请求头
        httpPost.setHeader("X-SW-Authorization-Token", token);
        httpPost.setHeader("Content-Type", "application/json");

        // 构建请求体
        JSONObject requestBody = new JSONObject();
        requestBody.put("keyIndex", keyIndex);
        requestBody.put("algType", hmacAlgType);
        requestBody.put("inData", DatatypeConverter.printBase64Binary(originalData.getBytes("UTF-8")));

        httpPost.setEntity(new StringEntity(requestBody.toJSONString(), StandardCharsets.UTF_8));

        HttpResponse response = httpClient.execute(httpPost);
        int statusCode = response.getStatusLine().getStatusCode();
        if (statusCode != 200) {
            throw new RuntimeException("HMAC请求失败，状态码: " + statusCode);
        }

        // 解析响应
        String responseBody = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
        JSONObject jsonResponse = JSON.parseObject(responseBody);

        return jsonResponse.getJSONObject("result")
                .getString("outData"); // 返回Base64格式的HMAC值
    }

    private static CloseableHttpClient createUnsafeHttpClient() throws NoSuchAlgorithmException, KeyManagementException {
        // 创建信任所有SSL证书的上下文
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, new TrustManager[]{
                new X509TrustManager() {
                    public void checkClientTrusted(X509Certificate[] chain, String authType) {
                    }

                    public void checkServerTrusted(X509Certificate[] chain, String authType) {
                    }

                    public X509Certificate[] getAcceptedIssuers() {
                        return null;
                    }
                }
        }, new java.security.SecureRandom());

        // 配置SocketFactory
        SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(
                sslContext,
                NoopHostnameVerifier.INSTANCE
        );

        return HttpClients.custom()
                .setSSLSocketFactory(sslSocketFactory)
                .build();
    }
}
