package com.kospo.talk.config.utils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.util.FileCopyUtils;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.RSAKeyGenParameterSpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

public class CryptoUtil {

    public static String encrypt(String plainText) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, loadPublicKey());
        byte[] encryptedBytes = cipher.doFinal(plainText.getBytes());
        return Base64.getEncoder().encodeToString(encryptedBytes);
    }

    public static String decrypt(String encryptText) throws Exception {
        encryptText = encryptText.replaceAll(" ", "+");
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, loadPrivateKey());
        byte[] decryptBytes = cipher.doFinal(Base64.getDecoder().decode(encryptText));
        return new String(decryptBytes);
    }

    private static PublicKey loadPublicKey() throws NoSuchAlgorithmException, InvalidKeySpecException, IOException {
        ClassPathResource resource = new ClassPathResource("public.key");
        byte[] keyBytes = FileCopyUtils.copyToByteArray(resource.getInputStream());
        X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePublic(spec);
    }

    private static PrivateKey loadPrivateKey() throws NoSuchAlgorithmException, InvalidKeySpecException, IOException {
        ClassPathResource resource = new ClassPathResource("private.key");
        byte[] keyBytes = FileCopyUtils.copyToByteArray(resource.getInputStream());
        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePrivate(spec);
    }

    private static byte[] readKeyFromFile(String fileName) {
        File file = new File(fileName);
        byte[] keyBytes = new byte[(int) file.length()];
        try(FileInputStream fis = new FileInputStream(file)) {
            fis.read(keyBytes);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        return keyBytes;
    }

    private static void saveKeyToFile(String fileName, byte[] keyBytes) {
        File file = new File(fileName);
        try(FileOutputStream fos = new FileOutputStream(file)) {
            fos.write(keyBytes);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) {
//            System.out.println(encrypt("psn14020"));
//            KeyPairGenerator keygen = KeyPairGenerator.getInstance("RSA");
//            keygen.initialize(new RSAKeyGenParameterSpec(2048, RSAKeyGenParameterSpec.F4));
//            KeyPair pair = keygen.generateKeyPair();
//
//            saveKeyToFile("C:\\Users\\psn14020\\IdeaProjects\\talk\\src\\main\\resources\\private.key", pair.getPrivate().getEncoded());
//            saveKeyToFile("C:\\Users\\psn14020\\IdeaProjects\\talk\\src\\main\\resources\\public.key", pair.getPublic().getEncoded());
    }
}
