package org.pmiops.workbench.google;

import static com.google.common.truth.Truth.assertThat;

import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.http.apache.ApacheHttpTransport;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.time.Clock;
import javax.mail.MessagingException;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.pmiops.workbench.config.WorkbenchConfig;
import org.pmiops.workbench.mail.MailService;
import org.pmiops.workbench.mail.MailServiceImpl;
import org.pmiops.workbench.test.Providers;
import org.springframework.retry.backoff.NoBackOffPolicy;

public class DirectoryServiceImplIntegrationTest {
  private DirectoryServiceImpl service;
  private final GoogleCredential googleCredential = getGoogleCredential();
  private final WorkbenchConfig workbenchConfig = createConfig();
  private final ApacheHttpTransport httpTransport = new ApacheHttpTransport();

  @Before
  public void setUp() throws MessagingException {
    MailService mailService = Mockito.mock(MailServiceImpl.class);
    service =
        new DirectoryServiceImpl(
            Providers.of(googleCredential),
            Providers.of(workbenchConfig),
            httpTransport,
            new GoogleRetryHandler(new NoBackOffPolicy()));
  }

  @Test
  public void testDummyUsernameIsNotTaken() {
    assertThat(service.isUsernameTaken("username-that-should-not-exist")).isFalse();
  }

  @Test
  public void testDirectoryServiceUsernameIsTaken() {
    assertThat(service.isUsernameTaken("directory-service")).isTrue();
  }

  @Test
  public void testCreateAndDeleteTestUser() {
    String userName = String.format("integration.test.%d", Clock.systemUTC().millis());
    service.createUser("Integration", "Test", userName, "notasecret@gmail.com");
    assertThat(service.isUsernameTaken(userName)).isTrue();
    // Ensure our two custom schema fields are correctly set & re-fetched from GSuite.
    assertThat(service.getContactEmailAddress(userName).equals("notasecret@gmail.com"));
    assertThat(
        service
            .getUserByUsername(userName)
            .getCustomSchemas()
            .get("All_of_Us_Workbench")
            .get("Institution")
            .equals("All of Us Research Workbench"));
    service.deleteUser(userName);
    assertThat(service.isUsernameTaken(userName)).isFalse();
  }

  private static GoogleCredential getGoogleCredential() {
    try {
      String saKeyPath = "src/main/webapp/WEB-INF/gsuite-admin-sa.json";
      return GoogleCredential.fromStream(new FileInputStream(new File(saKeyPath)));
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

  private static WorkbenchConfig createConfig() {
    WorkbenchConfig config = new WorkbenchConfig();
    config.googleDirectoryService = new WorkbenchConfig.GoogleDirectoryServiceConfig();
    config.googleDirectoryService.gSuiteDomain = "fake-research-aou.org";
    return config;
  }
}

@@ -340,33 +340,17 @@
 java
-x.mail.MessagingException
+.util.Map
 ;%0Aim
@@ -399,36 +399,8 @@
 st;%0A
-import org.mockito.Mockito;%0A
 impo
@@ -479,176 +479,268 @@
 nch.
-mail.MailService;%0Aimport org.pmiops.workbench.mail.MailServiceImpl;%0Aimport org.pmiops.workbench.test.Providers;%0Aimport org.springframework.retry.backoff.NoBackOffPolicy
+test.Providers;%0Aimport org.springframework.retry.backoff.ExponentialRandomBackOffPolicy;%0Aimport org.springframework.retry.backoff.NoBackOffPolicy;%0Aimport org.springframework.retry.policy.SimpleRetryPolicy;%0Aimport org.springframework.retry.support.RetryTemplate
 ;%0A%0Ap
@@ -1086,102 +1086,9 @@
 p() 
-throws MessagingException %7B%0A    MailService mailService = Mockito.mock(MailServiceImpl.class);
+%7B
 %0A   
@@ -1875,16 +1875,668 @@
 sTrue();
+%0A%0A    // As of ~6/25/19, customSchemas are sometimes unavailable on the initial call to Gsuite. This%0A    // data is likely not written with strong consistency. Retry until it is available.%0A    Map%3CString, Object%3E aouMeta =%0A        retryTemplate()%0A            .execute(%0A                c -%3E %7B%0A                  Map%3CString, Map%3CString, Object%3E%3E schemas =%0A                      service.getUserByUsername(userName).getCustomSchemas();%0A                  if (schemas == null) %7B%0A                    throw new RuntimeException(%22custom schemas is still null%22);%0A                  %7D%0A                  return schemas.get(%22All_of_Us_Workbench%22);%0A                %7D);
 %0A    // 
@@ -2615,16 +2615,102 @@
 GSuite.%0A
+    assertThat(aouMeta).containsEntry(%22Institution%22, %22All of Us Research Workbench%22);%0A
     asse
@@ -2798,66 +2798,71 @@
     
-assertThat(%0A        service%0A            .getUserBy
+service.deleteUser(userName);%0A    assertThat(service.is
 Username
 (use
@@ -2849,32 +2849,37 @@
 rvice.isUsername
+Taken
 (userName)%0A     
@@ -2876,260 +2876,421 @@
 ame)
-%0A            .getCustomSchemas()%0A            .get(%22All_of_Us_Workbench%22)%0A            .get(%22Institution%22)%0A            .equals(%22All of Us Research Workbench%22));%0A    service.deleteUser(userName
+).isFalse();%0A  %7D%0A%0A  private static RetryTemplate retryTemplate() %7B%0A    RetryTemplate tmpl = new RetryTemplate();%0A    ExponentialRandomBackOffPolicy backoff = new ExponentialRandomBackOffPolicy();%0A    tmpl.setBackOffPolicy(backoff);%0A    SimpleRetryPolicy retry = new SimpleRetryPolicy();%0A    retry.setMaxAttempts(10);%0A    tmpl.setRetryPolicy(retry
 );%0A    
-as
+tmpl.
 se
-r
 tTh
-at(service.isUsernameTaken(userName)).isFalse()
+rowLastExceptionOnExhausted(true);%0A    return tmpl
 ;%0A  

Fix gsuite integration test (#2279)