Use direct GerritApi calls in GerritClientAccount

Modify both `getAccountId` and `getAccountGroups` to use direct
`GerritApi` calls. Note that it still extends the `GerritClientBase` as
it is a parent for several implementations (that will be refactored
later).

The `ChatGptReviewTestBase` was modified to mock direct `GerritApi`
calls related to accounts. As a result all tests are still passing.

Bug: Issue 336577745
Change-Id: Iaee041a4c38ae842ba4707841c782dd1fb33f664
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/api/gerrit/GerritClientAccount.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/api/gerrit/GerritClientAccount.java
index 5baa465..8004845 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/api/gerrit/GerritClientAccount.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/api/gerrit/GerritClientAccount.java
@@ -1,16 +1,16 @@
 package com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit;
 
-import com.google.gson.JsonArray;
+import com.google.gerrit.extensions.common.AccountInfo;
+import com.google.gerrit.extensions.common.GroupInfo;
+import com.google.gerrit.server.util.ManualRequestContext;
 import com.googlesource.gerrit.plugins.chatgpt.config.Configuration;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.UriResourceLocator;
 import lombok.extern.slf4j.Slf4j;
 
-import java.net.URI;
+import static java.util.stream.Collectors.toList;
+
 import java.util.List;
 import java.util.NoSuchElementException;
 import java.util.Optional;
-import java.util.stream.Collectors;
-import java.util.stream.StreamSupport;
 
 @Slf4j
 public class GerritClientAccount extends GerritClientBase {
@@ -37,11 +37,12 @@
     }
 
     protected Optional<Integer> getAccountId(String authorUsername) {
-        URI uri = URI.create(config.getGerritAuthBaseUrl()
-                + UriResourceLocator.gerritAccountIdUri(authorUsername));
-        try {
-            JsonArray responseArray = forwardGetRequestReturnJsonArray(uri);
-            return Optional.of(responseArray.get(0).getAsJsonObject().get("_account_id").getAsInt());
+        try (ManualRequestContext requestContext = config.openRequestContext()) {
+            List<AccountInfo> accounts = config.getGerritApi().accounts().query(authorUsername).get();
+            if (accounts.isEmpty()) {
+                return Optional.empty();
+            }
+            return Optional.of(accounts.get(0)).map(a -> a._accountId);
         }
         catch (Exception e) {
             log.error("Could not find account ID for username '{}'", authorUsername);
@@ -55,14 +56,9 @@
     }
 
     private List<String> getAccountGroups(Integer accountId) {
-        URI uri = URI.create(config.getGerritAuthBaseUrl()
-                + UriResourceLocator.gerritAccountsUri()
-                + UriResourceLocator.gerritGroupPostfixUri(accountId));
-        try {
-            JsonArray responseArray = forwardGetRequestReturnJsonArray(uri);
-            return StreamSupport.stream(responseArray.spliterator(), false)
-                    .map(jsonElement -> jsonElement.getAsJsonObject().get("name").getAsString())
-                    .collect(Collectors.toList());
+        try (ManualRequestContext requestContext = config.openRequestContext()) {
+            List<GroupInfo> groups = config.getGerritApi().accounts().id(accountId).getGroups();
+            return groups.stream().map(g -> g.name).collect(toList());
         }
         catch (Exception e) {
             log.error("Could not find groups for account ID {}", accountId);
diff --git a/src/test/java/com/googlesource/gerrit/plugins/chatgpt/ChatGptReviewTestBase.java b/src/test/java/com/googlesource/gerrit/plugins/chatgpt/ChatGptReviewTestBase.java
index b252280..7139ee6 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/chatgpt/ChatGptReviewTestBase.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/chatgpt/ChatGptReviewTestBase.java
@@ -12,9 +12,14 @@
 import com.google.gerrit.server.account.AccountCache;
 import com.google.gerrit.server.account.AccountState;
 import com.google.gerrit.extensions.api.GerritApi;
+import com.google.gerrit.extensions.api.accounts.AccountApi;
+import com.google.gerrit.extensions.api.accounts.Accounts;
+import com.google.gerrit.extensions.api.accounts.Accounts.QueryRequest;
 import com.google.gerrit.extensions.api.changes.ChangeApi;
 import com.google.gerrit.extensions.api.changes.Changes;
+import com.google.gerrit.extensions.common.AccountInfo;
 import com.google.gerrit.extensions.common.ChangeInfo;
+import com.google.gerrit.extensions.common.GroupInfo;
 import com.google.gerrit.extensions.restapi.RestApiException;
 import com.google.gerrit.json.OutputFormat;
 import com.google.gerrit.server.config.PluginConfig;
@@ -36,7 +41,7 @@
 import com.googlesource.gerrit.plugins.chatgpt.data.PluginDataHandler;
 import com.googlesource.gerrit.plugins.chatgpt.listener.EventHandlerTask;
 import com.googlesource.gerrit.plugins.chatgpt.listener.GerritEventContextModule;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.UriResourceLocator;
+import com.google.inject.TypeLiteral;
 import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit.GerritChange;
 import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit.GerritClient;
 import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit.GerritClientFacade;
@@ -169,27 +174,15 @@
     protected void setupMockRequests() throws RestApiException {
         String fullChangeId = getGerritChange().getFullChangeId();
 
+        Accounts accountsMock = mockGerritAccountsRestEndpoint();
         // Mock the behavior of the gerritAccountIdUri request
-        WireMock.stubFor(WireMock.get(gerritAccountIdUri(GERRIT_GPT_USERNAME))
-                .willReturn(WireMock.aResponse()
-                        .withStatus(HTTP_OK)
-                        .withHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString())
-                        .withBody("[{\"_account_id\": " + GERRIT_GPT_ACCOUNT_ID + "}]")));
+        mockGerritAccountsQueryApiCall(accountsMock, GERRIT_GPT_USERNAME, GERRIT_GPT_ACCOUNT_ID);
 
         // Mock the behavior of the gerritAccountIdUri request
-        WireMock.stubFor(WireMock.get(gerritAccountIdUri(GERRIT_USER_USERNAME))
-                .willReturn(WireMock.aResponse()
-                        .withStatus(HTTP_OK)
-                        .withHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString())
-                        .withBody("[{\"_account_id\": " + GERRIT_USER_ACCOUNT_ID + "}]")));
+        mockGerritAccountsQueryApiCall(accountsMock, GERRIT_USER_USERNAME, GERRIT_USER_ACCOUNT_ID);
 
         // Mock the behavior of the gerritAccountGroups request
-        WireMock.stubFor(WireMock.get(UriResourceLocator.gerritAccountsUri() +
-                        gerritGroupPostfixUri(GERRIT_USER_ACCOUNT_ID))
-                .willReturn(WireMock.aResponse()
-                        .withStatus(HTTP_OK)
-                        .withHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString())
-                        .withBodyFile("gerritAccountGroups.json")));
+        mockGerritAccountGroupsApiCall(accountsMock, GERRIT_USER_ACCOUNT_ID);
 
         // Mock the behavior of the gerritPatchSetRevisionsUri request
         WireMock.stubFor(WireMock.get(gerritPatchSetRevisionsUri(fullChangeId))
@@ -204,7 +197,7 @@
                         .withStatus(HTTP_OK)
                         .withHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString())
                         .withBodyFile("gerritPatchSetDetail.json")));
-        mockGerritApi();
+        mockGerritChangeDetailsApiCall();
 
         // Mock the behavior of the gerritPatchSet comments request
         WireMock.stubFor(WireMock.get(gerritGetAllPatchSetCommentsUri(fullChangeId))
@@ -219,7 +212,32 @@
                         .withStatus(HTTP_OK)));
     }
 
-    private void mockGerritApi() throws RestApiException {
+    private Accounts mockGerritAccountsRestEndpoint() {
+        Accounts accountsMock = mock(Accounts.class);
+        when(gerritApi.accounts()).thenReturn(accountsMock);
+        return accountsMock;
+    }
+
+    private void mockGerritAccountsQueryApiCall(
+        Accounts accountsMock, String username, int expectedAccountId) throws RestApiException {
+        QueryRequest queryRequestMock = mock(QueryRequest.class);
+        when(accountsMock.query(username)).thenReturn(queryRequestMock);
+        when(queryRequestMock.get()).thenReturn(List.of(new AccountInfo(expectedAccountId)));
+    }
+
+    private void mockGerritAccountGroupsApiCall(Accounts accountsMock, int accountId)
+        throws RestApiException {
+        Gson gson = OutputFormat.JSON.newGson();
+        List<GroupInfo> groups =
+            gson.fromJson(
+                readTestFile("__files/gerritAccountGroups.json"),
+                new TypeLiteral<List<GroupInfo>>() {}.getType());
+        AccountApi accountApiMock = mock(AccountApi.class);
+        when(accountsMock.id(accountId)).thenReturn(accountApiMock);
+        when(accountApiMock.getGroups()).thenReturn(groups);
+    }
+
+    private void mockGerritChangeDetailsApiCall() throws RestApiException {
         Gson gson = OutputFormat.JSON.newGson();
         ChangeInfo changeInfo = gson.fromJson(readTestFile("__files/gerritPatchSetDetail.json"), ChangeInfo.class);
         Changes changesMock = mock(Changes.class);