package io.trustbuilder.mfa.android.demoapp.security;

import static androidx.constraintlayout.helper.widget.MotionEffect.TAG;

import android.os.Build;
import android.security.keystore.KeyGenParameterSpec;
import android.security.keystore.KeyProperties;
import android.util.Log;

import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.UnrecoverableEntryException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;

import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;

public class KeystoreService {

    public KeyPair generateKeys(String keystoreAlias, boolean useStrongBox) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException {
        KeyPairGenerator generator = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_RSA, "AndroidKeyStore");
        KeyGenParameterSpec.Builder builder = new KeyGenParameterSpec
                .Builder(keystoreAlias, KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY);
        builder.setUserAuthenticationRequired(true);
        builder.setInvalidatedByBiometricEnrollment(true);
        builder.setKeySize(2048);
        builder.setDigests(KeyProperties.DIGEST_SHA256);
        builder.setSignaturePaddings(KeyProperties.SIGNATURE_PADDING_RSA_PSS);
        builder.setUserAuthenticationRequired(true);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && useStrongBox) {
            Log.d(TAG, "generateRsaKeyForBio: strong?");
            builder.setIsStrongBoxBacked(true);
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            Log.d(TAG, "generateRsaKeyForBio: Code R");
            builder.setUserAuthenticationParameters(10, KeyProperties.AUTH_BIOMETRIC_STRONG);
        }
        KeyGenParameterSpec spec = builder.build();
        generator.initialize(spec);
        return generator.generateKeyPair();

    }

    public SecretKey getKey(String clientId, String keyStoreName) throws KeyStoreException, UnrecoverableKeyException, NoSuchAlgorithmException, CertificateException, IOException {
        KeyStore keyStore = KeyStore.getInstance(keyStoreName);
        keyStore.load(null);
        return (SecretKey) keyStore.getKey(clientId, null);
    }

    public void deleteEntry(String clientId, String keyStoreName) throws KeyStoreException {
        KeyStore keyStore = KeyStore.getInstance(keyStoreName);
        keyStore.deleteEntry(clientId);
    }

    public SecretKey generateKey(String keyStoreName, String clientId) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException, KeyStoreException, CertificateException, IOException {
        KeyStore keyStore = KeyStore.getInstance(keyStoreName);
        KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, keyStoreName);
        keyStore.load(null);
        keyGenerator.init(new KeyGenParameterSpec.Builder(clientId,
                KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT).setBlockModes(
                        KeyProperties.BLOCK_MODE_CBC)
                .setUserAuthenticationRequired(true)
                .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
                .build());
        return keyGenerator.generateKey();
    }

    public PrivateKey getPrivateKey(String keyStoreAlias) throws KeyStoreException, UnrecoverableEntryException, NoSuchAlgorithmException, CertificateException, IOException {
        KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
        keyStore.load(null);
        KeyStore.Entry entry = keyStore.getEntry(keyStoreAlias, null);
        return ((KeyStore.PrivateKeyEntry)entry).getPrivateKey();
    }
}
