package com.takensoft.pohangTp.common.util;


import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Base64.Decoder;
import java.util.Base64.Encoder;
import java.util.HashMap;
import java.util.Map;

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.encrypt.AesBytesEncryptor;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.DelegatingPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

/**
 * @author 김성원
 * @since 2024.01.02
 * 
 * 암호화 관련 클래스 
 */
public class CryptoUtil {
	

	private final static String encoderKey = "bcrypt";
	private final static String secret = "takenbmsc!@#";
	private final static String salt = "70726574657374";
	
	/**
	 * @author 김성원
	 * @since 2024.01.09
	 * 
	 * 기본 단방향 엔코드 생성
	 */
	public static PasswordEncoder createDelegatingPasswordEncoder() {	
		Map<String, PasswordEncoder> encoders = new HashMap<>();
		encoders.put(encoderKey, new BCryptPasswordEncoder());	
		return new DelegatingPasswordEncoder(encoderKey, encoders);
	}
	
	/**
	 * @author 김성원
	 * @since 2024.01.09
	 * 
	 * 커스텀 key기반의  단방향 엔코드 생성
	 */
	public static PasswordEncoder createDelegatingPasswordEncoder(String key) {	
		Map<String, PasswordEncoder> encoders = new HashMap<>();
		encoders.put(key, new BCryptPasswordEncoder());	
		return new DelegatingPasswordEncoder(key, encoders);
	}
	
	
	/**
	 * @author 김성원
	 * @since 2024.01.09
	 * 
	 * 기본 단방향 암호화 
	 */
	public static String PasswordEncoder(String data) {	
		
		PasswordEncoder passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
		Encoder encoder = Base64.getEncoder();       
		return  encoder.encodeToString(passwordEncoder.encode(data).getBytes(StandardCharsets.UTF_8)) ;
	}
	
	/**
	 * @author 김성원
	 * @since 2024.01.09
	 * 
	 * 커스텀 key기반의  단방향 암호화 
	 */
	public static String PasswordEncoder(String key , String data) {	
		
		if(StringUtil.isEmpty(data)) {
			return data;
		}
		
		PasswordEncoder passwordEncoder = createDelegatingPasswordEncoder(key);
		
		return passwordEncoder.encode(data);
	}
		
	
	
	/**
	 * @author 김성원
	 * @since 2024.01.09
	 * 
	 * 단방향 암호화 비교구문 
	 */
	public static boolean passwordMatch(String data, String checkData) {
		
		PasswordEncoder passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
		Decoder decoder = Base64.getDecoder();		
		return passwordEncoder.matches(data,new String(decoder.decode(checkData), StandardCharsets.UTF_8) );
		
	}
	

	/**
	 * @author 김성원
	 * @since 2024.01.09
	 * 
	 * 기본 key, salt 기반의 양방향 암호화 객체 생성  
	 */
	public static AesBytesEncryptor aesBytesEncryptor() {
	    return new AesBytesEncryptor("232323", salt);
	}
	
	/**
	 * @author 김성원
	 * @since 2024.01.09
	 * 
	 * 커스텀 key, salt 기반의 양방향 암호화 객체 생성  
	 */
	public static AesBytesEncryptor aesBytesEncryptor(String key, String salt) {
	    return new AesBytesEncryptor(key, salt);
	    
	}	
	
	/**
	 * @author 김성원
	 * @since 2024.01.09
	 * 
	 * 기본 key, salt 기반의 양방향 암호화 
	 */
	public static String encryptData(String data) {
		if(StringUtil.isEmpty(data)) {
			return data;
		}
		AesBytesEncryptor  bytesEncryptor =  aesBytesEncryptor();
        byte[] encrypt = bytesEncryptor.encrypt(data.getBytes(StandardCharsets.UTF_8));
        Encoder encoder = Base64.getEncoder();       
        return encoder.encodeToString(encrypt); 
    }
	
	/**
	 * @author 김성원
	 * @since 2024.01.09
	 * 
	 * 커스텀  key, salt 기반의 양방향 암호화 
	 */
	public static String encryptData(String key, String salt, String data) {
		if(StringUtil.isEmpty(data)) {
			return data;
		}
		AesBytesEncryptor  bytesEncryptor =  aesBytesEncryptor(key, salt);
        byte[] encrypt = bytesEncryptor.encrypt(data.getBytes(StandardCharsets.UTF_8));
        Encoder encoder = Base64.getEncoder();       
        return encoder.encodeToString(encrypt); 
    }
	
	
	
	/**
	 * @author 김성원
	 * @since 2024.01.09
	 * 
	 * 기본 key, salt 기반의 양방향 복호화
	 */
	public static String decryptData(String data) {
		if(StringUtil.isEmpty(data)) {
			return data;
		}
		AesBytesEncryptor  bytesEncryptor =  aesBytesEncryptor();
		Decoder decoder = Base64.getDecoder();		
        byte[] decrypt = bytesEncryptor.decrypt(decoder.decode(data));
        return new String(decrypt, StandardCharsets.UTF_8);
    }	
	
	/**
	 * @author 김성원
	 * @since 2024.01.09
	 * 
	 * 커스텀 key, salt 기반의 양방향 복호화
	 */
	public static String decryptData(String key, String salt, String data) {
		if(StringUtil.isEmpty(data)) {
			return data;
		}
		AesBytesEncryptor  bytesEncryptor =  aesBytesEncryptor(key, salt);
		Decoder decoder = Base64.getDecoder();		
        byte[] decrypt = bytesEncryptor.decrypt(decoder.decode(data));
        return new String(decrypt, StandardCharsets.UTF_8);
    }	
	
	 
	/**
	 * @author 김성원
	 * @since 2024.01.09
	 * 
	 * 	* 바이트 스트링 변환
	*/
	public static String byteArrayToString(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte abyte :bytes){
            sb.append(abyte);
            sb.append(" ");
        }
        return sb.toString();
    }
	
	/**
	 * @author 김성원
	 * @since 2024.01.09
	 * 
	 * 스트링 바이트 변환
	*/
	public static byte[] stringToByteArray(String byteString) {
        String[] split = byteString.split("\\s");
        ByteBuffer buffer = ByteBuffer.allocate(split.length);
        for (String s : split) {
            buffer.put((byte) Integer.parseInt(s));
        }
        return buffer.array();
    }
	
}
