package cn.hztech.sdk;

import cn.hztech.sdk.crypto.envelope.GmPacket;
import cn.hztech.sdk.crypto.envelope.GmPacketBuilder;
import cn.hztech.sdk.crypto.envelope.GmPacketParser;
import cn.hztech.sdk.crypto.sm2.SM2Util;
import cn.hztech.sdk.crypto.sm4.SM4Util;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.security.*;
import java.util.Base64;

import static org.junit.jupiter.api.Assertions.*;

/**
 * 报文构建器和解析器测试
 */
class GmPacketTest {

    private SM2Util sm2Util;
    private SM4Util sm4Util;
    private KeyPair senderKeyPair;
    private KeyPair receiverKeyPair;

    @BeforeEach
    void setUp() throws Exception {
        sm2Util = new SM2Util();
        sm4Util = new SM4Util();

        // 生成发送方密钥对
        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC", "BC");
        keyGen.initialize(256);
        senderKeyPair = keyGen.generateKeyPair();
        receiverKeyPair = keyGen.generateKeyPair();
    }

    @Test
    void testBuildAndParsePacket() {
        String appId = "TEST_APP_001";
        String businessData = "{\"userId\":\"12345\",\"userName\":\"测试用户\"}";

        // 构建报文（使用接收方公钥加密，发送方私钥签名）
        String senderPrivateKey = Base64.getEncoder().encodeToString(senderKeyPair.getPrivate().getEncoded());
        String receiverPublicKey = Base64.getEncoder().encodeToString(receiverKeyPair.getPublic().getEncoded());

        GmPacketBuilder builder = new GmPacketBuilder(appId, senderPrivateKey, receiverPublicKey, sm2Util, sm4Util);
        GmPacket packet = builder.build(businessData);

        assertNotNull(packet);
        assertEquals(appId, packet.getAppId());
        assertEquals("1.0", packet.getVersion());
        assertNotNull(packet.getTimestamp());
        assertNotNull(packet.getNonce());
        assertNotNull(packet.getEncryptKey());
        assertNotNull(packet.getEncryptData());
        assertNotNull(packet.getSign());

        // 解析报文（使用接收方私钥解密，发送方公钥验签）
        String receiverPrivateKey = Base64.getEncoder().encodeToString(receiverKeyPair.getPrivate().getEncoded());
        String senderPublicKey = Base64.getEncoder().encodeToString(senderKeyPair.getPublic().getEncoded());

        GmPacketParser parser = new GmPacketParser(receiverPrivateKey, senderPublicKey, sm2Util, sm4Util, 60000L);
        String decryptedData = parser.parse(packet);

        assertEquals(businessData, decryptedData);
    }

    @Test
    void testTimestampValidation() {
        String appId = "TEST_APP_001";
        String businessData = "{\"test\":\"data\"}";

        String senderPrivateKey = Base64.getEncoder().encodeToString(senderKeyPair.getPrivate().getEncoded());
        String receiverPublicKey = Base64.getEncoder().encodeToString(receiverKeyPair.getPublic().getEncoded());

        GmPacketBuilder builder = new GmPacketBuilder(appId, senderPrivateKey, receiverPublicKey, sm2Util, sm4Util);
        GmPacket packet = builder.build(businessData);

        // 修改时间戳为过期时间
        packet.setTimestamp(System.currentTimeMillis() - 120000); // 2分钟前

        String receiverPrivateKey = Base64.getEncoder().encodeToString(receiverKeyPair.getPrivate().getEncoded());
        String senderPublicKey = Base64.getEncoder().encodeToString(senderKeyPair.getPublic().getEncoded());

        GmPacketParser parser = new GmPacketParser(receiverPrivateKey, senderPublicKey, sm2Util, sm4Util, 60000L);

        assertThrows(SecurityException.class, () -> {
            parser.parse(packet);
        });
    }

    @Test
    void testSignatureValidation() {
        String appId = "TEST_APP_001";
        String businessData = "{\"test\":\"data\"}";

        String senderPrivateKey = Base64.getEncoder().encodeToString(senderKeyPair.getPrivate().getEncoded());
        String receiverPublicKey = Base64.getEncoder().encodeToString(receiverKeyPair.getPublic().getEncoded());

        GmPacketBuilder builder = new GmPacketBuilder(appId, senderPrivateKey, receiverPublicKey, sm2Util, sm4Util);
        GmPacket packet = builder.build(businessData);

        // 篡改签名
        packet.setSign("tampered_signature");

        String receiverPrivateKey = Base64.getEncoder().encodeToString(receiverKeyPair.getPrivate().getEncoded());
        String senderPublicKey = Base64.getEncoder().encodeToString(senderKeyPair.getPublic().getEncoded());

        GmPacketParser parser = new GmPacketParser(receiverPrivateKey, senderPublicKey, sm2Util, sm4Util, 60000L);

        assertThrows(SecurityException.class, () -> {
            parser.parse(packet);
        });
    }

    @Test
    void testMultiplePackets() {
        String appId = "TEST_APP_001";
        String senderPrivateKey = Base64.getEncoder().encodeToString(senderKeyPair.getPrivate().getEncoded());
        String receiverPublicKey = Base64.getEncoder().encodeToString(receiverKeyPair.getPublic().getEncoded());

        GmPacketBuilder builder = new GmPacketBuilder(appId, senderPrivateKey, receiverPublicKey, sm2Util, sm4Util);

        // 构建多个报文，验证nonce的唯一性
        GmPacket packet1 = builder.build("{\"data\":\"test1\"}");
        GmPacket packet2 = builder.build("{\"data\":\"test2\"}");

        assertNotEquals(packet1.getNonce(), packet2.getNonce());
        assertNotEquals(packet1.getEncryptKey(), packet2.getEncryptKey());
        assertNotEquals(packet1.getSign(), packet2.getSign());
    }
}
