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

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.when;

import android.security.keystore.StrongBoxUnavailableException;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;

import java.security.InvalidAlgorithmParameterException;
import java.security.KeyPair;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;

import io.trustbuilder.mfa.android.demoapp.security.CryptoUtils;
import io.trustbuilder.mfa.android.demoapp.security.KeystoreService;

@RunWith(RobolectricTestRunner.class)
public class CryptoUtilsTest {
    @Test
    public void onGenerateRsaKeyForBio_shouldSuccess() {
        try {
            KeystoreService keystoreService = mock(KeystoreService.class);
            PrivateKey privateKey = mock(PrivateKey.class);
            PublicKey publicKey = mock(PublicKey.class);
            when(publicKey.getEncoded()).thenReturn("pubKey".getBytes());
            KeyPair fakeKeyPair = new KeyPair(publicKey, privateKey);
            when(keystoreService.generateKeys(any(), anyBoolean())).thenReturn(fakeKeyPair);
            byte[] key = CryptoUtils.generateRsaKeyForBio("alias", keystoreService);
            Assert.assertNotNull(key);
        } catch (NoSuchAlgorithmException | NoSuchProviderException |
                 InvalidAlgorithmParameterException e) {
            throw new RuntimeException(e);
        }
    }

    @Test
    public void onGenerateRsaKeyForBio_shouldSuccessWithStrongBoxException() {
        try {
            KeystoreService keystoreService = mock(KeystoreService.class);
            PrivateKey privateKey = mock(PrivateKey.class);
            PublicKey publicKey = mock(PublicKey.class);
            when(publicKey.getEncoded()).thenReturn("pubKey".getBytes());
            KeyPair fakeKeyPair = new KeyPair(publicKey, privateKey);
            when(keystoreService.generateKeys("alias", true)).thenThrow(new StrongBoxUnavailableException());
            when(keystoreService.generateKeys("alias", false)).thenReturn(fakeKeyPair);
            byte[] key = CryptoUtils.generateRsaKeyForBio("alias", keystoreService);
            Assert.assertNotNull(key);
        } catch (NoSuchAlgorithmException | NoSuchProviderException |
                 InvalidAlgorithmParameterException e) {
            throw new RuntimeException(e);
        }
    }

    @Test
    public void onGenerateRsaKeyForBioForOldAndroid_shouldSuccess() {
        try {
            KeystoreService keystoreService = mock(KeystoreService.class);
            PrivateKey privateKey = mock(PrivateKey.class);
            PublicKey publicKey = mock(PublicKey.class);
            when(publicKey.getEncoded()).thenReturn("pubKey".getBytes());
            KeyPair fakeKeyPair = new KeyPair(publicKey, privateKey);
            when(keystoreService.generateKeys(any(), anyBoolean())).thenReturn(fakeKeyPair);
            byte[] key = CryptoUtils.generateRsaKeyForBioForOldAndroid("alias", keystoreService);
            Assert.assertNotNull(key);
        } catch (NoSuchAlgorithmException | NoSuchProviderException |
                 InvalidAlgorithmParameterException e) {
            throw new RuntimeException(e);
        }
    }
}
