// 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.googlesignin;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
import com.google.android.gms.auth.api.signin.GoogleSignInClient;
import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
import com.google.android.gms.common.api.Scope;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.PluginRegistry;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;

public class GoogleSignInTest {
  @Mock Context mockContext;
  @Mock Resources mockResources;
  @Mock Activity mockActivity;
  @Mock PluginRegistry.Registrar mockRegistrar;
  @Mock BinaryMessenger mockMessenger;
  @Spy MethodChannel.Result result;
  @Mock GoogleSignInWrapper mockGoogleSignIn;
  @Mock GoogleSignInAccount account;
  @Mock GoogleSignInClient mockClient;
  private GoogleSignInPlugin plugin;

  @Before
  public void setUp() {
    MockitoAnnotations.initMocks(this);
    when(mockRegistrar.messenger()).thenReturn(mockMessenger);
    when(mockRegistrar.context()).thenReturn(mockContext);
    when(mockRegistrar.activity()).thenReturn(mockActivity);
    when(mockContext.getResources()).thenReturn(mockResources);
    plugin = new GoogleSignInPlugin();
    plugin.initInstance(mockRegistrar.messenger(), mockRegistrar.context(), mockGoogleSignIn);
    plugin.setUpRegistrar(mockRegistrar);
  }

  @Test
  public void requestScopes_ResultErrorIfAccountIsNull() {
    MethodCall methodCall = new MethodCall("requestScopes", null);
    when(mockGoogleSignIn.getLastSignedInAccount(mockContext)).thenReturn(null);
    plugin.onMethodCall(methodCall, result);
    verify(result).error("sign_in_required", "No account to grant scopes.", null);
  }

  @Test
  public void requestScopes_ResultTrueIfAlreadyGranted() {
    HashMap<String, List<String>> arguments = new HashMap<>();
    arguments.put("scopes", Collections.singletonList("requestedScope"));

    MethodCall methodCall = new MethodCall("requestScopes", arguments);
    Scope requestedScope = new Scope("requestedScope");
    when(mockGoogleSignIn.getLastSignedInAccount(mockContext)).thenReturn(account);
    when(account.getGrantedScopes()).thenReturn(Collections.singleton(requestedScope));
    when(mockGoogleSignIn.hasPermissions(account, requestedScope)).thenReturn(true);

    plugin.onMethodCall(methodCall, result);
    verify(result).success(true);
  }

  @Test
  public void requestScopes_RequestsPermissionIfNotGranted() {
    HashMap<String, List<String>> arguments = new HashMap<>();
    arguments.put("scopes", Collections.singletonList("requestedScope"));
    MethodCall methodCall = new MethodCall("requestScopes", arguments);
    Scope requestedScope = new Scope("requestedScope");

    when(mockGoogleSignIn.getLastSignedInAccount(mockContext)).thenReturn(account);
    when(account.getGrantedScopes()).thenReturn(Collections.singleton(requestedScope));
    when(mockGoogleSignIn.hasPermissions(account, requestedScope)).thenReturn(false);

    plugin.onMethodCall(methodCall, result);

    verify(mockGoogleSignIn)
        .requestPermissions(mockActivity, 53295, account, new Scope[] {requestedScope});
  }

  @Test
  public void requestScopes_ReturnsFalseIfPermissionDenied() {
    HashMap<String, List<String>> arguments = new HashMap<>();
    arguments.put("scopes", Collections.singletonList("requestedScope"));
    MethodCall methodCall = new MethodCall("requestScopes", arguments);
    Scope requestedScope = new Scope("requestedScope");

    ArgumentCaptor<PluginRegistry.ActivityResultListener> captor =
        ArgumentCaptor.forClass(PluginRegistry.ActivityResultListener.class);
    verify(mockRegistrar).addActivityResultListener(captor.capture());
    PluginRegistry.ActivityResultListener listener = captor.getValue();

    when(mockGoogleSignIn.getLastSignedInAccount(mockContext)).thenReturn(account);
    when(account.getGrantedScopes()).thenReturn(Collections.singleton(requestedScope));
    when(mockGoogleSignIn.hasPermissions(account, requestedScope)).thenReturn(false);

    plugin.onMethodCall(methodCall, result);
    listener.onActivityResult(
        GoogleSignInPlugin.Delegate.REQUEST_CODE_REQUEST_SCOPE,
        Activity.RESULT_CANCELED,
        new Intent());

    verify(result).success(false);
  }

  @Test
  public void requestScopes_ReturnsTrueIfPermissionGranted() {
    HashMap<String, List<String>> arguments = new HashMap<>();
    arguments.put("scopes", Collections.singletonList("requestedScope"));
    MethodCall methodCall = new MethodCall("requestScopes", arguments);
    Scope requestedScope = new Scope("requestedScope");

    ArgumentCaptor<PluginRegistry.ActivityResultListener> captor =
        ArgumentCaptor.forClass(PluginRegistry.ActivityResultListener.class);
    verify(mockRegistrar).addActivityResultListener(captor.capture());
    PluginRegistry.ActivityResultListener listener = captor.getValue();

    when(mockGoogleSignIn.getLastSignedInAccount(mockContext)).thenReturn(account);
    when(account.getGrantedScopes()).thenReturn(Collections.singleton(requestedScope));
    when(mockGoogleSignIn.hasPermissions(account, requestedScope)).thenReturn(false);

    plugin.onMethodCall(methodCall, result);
    listener.onActivityResult(
        GoogleSignInPlugin.Delegate.REQUEST_CODE_REQUEST_SCOPE, Activity.RESULT_OK, new Intent());

    verify(result).success(true);
  }

  @Test
  public void requestScopes_mayBeCalledRepeatedly_ifAlreadyGranted() {
    HashMap<String, List<String>> arguments = new HashMap<>();
    arguments.put("scopes", Collections.singletonList("requestedScope"));
    MethodCall methodCall = new MethodCall("requestScopes", arguments);
    Scope requestedScope = new Scope("requestedScope");

    ArgumentCaptor<PluginRegistry.ActivityResultListener> captor =
        ArgumentCaptor.forClass(PluginRegistry.ActivityResultListener.class);
    verify(mockRegistrar).addActivityResultListener(captor.capture());
    PluginRegistry.ActivityResultListener listener = captor.getValue();

    when(mockGoogleSignIn.getLastSignedInAccount(mockContext)).thenReturn(account);
    when(account.getGrantedScopes()).thenReturn(Collections.singleton(requestedScope));
    when(mockGoogleSignIn.hasPermissions(account, requestedScope)).thenReturn(false);

    plugin.onMethodCall(methodCall, result);
    listener.onActivityResult(
        GoogleSignInPlugin.Delegate.REQUEST_CODE_REQUEST_SCOPE, Activity.RESULT_OK, new Intent());
    plugin.onMethodCall(methodCall, result);
    listener.onActivityResult(
        GoogleSignInPlugin.Delegate.REQUEST_CODE_REQUEST_SCOPE, Activity.RESULT_OK, new Intent());

    verify(result, times(2)).success(true);
  }

  @Test
  public void requestScopes_mayBeCalledRepeatedly_ifNotSignedIn() {
    HashMap<String, List<String>> arguments = new HashMap<>();
    arguments.put("scopes", Collections.singletonList("requestedScope"));
    MethodCall methodCall = new MethodCall("requestScopes", arguments);
    Scope requestedScope = new Scope("requestedScope");

    ArgumentCaptor<PluginRegistry.ActivityResultListener> captor =
        ArgumentCaptor.forClass(PluginRegistry.ActivityResultListener.class);
    verify(mockRegistrar).addActivityResultListener(captor.capture());
    PluginRegistry.ActivityResultListener listener = captor.getValue();

    when(mockGoogleSignIn.getLastSignedInAccount(mockContext)).thenReturn(null);

    plugin.onMethodCall(methodCall, result);
    listener.onActivityResult(
        GoogleSignInPlugin.Delegate.REQUEST_CODE_REQUEST_SCOPE, Activity.RESULT_OK, new Intent());
    plugin.onMethodCall(methodCall, result);
    listener.onActivityResult(
        GoogleSignInPlugin.Delegate.REQUEST_CODE_REQUEST_SCOPE, Activity.RESULT_OK, new Intent());

    verify(result, times(2)).error("sign_in_required", "No account to grant scopes.", null);
  }

  @Test(expected = IllegalStateException.class)
  public void signInThrowsWithoutActivity() {
    final GoogleSignInPlugin plugin = new GoogleSignInPlugin();
    plugin.initInstance(
        mock(BinaryMessenger.class), mock(Context.class), mock(GoogleSignInWrapper.class));

    plugin.onMethodCall(new MethodCall("signIn", null), null);
  }

  @Test
  public void init_LoadsServerClientIdFromResources() {
    final String packageName = "fakePackageName";
    final String serverClientId = "fakeServerClientId";
    final int resourceId = 1;
    MethodCall methodCall = buildInitMethodCall(null, null);
    when(mockContext.getPackageName()).thenReturn(packageName);
    when(mockResources.getIdentifier("default_web_client_id", "string", packageName))
        .thenReturn(resourceId);
    when(mockContext.getString(resourceId)).thenReturn(serverClientId);
    initAndAssertServerClientId(methodCall, serverClientId);
  }

  @Test
  public void init_InterpretsClientIdAsServerClientId() {
    final String clientId = "fakeClientId";
    MethodCall methodCall = buildInitMethodCall(clientId, null);
    initAndAssertServerClientId(methodCall, clientId);
  }

  @Test
  public void init_ForwardsServerClientId() {
    final String serverClientId = "fakeServerClientId";
    MethodCall methodCall = buildInitMethodCall(null, serverClientId);
    initAndAssertServerClientId(methodCall, serverClientId);
  }

  @Test
  public void init_IgnoresClientIdIfServerClientIdIsProvided() {
    final String clientId = "fakeClientId";
    final String serverClientId = "fakeServerClientId";
    MethodCall methodCall = buildInitMethodCall(clientId, serverClientId);
    initAndAssertServerClientId(methodCall, serverClientId);
  }

  @Test
  public void init_PassesForceCodeForRefreshTokenFalseWithServerClientIdParameter() {
    MethodCall methodCall = buildInitMethodCall("fakeClientId", "fakeServerClientId", false);

    initAndAssertForceCodeForRefreshToken(methodCall, false);
  }

  @Test
  public void init_PassesForceCodeForRefreshTokenTrueWithServerClientIdParameter() {
    MethodCall methodCall = buildInitMethodCall("fakeClientId", "fakeServerClientId", true);

    initAndAssertForceCodeForRefreshToken(methodCall, true);
  }

  @Test
  public void init_PassesForceCodeForRefreshTokenFalseWithServerClientIdFromResources() {
    final String packageName = "fakePackageName";
    final String serverClientId = "fakeServerClientId";
    final int resourceId = 1;
    MethodCall methodCall = buildInitMethodCall(null, null, false);
    when(mockContext.getPackageName()).thenReturn(packageName);
    when(mockResources.getIdentifier("default_web_client_id", "string", packageName))
        .thenReturn(resourceId);
    when(mockContext.getString(resourceId)).thenReturn(serverClientId);

    initAndAssertForceCodeForRefreshToken(methodCall, false);
  }

  @Test
  public void init_PassesForceCodeForRefreshTokenTrueWithServerClientIdFromResources() {
    final String packageName = "fakePackageName";
    final String serverClientId = "fakeServerClientId";
    final int resourceId = 1;
    MethodCall methodCall = buildInitMethodCall(null, null, true);
    when(mockContext.getPackageName()).thenReturn(packageName);
    when(mockResources.getIdentifier("default_web_client_id", "string", packageName))
        .thenReturn(resourceId);
    when(mockContext.getString(resourceId)).thenReturn(serverClientId);

    initAndAssertForceCodeForRefreshToken(methodCall, true);
  }

  public void initAndAssertServerClientId(MethodCall methodCall, String serverClientId) {
    ArgumentCaptor<GoogleSignInOptions> optionsCaptor =
        ArgumentCaptor.forClass(GoogleSignInOptions.class);
    when(mockGoogleSignIn.getClient(any(Context.class), optionsCaptor.capture()))
        .thenReturn(mockClient);
    plugin.onMethodCall(methodCall, result);
    verify(result).success(null);
    Assert.assertEquals(serverClientId, optionsCaptor.getValue().getServerClientId());
  }

  public void initAndAssertForceCodeForRefreshToken(
      MethodCall methodCall, boolean forceCodeForRefreshToken) {
    ArgumentCaptor<GoogleSignInOptions> optionsCaptor =
        ArgumentCaptor.forClass(GoogleSignInOptions.class);
    when(mockGoogleSignIn.getClient(any(Context.class), optionsCaptor.capture()))
        .thenReturn(mockClient);
    plugin.onMethodCall(methodCall, result);
    verify(result).success(null);
    Assert.assertEquals(
        forceCodeForRefreshToken, optionsCaptor.getValue().isForceCodeForRefreshToken());
  }

  private static MethodCall buildInitMethodCall(String clientId, String serverClientId) {
    return buildInitMethodCall(
        "SignInOption.standard", Collections.<String>emptyList(), clientId, serverClientId, false);
  }

  private static MethodCall buildInitMethodCall(
      String clientId, String serverClientId, boolean forceCodeForRefreshToken) {
    return buildInitMethodCall(
        "SignInOption.standard",
        Collections.<String>emptyList(),
        clientId,
        serverClientId,
        forceCodeForRefreshToken);
  }

  private static MethodCall buildInitMethodCall(
      String signInOption,
      List<String> scopes,
      String clientId,
      String serverClientId,
      boolean forceCodeForRefreshToken) {
    HashMap<String, Object> arguments = new HashMap<>();
    arguments.put("signInOption", signInOption);
    arguments.put("scopes", scopes);
    if (clientId != null) {
      arguments.put("clientId", clientId);
    }
    if (serverClientId != null) {
      arguments.put("serverClientId", serverClientId);
    }
    arguments.put("forceCodeForRefreshToken", forceCodeForRefreshToken);
    return new MethodCall("init", arguments);
  }
}
