package com.emoon.openplatform.controller;

import cn.hutool.core.codec.Base64;
import cn.hutool.http.HttpStatus;
import com.emoon.common.core.domain.R;
import com.emoon.common.core.utils.StringUtils;
import com.emoon.openplatform.util.HttpUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

/**
 * @author destiny
 * @description:
 * @date 2025/10/25 19:37
 */
@Slf4j
@RestController
@RequestMapping("/sm4")
@RequiredArgsConstructor
public class Sm4Controller {

    @Value("${sm4.key}")
    private String sm4Key;

    @Value("${sm4.private-key}")
    private String sm4PrivateKey;

    @Value("${sm4.public-key}")
    private String sm4PublicKey;

    @Value("${sm4.open-url}")
    private String sm4OpenUrl;

    @Value("${sm4.open-url-local}")
    private String sm4OpenUrlLocal;

    public static final String NETWORK = "1";
    public static final String NETWORK_LOCAL = "2";

    @PostMapping("/dataSM4")
    public R<String> dataSM4(@RequestParam(required = false, defaultValue = "") String token,
                             @RequestParam String model,
                             @RequestParam String network,
                             @RequestParam("data") String dataJson) {
        try {
            String result = dataSM40(token, model, network, dataJson);
            return R.ok(result);
        } catch (Exception e) {
            log.error("Failed to get token: {}", e.getMessage(), e);
            return R.fail(HttpStatus.HTTP_INTERNAL_ERROR, "获取令牌失败: " + e.getMessage());
        }
    }

    public String dataSM40(String token, String model, String network, String dataJson) throws Exception {
        // 判断该请求是否需要生成token
        if ("noUse".equals(token)) {
            return "noToken";
        }

        // 组装请求的数据为base64格式
        ObjectMapper objectMapper = new ObjectMapper();
        Map<String, Object> data = new HashMap<>();
        data.put("model", model);
        data.put("network", network);

        // 解析输入数据
        Object inputData = objectMapper.readValue(dataJson, Object.class);
        data.put("input", inputData);

        String jsonData = objectMapper.writeValueAsString(data);
        System.out.println("参数标记: " + jsonData);

        // Base64编码
        String base64Data = Base64.encodeStr(jsonData.getBytes(StandardCharsets.UTF_8), true, true);

        // 对请求的参数进行SM4加密

        byte[] encryptedBinary = sm4Encrypt(base64Data, sm4PrivateKey, sm4Key);
        String encryptedBase64 = Base64.encodeStr(encryptedBinary, true, true);

        // 创建最终的含有SM4的IV的数据
        Map<String, String> modifiedDataMap = new HashMap<>();
        modifiedDataMap.put("encryptedBase64", encryptedBase64);
        modifiedDataMap.put("smIV", sm4Key);
        modifiedDataMap.put("publicKey", sm4PublicKey);

        String modifiedDataJson = objectMapper.writeValueAsString(modifiedDataMap);
        String modifiedDataBase64 = Base64.encodeStr(modifiedDataJson.getBytes(StandardCharsets.UTF_8), true, true);

        // 将 '+' 替换为 '-'，'/' 替换为 '_'
        String modifiedData = modifiedDataBase64.replace('+', '-').replace('/', '_');

        // 将加密的参数发送给开放平台，获取短令牌
        String url;
        if (StringUtils.equals(NETWORK, network)) {
            url = sm4OpenUrl + "/Apis/getToken";
        } else if (StringUtils.equals(NETWORK_LOCAL, network)) {
            url = sm4OpenUrlLocal + "/Apis/getToken";
        } else {
            throw new IllegalArgumentException("Invalid network parameter");
        }


        Map<String, String> encryption = new HashMap<>();
        encryption.put("information", modifiedData);

        String response = HttpUtil.curlPost(url, encryption);
        // 解析响应获取token（这里简化处理，实际应使用JSON解析库）
        // 假设响应格式为 {"token":"xxx","code":0}

        return parseTokenFromResponse(response);
    }

    // 简化的响应解析方法
    private String parseTokenFromResponse(String response) {
        // 实际应该使用JSON解析库如Jackson或Gson
        // 这里简化处理，假设响应格式为 {"token":"xxx","code":0}
        int start = response.indexOf("\"token\":\"") + 9;
        int end = response.indexOf("\"", start);
        return response.substring(start, end);
    }

    // SM4加密方法（使用AES算法模拟SM4）
    private byte[] sm4Encrypt(String data, String key, String iv) throws Exception {
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES");
        IvParameterSpec ivSpec = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
        return cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
    }
}
