// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package io.flutter.plugins.localauth;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.app.Activity;
import android.app.KeyguardManager;
import android.app.NativeActivity;
import android.content.Context;
import androidx.biometric.BiometricManager;
import androidx.fragment.app.FragmentActivity;
import androidx.lifecycle.Lifecycle;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.engine.dart.DartExecutor;
import io.flutter.embedding.engine.plugins.FlutterPlugin.FlutterPluginBinding;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
import io.flutter.embedding.engine.plugins.lifecycle.HiddenLifecycleReference;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugins.localauth.AuthenticationHelper.AuthCompletionHandler;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;

@RunWith(RobolectricTestRunner.class)
public class LocalAuthTest {
  @Test
  public void authenticate_returnsErrorWhenAuthInProgress() {
    final LocalAuthPlugin plugin = new LocalAuthPlugin();
    plugin.authInProgress.set(true);
    final MethodChannel.Result mockResult = mock(MethodChannel.Result.class);
    plugin.onMethodCall(new MethodCall("authenticate", null), mockResult);
    verify(mockResult).error("auth_in_progress", "Authentication in progress", null);
  }

  @Test
  public void authenticate_returnsErrorWithNoForegroundActivity() {
    final LocalAuthPlugin plugin = new LocalAuthPlugin();
    final MethodChannel.Result mockResult = mock(MethodChannel.Result.class);
    plugin.onMethodCall(new MethodCall("authenticate", null), mockResult);
    verify(mockResult)
        .error("no_activity", "local_auth plugin requires a foreground activity", null);
  }

  @Test
  public void authenticate_returnsErrorWhenActivityNotFragmentActivity() {
    final LocalAuthPlugin plugin = new LocalAuthPlugin();
    setPluginActivity(plugin, buildMockActivityWithContext(mock(NativeActivity.class)));
    final MethodChannel.Result mockResult = mock(MethodChannel.Result.class);
    plugin.onMethodCall(new MethodCall("authenticate", null), mockResult);
    verify(mockResult)
        .error(
            "no_fragment_activity",
            "local_auth plugin requires activity to be a FragmentActivity.",
            null);
  }

  @Test
  public void authenticate_returnsErrorWhenDeviceNotSupported() {
    final LocalAuthPlugin plugin = new LocalAuthPlugin();
    final MethodChannel.Result mockResult = mock(MethodChannel.Result.class);
    setPluginActivity(plugin, buildMockActivityWithContext(mock(FragmentActivity.class)));
    plugin.onMethodCall(new MethodCall("authenticate", null), mockResult);
    assertFalse(plugin.authInProgress.get());
    verify(mockResult).error("NotAvailable", "Required security features not enabled", null);
  }

  @Test
  public void authenticate_properlyConfiguresBiometricOnlyAuthenticationRequest() {
    final LocalAuthPlugin plugin = spy(new LocalAuthPlugin());
    setPluginActivity(plugin, buildMockActivityWithContext(mock(FragmentActivity.class)));
    when(plugin.isDeviceSupported()).thenReturn(true);

    final BiometricManager mockBiometricManager = mock(BiometricManager.class);
    when(mockBiometricManager.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_WEAK))
        .thenReturn(BiometricManager.BIOMETRIC_SUCCESS);
    when(mockBiometricManager.canAuthenticate(BiometricManager.Authenticators.DEVICE_CREDENTIAL))
        .thenReturn(BiometricManager.BIOMETRIC_SUCCESS);
    plugin.setBiometricManager(mockBiometricManager);

    ArgumentCaptor<Boolean> allowCredentialsCaptor = ArgumentCaptor.forClass(Boolean.class);
    doNothing()
        .when(plugin)
        .sendAuthenticationRequest(
            any(MethodCall.class),
            any(AuthCompletionHandler.class),
            allowCredentialsCaptor.capture());
    final MethodChannel.Result mockResult = mock(MethodChannel.Result.class);
    HashMap<String, Object> arguments = new HashMap<>();
    arguments.put("biometricOnly", true);

    plugin.onMethodCall(new MethodCall("authenticate", arguments), mockResult);
    assertFalse(allowCredentialsCaptor.getValue());
  }

  @Test
  @Config(sdk = 30)
  public void authenticate_properlyConfiguresBiometricAndDeviceCredentialAuthenticationRequest() {
    final LocalAuthPlugin plugin = spy(new LocalAuthPlugin());
    setPluginActivity(plugin, buildMockActivityWithContext(mock(FragmentActivity.class)));
    when(plugin.isDeviceSupported()).thenReturn(true);

    final BiometricManager mockBiometricManager = mock(BiometricManager.class);
    when(mockBiometricManager.canAuthenticate(BiometricManager.Authenticators.DEVICE_CREDENTIAL))
        .thenReturn(BiometricManager.BIOMETRIC_SUCCESS);
    plugin.setBiometricManager(mockBiometricManager);

    ArgumentCaptor<Boolean> allowCredentialsCaptor = ArgumentCaptor.forClass(Boolean.class);
    doNothing()
        .when(plugin)
        .sendAuthenticationRequest(
            any(MethodCall.class),
            any(AuthCompletionHandler.class),
            allowCredentialsCaptor.capture());
    final MethodChannel.Result mockResult = mock(MethodChannel.Result.class);
    HashMap<String, Object> arguments = new HashMap<>();
    arguments.put("biometricOnly", false);

    plugin.onMethodCall(new MethodCall("authenticate", arguments), mockResult);
    assertTrue(allowCredentialsCaptor.getValue());
  }

  @Test
  @Config(sdk = 30)
  public void authenticate_properlyConfiguresDeviceCredentialOnlyAuthenticationRequest() {
    final LocalAuthPlugin plugin = spy(new LocalAuthPlugin());
    setPluginActivity(plugin, buildMockActivityWithContext(mock(FragmentActivity.class)));
    when(plugin.isDeviceSupported()).thenReturn(true);

    final BiometricManager mockBiometricManager = mock(BiometricManager.class);
    when(mockBiometricManager.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_WEAK))
        .thenReturn(BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED);
    when(mockBiometricManager.canAuthenticate(BiometricManager.Authenticators.DEVICE_CREDENTIAL))
        .thenReturn(BiometricManager.BIOMETRIC_SUCCESS);
    plugin.setBiometricManager(mockBiometricManager);

    ArgumentCaptor<Boolean> allowCredentialsCaptor = ArgumentCaptor.forClass(Boolean.class);
    doNothing()
        .when(plugin)
        .sendAuthenticationRequest(
            any(MethodCall.class),
            any(AuthCompletionHandler.class),
            allowCredentialsCaptor.capture());
    final MethodChannel.Result mockResult = mock(MethodChannel.Result.class);
    HashMap<String, Object> arguments = new HashMap<>();
    arguments.put("biometricOnly", false);

    plugin.onMethodCall(new MethodCall("authenticate", arguments), mockResult);
    assertTrue(allowCredentialsCaptor.getValue());
  }

  @Test
  public void isDeviceSupportedReturnsFalse() {
    final LocalAuthPlugin plugin = new LocalAuthPlugin();
    final MethodChannel.Result mockResult = mock(MethodChannel.Result.class);
    plugin.onMethodCall(new MethodCall("isDeviceSupported", null), mockResult);
    verify(mockResult).success(false);
  }

  @Test
  public void deviceSupportsBiometrics_returnsTrueForPresentNonEnrolledBiometrics() {
    final LocalAuthPlugin plugin = new LocalAuthPlugin();
    final MethodChannel.Result mockResult = mock(MethodChannel.Result.class);
    final BiometricManager mockBiometricManager = mock(BiometricManager.class);
    when(mockBiometricManager.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_WEAK))
        .thenReturn(BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED);
    plugin.setBiometricManager(mockBiometricManager);
    plugin.onMethodCall(new MethodCall("deviceSupportsBiometrics", null), mockResult);
    verify(mockResult).success(true);
  }

  @Test
  public void deviceSupportsBiometrics_returnsTrueForPresentEnrolledBiometrics() {
    final LocalAuthPlugin plugin = new LocalAuthPlugin();
    final MethodChannel.Result mockResult = mock(MethodChannel.Result.class);
    final BiometricManager mockBiometricManager = mock(BiometricManager.class);
    when(mockBiometricManager.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_WEAK))
        .thenReturn(BiometricManager.BIOMETRIC_SUCCESS);
    plugin.setBiometricManager(mockBiometricManager);
    plugin.onMethodCall(new MethodCall("deviceSupportsBiometrics", null), mockResult);
    verify(mockResult).success(true);
  }

  @Test
  public void deviceSupportsBiometrics_returnsFalseForNoBiometricHardware() {
    final LocalAuthPlugin plugin = new LocalAuthPlugin();
    final MethodChannel.Result mockResult = mock(MethodChannel.Result.class);
    final BiometricManager mockBiometricManager = mock(BiometricManager.class);
    when(mockBiometricManager.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_WEAK))
        .thenReturn(BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE);
    plugin.setBiometricManager(mockBiometricManager);
    plugin.onMethodCall(new MethodCall("deviceSupportsBiometrics", null), mockResult);
    verify(mockResult).success(false);
  }

  @Test
  public void deviceSupportsBiometrics_returnsFalseForNullBiometricManager() {
    final LocalAuthPlugin plugin = new LocalAuthPlugin();
    final MethodChannel.Result mockResult = mock(MethodChannel.Result.class);
    plugin.setBiometricManager(null);
    plugin.onMethodCall(new MethodCall("deviceSupportsBiometrics", null), mockResult);
    verify(mockResult).success(false);
  }

  @Test
  public void onDetachedFromActivity_ShouldReleaseActivity() {
    final Activity mockActivity = mock(Activity.class);
    final ActivityPluginBinding mockActivityBinding = mock(ActivityPluginBinding.class);
    when(mockActivityBinding.getActivity()).thenReturn(mockActivity);

    Context mockContext = mock(Context.class);
    when(mockActivity.getBaseContext()).thenReturn(mockContext);
    when(mockActivity.getApplicationContext()).thenReturn(mockContext);

    final HiddenLifecycleReference mockLifecycleReference = mock(HiddenLifecycleReference.class);
    when(mockActivityBinding.getLifecycle()).thenReturn(mockLifecycleReference);

    final Lifecycle mockLifecycle = mock(Lifecycle.class);
    when(mockLifecycleReference.getLifecycle()).thenReturn(mockLifecycle);

    final FlutterPluginBinding mockPluginBinding = mock(FlutterPluginBinding.class);
    final FlutterEngine mockFlutterEngine = mock(FlutterEngine.class);
    when(mockPluginBinding.getFlutterEngine()).thenReturn(mockFlutterEngine);

    DartExecutor mockDartExecutor = mock(DartExecutor.class);
    when(mockFlutterEngine.getDartExecutor()).thenReturn(mockDartExecutor);

    final LocalAuthPlugin plugin = new LocalAuthPlugin();
    plugin.onAttachedToEngine(mockPluginBinding);
    plugin.onAttachedToActivity(mockActivityBinding);
    assertNotNull(plugin.getActivity());

    plugin.onDetachedFromActivity();
    assertNull(plugin.getActivity());
  }

  @Test
  public void getEnrolledBiometrics_shouldReturnError_whenNoActivity() {
    final LocalAuthPlugin plugin = new LocalAuthPlugin();
    final MethodChannel.Result mockResult = mock(MethodChannel.Result.class);

    plugin.onMethodCall(new MethodCall("getEnrolledBiometrics", null), mockResult);
    verify(mockResult)
        .error("no_activity", "local_auth plugin requires a foreground activity", null);
  }

  @Test
  public void getEnrolledBiometrics_shouldReturnError_whenFinishingActivity() {
    final LocalAuthPlugin plugin = new LocalAuthPlugin();
    final MethodChannel.Result mockResult = mock(MethodChannel.Result.class);
    final Activity mockActivity = buildMockActivityWithContext(mock(Activity.class));
    when(mockActivity.isFinishing()).thenReturn(true);
    setPluginActivity(plugin, mockActivity);

    plugin.onMethodCall(new MethodCall("getEnrolledBiometrics", null), mockResult);
    verify(mockResult)
        .error("no_activity", "local_auth plugin requires a foreground activity", null);
  }

  @Test
  public void getEnrolledBiometrics_shouldReturnEmptyList_withoutHardwarePresent() {
    final LocalAuthPlugin plugin = new LocalAuthPlugin();
    setPluginActivity(plugin, buildMockActivityWithContext(mock(Activity.class)));
    final MethodChannel.Result mockResult = mock(MethodChannel.Result.class);
    final BiometricManager mockBiometricManager = mock(BiometricManager.class);
    when(mockBiometricManager.canAuthenticate(anyInt()))
        .thenReturn(BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE);
    plugin.setBiometricManager(mockBiometricManager);

    plugin.onMethodCall(new MethodCall("getEnrolledBiometrics", null), mockResult);
    verify(mockResult).success(Collections.emptyList());
  }

  @Test
  public void getEnrolledBiometrics_shouldReturnEmptyList_withNoMethodsEnrolled() {
    final LocalAuthPlugin plugin = new LocalAuthPlugin();
    setPluginActivity(plugin, buildMockActivityWithContext(mock(Activity.class)));
    final MethodChannel.Result mockResult = mock(MethodChannel.Result.class);
    final BiometricManager mockBiometricManager = mock(BiometricManager.class);
    when(mockBiometricManager.canAuthenticate(anyInt()))
        .thenReturn(BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED);
    plugin.setBiometricManager(mockBiometricManager);

    plugin.onMethodCall(new MethodCall("getEnrolledBiometrics", null), mockResult);
    verify(mockResult).success(Collections.emptyList());
  }

  @Test
  public void getEnrolledBiometrics_shouldOnlyAddEnrolledBiometrics() {
    final LocalAuthPlugin plugin = new LocalAuthPlugin();
    setPluginActivity(plugin, buildMockActivityWithContext(mock(Activity.class)));
    final MethodChannel.Result mockResult = mock(MethodChannel.Result.class);
    final BiometricManager mockBiometricManager = mock(BiometricManager.class);
    when(mockBiometricManager.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_WEAK))
        .thenReturn(BiometricManager.BIOMETRIC_SUCCESS);
    when(mockBiometricManager.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_STRONG))
        .thenReturn(BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED);
    plugin.setBiometricManager(mockBiometricManager);

    plugin.onMethodCall(new MethodCall("getEnrolledBiometrics", null), mockResult);
    verify(mockResult)
        .success(
            new ArrayList<String>() {
              {
                add("weak");
              }
            });
  }

  @Test
  public void getEnrolledBiometrics_shouldAddStrongBiometrics() {
    final LocalAuthPlugin plugin = new LocalAuthPlugin();
    setPluginActivity(plugin, buildMockActivityWithContext(mock(Activity.class)));
    final MethodChannel.Result mockResult = mock(MethodChannel.Result.class);
    final BiometricManager mockBiometricManager = mock(BiometricManager.class);
    when(mockBiometricManager.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_WEAK))
        .thenReturn(BiometricManager.BIOMETRIC_SUCCESS);
    when(mockBiometricManager.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_STRONG))
        .thenReturn(BiometricManager.BIOMETRIC_SUCCESS);
    plugin.setBiometricManager(mockBiometricManager);

    plugin.onMethodCall(new MethodCall("getEnrolledBiometrics", null), mockResult);
    verify(mockResult)
        .success(
            new ArrayList<String>() {
              {
                add("weak");
                add("strong");
              }
            });
  }

  @Test
  @Config(sdk = 22)
  public void isDeviceSecure_returnsFalseOnBelowApi23() {
    final LocalAuthPlugin plugin = new LocalAuthPlugin();
    assertFalse(plugin.isDeviceSecure());
  }

  @Test
  @Config(sdk = 23)
  public void isDeviceSecure_returnsTrueIfDeviceIsSecure() {
    final LocalAuthPlugin plugin = new LocalAuthPlugin();
    KeyguardManager mockKeyguardManager = mock(KeyguardManager.class);
    plugin.setKeyguardManager(mockKeyguardManager);

    when(mockKeyguardManager.isDeviceSecure()).thenReturn(true);
    assertTrue(plugin.isDeviceSecure());

    when(mockKeyguardManager.isDeviceSecure()).thenReturn(false);
    assertFalse(plugin.isDeviceSecure());
  }

  @Test
  @Config(sdk = 30)
  public void
      canAuthenticateWithDeviceCredential_returnsTrueIfHasBiometricManagerSupportAboveApi30() {
    final LocalAuthPlugin plugin = new LocalAuthPlugin();
    final BiometricManager mockBiometricManager = mock(BiometricManager.class);
    plugin.setBiometricManager(mockBiometricManager);

    when(mockBiometricManager.canAuthenticate(BiometricManager.Authenticators.DEVICE_CREDENTIAL))
        .thenReturn(BiometricManager.BIOMETRIC_SUCCESS);
    assertTrue(plugin.canAuthenticateWithDeviceCredential());

    when(mockBiometricManager.canAuthenticate(BiometricManager.Authenticators.DEVICE_CREDENTIAL))
        .thenReturn(BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED);
    assertFalse(plugin.canAuthenticateWithDeviceCredential());
  }

  private Activity buildMockActivityWithContext(Activity mockActivity) {
    final Context mockContext = mock(Context.class);
    when(mockActivity.getBaseContext()).thenReturn(mockContext);
    when(mockActivity.getApplicationContext()).thenReturn(mockContext);
    return mockActivity;
  }

  private void setPluginActivity(LocalAuthPlugin plugin, Activity activity) {
    final HiddenLifecycleReference mockLifecycleReference = mock(HiddenLifecycleReference.class);
    final FlutterPluginBinding mockPluginBinding = mock(FlutterPluginBinding.class);
    final ActivityPluginBinding mockActivityBinding = mock(ActivityPluginBinding.class);
    final FlutterEngine mockFlutterEngine = mock(FlutterEngine.class);
    final DartExecutor mockDartExecutor = mock(DartExecutor.class);
    when(mockPluginBinding.getFlutterEngine()).thenReturn(mockFlutterEngine);
    when(mockFlutterEngine.getDartExecutor()).thenReturn(mockDartExecutor);
    when(mockActivityBinding.getActivity()).thenReturn(activity);
    when(mockActivityBinding.getLifecycle()).thenReturn(mockLifecycleReference);
    plugin.onAttachedToEngine(mockPluginBinding);
    plugin.onAttachedToActivity(mockActivityBinding);
  }
}
