package com.eactive.eai.manage.crypto;

import java.util.Base64;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import org.springframework.stereotype.Service;

import com.eactive.eai.common.security.CryptoModuleDiagnosticDTO;
import com.eactive.eai.common.security.CryptoModuleExtension;
import com.eactive.eai.common.security.CryptoModuleManager;

/**
 * CryptoModuleManager 진단 및 암복호화 테스트를 위임하는 서비스.
 *
 * createExtension(cryptoName, runtimeContext) 는 STATIC 키 방식인 경우 내부에서
 * createExtension(cryptoName) 으로 위임하므로, 테스트 시 runtimeContext 유무와 무관하게
 * 동일 메서드를 사용한다.
 */
@Service
public class CryptoModuleManageService {

	public List<CryptoModuleDiagnosticDTO> listAll() {
		return CryptoModuleManager.getInstance().describeAll();
	}

	public CryptoModuleDiagnosticDTO get(String cryptoName) {
		return CryptoModuleManager.getInstance().describe(cryptoName);
	}

	public List<String> listDynamicCacheKeys() {
		return CryptoModuleManager.getInstance().listDynamicCacheKeys();
	}

	public String testEncrypt(String cryptoName, Map<String, String> runtimeContext,
			String plainTextBase64, String aadBase64) throws Exception {
		byte[] plain = Base64.getDecoder().decode(plainTextBase64);
		CryptoModuleExtension ext = CryptoModuleManager.getInstance()
				.createExtension(cryptoName, runtimeContext(runtimeContext));
		byte[] cipher = aadBase64 != null
				? ext.encrypt(plain, Base64.getDecoder().decode(aadBase64))
				: ext.encrypt(plain);
		return Base64.getEncoder().encodeToString(cipher);
	}

	public String testDecrypt(String cryptoName, Map<String, String> runtimeContext,
			String cipherTextBase64, String aadBase64) throws Exception {
		byte[] cipherBytes = Base64.getDecoder().decode(cipherTextBase64);
		CryptoModuleExtension ext = CryptoModuleManager.getInstance()
				.createExtension(cryptoName, runtimeContext(runtimeContext));
		byte[] plain = aadBase64 != null
				? ext.decrypt(cipherBytes, Base64.getDecoder().decode(aadBase64))
				: ext.decrypt(cipherBytes);
		return Base64.getEncoder().encodeToString(plain);
	}

	private Map<String, String> runtimeContext(Map<String, String> runtimeContext) {
		return runtimeContext != null ? runtimeContext : Collections.emptyMap();
	}
}
