package com.ruoyi.crypto.service.impl;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.nio.charset.StandardCharsets;
import java.security.Security;
import java.util.Collections;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import com.ruoyi.crypto.config.CryptoProperties;
import com.ruoyi.crypto.enums.CryptoDataType;

@DisplayName("StubCryptoServiceImpl")
class StubCryptoServiceImplTest
{
    private StubCryptoServiceImpl cryptoService;

    @BeforeEach
    void setUp()
    {
        if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null)
        {
            Security.addProvider(new BouncyCastleProvider());
        }
        CryptoProperties properties = new CryptoProperties();
        CryptoProperties.Hsm hsm = properties.getHsm();
        hsm.setProvider("stub");
        hsm.setHosts(Collections.singletonList("127.0.0.1:8008"));
        cryptoService = new StubCryptoServiceImpl(properties);
    }

    @Test
    @DisplayName("SM3-HMAC 可重复计算")
    void hmacSm3DeterministicForSameInput()
    {
        byte[] plain = "payload".getBytes(StandardCharsets.UTF_8);
        String first = cryptoService.hmacSm3(plain, CryptoDataType.CREDENTIAL);
        String second = cryptoService.hmacSm3(plain, CryptoDataType.CREDENTIAL);
        assertEquals(first, second);
    }

    @Test
    @DisplayName("SM4 加解密往返")
    void sm4RoundTrip()
    {
        String plain = "13800001111";
        String cipher = cryptoService.encryptSm4(plain, CryptoDataType.PERSONAL);
        assertNotEquals(plain, cipher);
        assertEquals(plain, cryptoService.decryptSm4(cipher, CryptoDataType.PERSONAL));
    }

    @Test
    @DisplayName("HMAC 校验")
    void verifyHmac()
    {
        byte[] plain = "admin".getBytes(StandardCharsets.UTF_8);
        String hmac = cryptoService.hmacSm3(plain, CryptoDataType.PERMISSION);
        assertTrue(cryptoService.verifyHmac(plain, hmac, CryptoDataType.PERMISSION));
    }
}
