//package com.eactive.eai.common.security.keyderiv;
//
//import static org.junit.jupiter.api.Assertions.*;
//import static org.mockito.Mockito.*;
//
//import java.nio.charset.StandardCharsets;
//import java.security.MessageDigest;
//import java.util.HashMap;
//import java.util.Map;
//
//import javax.crypto.SecretKey;
//import javax.crypto.spec.SecretKeySpec;
//
//import org.junit.jupiter.api.BeforeAll;
//import org.junit.jupiter.api.BeforeEach;
//import org.junit.jupiter.api.DisplayName;
//import org.junit.jupiter.api.MethodOrderer;
//import org.junit.jupiter.api.Test;
//import org.junit.jupiter.api.TestMethodOrder;
//import org.springframework.beans.factory.support.BeanDefinitionBuilder;
//import org.springframework.context.support.GenericApplicationContext;
//
//import com.eactive.eai.common.hsm.HsmCryptoService;
//import com.eactive.eai.common.security.keyderiv.DerivedKey;
//import com.eactive.eai.common.security.keyderiv.strategy.HsmContextSha256KeyDerivationStrategy;
//import com.eactive.eai.common.util.ApplicationContextProvider;
//
///**
// * HsmContextSha256KeyDerivationStrategy 단위 테스트
// */
//@TestMethodOrder(MethodOrderer.DisplayName.class)
//class HsmContextSha256KeyDerivationStrategyTest {
//
//    private static final String HSM_KEY_ALIAS = "MASTER_KEY_AES";
//    private static final byte[] MASTER_KEY    = "0123456789abcdef".getBytes(StandardCharsets.UTF_8);
//
//    private static GenericApplicationContext              ctx;
//    private static HsmCryptoService                      mockHsmCryptoService;
//    private static HsmContextSha256KeyDerivationStrategy strategy;
//
//    private Map<String, String> params;
//    private Map<String, String> runtimeContext;
//
//    @BeforeAll
//    static void setUpClass() throws Exception {
//        mockHsmCryptoService = mock(HsmCryptoService.class);
//        SecretKey mockSecretKey = new SecretKeySpec(MASTER_KEY, "AES");
//        when(mockHsmCryptoService.getSecretKey(HSM_KEY_ALIAS)).thenReturn(mockSecretKey);
//
//        ctx = new GenericApplicationContext();
//        ctx.getBeanFactory().registerSingleton("hsmCryptoService", mockHsmCryptoService);
//        ctx.registerBeanDefinition("applicationContextProvider",
//                BeanDefinitionBuilder.genericBeanDefinition(ApplicationContextProvider.class)
//                        .getBeanDefinition());
//        ctx.refresh();
//
//        strategy = new HsmContextSha256KeyDerivationStrategy();
//    }
//
//    @BeforeEach
//    void setUpParams() {
//        params = new HashMap<>();
//        params.put("hsmKeyAlias", HSM_KEY_ALIAS);
//        params.put("contextKey",  "X-Api-Group-Seq");
//
//        runtimeContext = new HashMap<>();
//        runtimeContext.put("X-Api-Group-Seq", "GROUP_001");
//    }
//
//    // =========================================================================
//    // 1. deriveKey
//    // =========================================================================
//
//    @Test
//    @DisplayName("1-1. 정상 파라미터 — DerivedKey 반환, 길이 32바이트(SHA-256 고정 출력)")
//    void testDeriveKey_validParams_returns32ByteKey() throws Exception {
//        DerivedKey dk = strategy.deriveKey(params, runtimeContext);
//
//        assertNotNull(dk);
//        assertNotNull(dk.getEncKey());
//        assertNotNull(dk.getDecKey());
//        assertEquals(32, dk.getEncKey().length, "SHA-256 출력은 항상 32바이트여야 한다");
//    }
//
//    @Test
//    @DisplayName("1-2. SHA-256(masterKey || contextValue) 계산 결과 검증")
//    void testDeriveKey_sha256ResultIsCorrect() throws Exception {
//        DerivedKey dk = strategy.deriveKey(params, runtimeContext);
//
//        byte[] contextBytes = "GROUP_001".getBytes(StandardCharsets.UTF_8);
//        byte[] combined = new byte[MASTER_KEY.length + contextBytes.length];
//        System.arraycopy(MASTER_KEY,    0, combined, 0,               MASTER_KEY.length);
//        System.arraycopy(contextBytes,  0, combined, MASTER_KEY.length, contextBytes.length);
//        byte[] expected = MessageDigest.getInstance("SHA-256").digest(combined);
//
//        assertArrayEquals(expected, dk.getEncKey(), "SHA-256 해싱 결과가 일치해야 한다");
//    }
//
//    @Test
//    @DisplayName("1-3. 대칭 알고리즘 — encKey == decKey")
//    void testDeriveKey_encKeyEqualsDecKey() throws Exception {
//        DerivedKey dk = strategy.deriveKey(params, runtimeContext);
//
//        assertArrayEquals(dk.getEncKey(), dk.getDecKey(), "대칭 방식이므로 encKey와 decKey가 동일해야 한다");
//    }
//
//    @Test
//    @DisplayName("1-4. runtimeContext 값 없음 — 빈 문자열로 처리")
//    void testDeriveKey_missingContextValue_emptyStringUsed() throws Exception {
//        runtimeContext.remove("X-Api-Group-Seq");
//        DerivedKey dk = strategy.deriveKey(params, runtimeContext);
//
//        byte[] expected = MessageDigest.getInstance("SHA-256").digest(MASTER_KEY);
//
//        assertArrayEquals(expected, dk.getEncKey(), "컨텍스트 값 없으면 masterKey만 해싱해야 한다");
//    }
//
//    @Test
//    @DisplayName("1-5. 다른 runtimeContext 값 — 다른 DerivedKey 생성")
//    void testDeriveKey_differentContextValue_differentKey() throws Exception {
//        DerivedKey dk1 = strategy.deriveKey(params, runtimeContext);
//
//        runtimeContext.put("X-Api-Group-Seq", "GROUP_002");
//        DerivedKey dk2 = strategy.deriveKey(params, runtimeContext);
//
//        assertFalse(java.util.Arrays.equals(dk1.getEncKey(), dk2.getEncKey()),
//                "컨텍스트 값이 다르면 도출된 키도 달라야 한다");
//    }
//
//    @Test
//    @DisplayName("1-6. 필수 파라미터 누락(hsmKeyAlias) — IllegalArgumentException")
//    void testDeriveKey_missingHsmKeyAlias_throwsException() {
//        params.remove("hsmKeyAlias");
//
//        assertThrows(IllegalArgumentException.class,
//                () -> strategy.deriveKey(params, runtimeContext),
//                "hsmKeyAlias 누락 시 IllegalArgumentException이 발생해야 한다");
//    }
//
//    @Test
//    @DisplayName("1-7. 필수 파라미터 누락(contextKey) — IllegalArgumentException")
//    void testDeriveKey_missingContextKey_throwsException() {
//        params.remove("contextKey");
//
//        assertThrows(IllegalArgumentException.class,
//                () -> strategy.deriveKey(params, runtimeContext),
//                "contextKey 누락 시 IllegalArgumentException이 발생해야 한다");
//    }
//
//    // =========================================================================
//    // 2. buildCacheKey
//    // =========================================================================
//
//    @Test
//    @DisplayName("2-1. buildCacheKey — cryptoName:contextValue 형식")
//    void testBuildCacheKey_format() {
//        String cacheKey = strategy.buildCacheKey("CRYPTO_A", params, runtimeContext);
//
//        assertEquals("CRYPTO_A:GROUP_001", cacheKey);
//    }
//
//    @Test
//    @DisplayName("2-2. buildCacheKey — contextKey 값 없으면 빈 문자열")
//    void testBuildCacheKey_missingContextValue_emptyString() {
//        runtimeContext.remove("X-Api-Group-Seq");
//        String cacheKey = strategy.buildCacheKey("CRYPTO_A", params, runtimeContext);
//
//        assertEquals("CRYPTO_A:", cacheKey);
//    }
//
//    @Test
//    @DisplayName("2-3. buildCacheKey — 다른 cryptoName은 다른 캐시 키")
//    void testBuildCacheKey_differentCryptoName_differentKey() {
//        String key1 = strategy.buildCacheKey("CRYPTO_A", params, runtimeContext);
//        String key2 = strategy.buildCacheKey("CRYPTO_B", params, runtimeContext);
//
//        assertNotEquals(key1, key2);
//    }
//}
