// Copyright (C) 2019 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.gerrit.acceptance.api.change;

import static com.google.common.truth.Truth.assertThat;
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.block;
import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
import static com.google.gerrit.testing.GerritJUnit.assertThrows;
import static java.util.stream.Collectors.toList;
import static javax.servlet.http.HttpServletResponse.SC_OK;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.acceptance.RestResponse;
import com.google.gerrit.acceptance.UseClockStep;
import com.google.gerrit.acceptance.config.GerritConfig;
import com.google.gerrit.acceptance.testsuite.account.AccountOperations;
import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
import com.google.gerrit.entities.AccessSection;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Patch;
import com.google.gerrit.entities.Permission;
import com.google.gerrit.entities.Project;
import com.google.gerrit.extensions.api.changes.ReviewInput;
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.TopLevelResource;
import com.google.gerrit.server.project.ProjectConfig;
import com.google.gerrit.server.restapi.change.QueryChanges;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.util.Arrays;
import java.util.List;
import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
import org.eclipse.jgit.junit.TestRepository;
import org.junit.Test;

public class QueryChangesIT extends AbstractDaemonTest {
  @Inject private AccountOperations accountOperations;
  @Inject private ProjectOperations projectOperations;
  @Inject private Provider<QueryChanges> queryChangesProvider;
  @Inject private RequestScopeOperations requestScopeOperations;

  @Test
  @SuppressWarnings("unchecked")
  public void multipleQueriesInOneRequestCanContainSameChange() throws Exception {
    String cId1 = createChange().getChangeId();
    String cId2 = createChange().getChangeId();
    int numericId1 = gApi.changes().id(cId1).get()._number;
    int numericId2 = gApi.changes().id(cId2).get()._number;

    gApi.changes().id(cId2).setWorkInProgress();

    QueryChanges queryChanges = queryChangesProvider.get();

    queryChanges.addQuery("is:open repo:" + project.get());
    queryChanges.addQuery("is:wip repo:" + project.get());

    List<List<ChangeInfo>> result =
        (List<List<ChangeInfo>>) queryChanges.apply(TopLevelResource.INSTANCE).value();
    assertThat(result).hasSize(2);
    assertThat(result.get(0)).hasSize(2);
    assertThat(result.get(1)).hasSize(1);

    List<Integer> firstResultIds =
        ImmutableList.of(result.get(0).get(0)._number, result.get(0).get(1)._number);
    assertThat(firstResultIds).containsExactly(numericId1, numericId2);
    assertThat(result.get(1).get(0)._number).isEqualTo(numericId2);
  }

  @Test
  @SuppressWarnings("unchecked")
  public void moreChangesIndicatorDoesNotWronglyCopyToUnrelatedChanges() throws Exception {
    String queryWithMoreChanges = "is:wip limit:1 repo:" + project.get();
    String queryWithNoMoreChanges = "is:open limit:10 repo:" + project.get();
    createChange().getChangeId();
    String cId2 = createChange().getChangeId();
    String cId3 = createChange().getChangeId();
    gApi.changes().id(cId2).setWorkInProgress();
    gApi.changes().id(cId3).setWorkInProgress();

    // Run the capped query first
    QueryChanges queryChanges = queryChangesProvider.get();
    queryChanges.addQuery(queryWithMoreChanges);
    queryChanges.addQuery(queryWithNoMoreChanges);
    List<List<ChangeInfo>> result =
        (List<List<ChangeInfo>>) queryChanges.apply(TopLevelResource.INSTANCE).value();
    assertThat(result).hasSize(2);
    assertThat(result.get(0)).hasSize(1);
    assertThat(result.get(1)).hasSize(3);
    // _moreChanges is set on the first response, but not on the second.
    assertThat(result.get(0).get(0)._moreChanges).isTrue();
    assertNoChangeHasMoreChangesSet(result.get(1));

    // Run the capped query second
    QueryChanges queryChanges2 = queryChangesProvider.get();
    queryChanges2.addQuery(queryWithNoMoreChanges);
    queryChanges2.addQuery(queryWithMoreChanges);
    List<List<ChangeInfo>> result2 =
        (List<List<ChangeInfo>>) queryChanges2.apply(TopLevelResource.INSTANCE).value();
    assertThat(result2).hasSize(2);
    assertThat(result2.get(0)).hasSize(3);
    assertThat(result2.get(1)).hasSize(1);
    // _moreChanges is set on the second response, but not on the first.
    assertNoChangeHasMoreChangesSet(result2.get(0));
    assertThat(result2.get(1).get(0)._moreChanges).isTrue();
  }

  @Test
  @SuppressWarnings("unchecked")
  @GerritConfig(name = "operator-alias.change.numberaliastest", value = "change")
  public void aliasQuery() throws Exception {
    String cId1 = createChange().getChangeId();
    String cId2 = createChange().getChangeId();
    int numericId1 = gApi.changes().id(cId1).get()._number;
    int numericId2 = gApi.changes().id(cId2).get()._number;

    QueryChanges queryChanges = queryChangesProvider.get();
    queryChanges.addQuery("numberaliastest:12345");
    queryChanges.addQuery("numberaliastest:" + numericId1);
    queryChanges.addQuery("numberaliastest:" + numericId2);

    List<List<ChangeInfo>> result =
        (List<List<ChangeInfo>>) queryChanges.apply(TopLevelResource.INSTANCE).value();
    assertThat(result).hasSize(3);
    assertThat(result.get(0)).hasSize(0);
    assertThat(result.get(1)).hasSize(1);
    assertThat(result.get(2)).hasSize(1);

    assertThat(result.get(1).get(0)._number).isEqualTo(numericId1);
    assertThat(result.get(2).get(0)._number).isEqualTo(numericId2);
  }

  @Test
  @UseClockStep
  @SuppressWarnings("unchecked")
  public void withPagedResults() throws Exception {
    // Create 4 visible changes.
    createChange(testRepo).getChange().getId().get();
    createChange(testRepo).getChange().getId().get();
    int changeId3 = createChange(testRepo).getChange().getId().get();
    int changeId4 = createChange(testRepo).getChange().getId().get();

    // Create hidden project.
    Project.NameKey hiddenProject = projectOperations.newProject().create();
    TestRepository<InMemoryRepository> hiddenRepo = cloneProject(hiddenProject, admin);
    // Create 2 hidden changes.
    createChange(hiddenRepo);
    createChange(hiddenRepo);
    // Actually hide project
    projectOperations
        .project(hiddenProject)
        .forUpdate()
        .add(block(Permission.READ).ref("refs/*").group(REGISTERED_USERS))
        .update();

    // Create a change query that matches all changes (visible and hidden changes).
    // The index returns the changes ordered by last updated timestamp:
    // hiddenChange2, hiddenChange1, change4, change3, change2, change1
    QueryChanges queryChanges = queryChangesProvider.get();
    queryChanges.addQuery("branch:master");

    // Set a limit on the query so that we need to paginate over the results from the index.
    queryChanges.setLimit(2);

    // Execute the query and verify the results.
    // Since the limit is set to 2, at most 2 changes are returned to user, but the index query is
    // executed with limit 3 (+1 so that we can populate the _more_changes field on the last
    // result).
    // This means the index query with limit 3 returns these changes:
    // hiddenChange2, hiddenChange1, change4
    // The 2 hidden changes are filtered out because they are not visible to the caller.
    // This means we have only one matching result (change4) but the limit (3) is not exhausted
    // yet. Hence the next page is loaded from the index (startIndex is 3 to skip the results
    // that we already processed, limit is again 3). The results for the next page are:
    // change3, change2, change1
    // change2 and change1 are dropped because they are over the limit.
    List<ChangeInfo> result =
        (List<ChangeInfo>) queryChanges.apply(TopLevelResource.INSTANCE).value();
    assertThat(result.stream().map(i -> i._number).collect(toList()))
        .containsExactly(changeId3, changeId4);
  }

  @Test
  public void usingOutOfRangeLabelValuesDoesNotCauseError() throws Exception {
    for (String operator : ImmutableList.of("=", ">", ">=", "<", "<=")) {
      QueryChanges queryChanges = queryChangesProvider.get();
      queryChanges.addQuery("label:Code-Review" + operator + "10");
      queryChanges.addQuery("label:Code-Review" + operator + "-10");
      queryChanges.addQuery("Code-Review" + operator + "10");
      queryChanges.addQuery("Code-Review" + operator + "-10");
      assertThat(queryChanges.apply(TopLevelResource.INSTANCE).statusCode()).isEqualTo(SC_OK);
    }
  }

  @Test
  public void queryByFullNameEmailFormatWithEmptyFullNameWhenEmailMatchesSeveralAccounts()
      throws Exception {
    // Create 2 accounts with the same preferred email (both account must have no external ID for
    // the email because otherwise the account with the external ID takes precedence).
    String email = "foo.bar@example.com";
    Account.Id account1 = accountOperations.newAccount().create();
    accountOperations
        .account(account1)
        .forInvalidation()
        .preferredEmailWithoutExternalId(email)
        .invalidate();
    Account.Id account2 = accountOperations.newAccount().create();
    accountOperations
        .account(account2)
        .forInvalidation()
        .preferredEmailWithoutExternalId(email)
        .invalidate();

    // Search with "Full Name <email>" format, but without full name. Both created accounts match
    // the email. In this case Gerrit falls back to match on the full name. Check that this logic
    // doesn't fail if the full name in the input string is not present.
    QueryChanges queryChanges = queryChangesProvider.get();
    queryChanges.addQuery("<" + email + ">");
    assertThat(queryChanges.apply(TopLevelResource.INSTANCE).statusCode()).isEqualTo(SC_OK);
  }

  @Test
  public void defaultQueryCannotBeParsedDueToInvalidRegEx() throws Exception {
    QueryChanges queryChanges = queryChangesProvider.get();
    queryChanges.addQuery("^[A");
    BadRequestException e =
        assertThrows(
            BadRequestException.class, () -> queryChanges.apply(TopLevelResource.INSTANCE));
    assertThat(e).hasMessageThat().contains("no viable alternative at character '['");
  }

  @Test
  public void defaultQueryWithInvalidQuotedRegEx() throws Exception {
    QueryChanges queryChanges = queryChangesProvider.get();
    queryChanges.addQuery("\"^[A\"");
    BadRequestException e =
        assertThrows(
            BadRequestException.class, () -> queryChanges.apply(TopLevelResource.INSTANCE));
    assertThat(e).hasMessageThat().isEqualTo("invalid regular expression: [A");
  }

  @Test
  @SuppressWarnings("unchecked")
  @GerritConfig(name = "has-operand-alias.change.unaddressedaliastest", value = "unresolved")
  public void hasOperandAliasQuery() throws Exception {
    String cId1 = createChange().getChangeId();
    String cId2 = createChange().getChangeId();
    int numericId1 = gApi.changes().id(cId1).get()._number;
    int numericId2 = gApi.changes().id(cId2).get()._number;

    ReviewInput input = new ReviewInput();
    ReviewInput.CommentInput comment = new ReviewInput.CommentInput();
    comment.line = 1;
    comment.message = "comment";
    comment.unresolved = true;
    input.comments = ImmutableMap.of(Patch.COMMIT_MSG, ImmutableList.of(comment));
    gApi.changes().id(cId2).current().review(input);

    QueryChanges queryChanges = queryChangesProvider.get();
    queryChanges.addQuery("is:open repo:" + project.get());
    queryChanges.addQuery("has:unaddressedaliastest repo:" + project.get());

    List<List<ChangeInfo>> result =
        (List<List<ChangeInfo>>) queryChanges.apply(TopLevelResource.INSTANCE).value();
    assertThat(result).hasSize(2);
    assertThat(result.get(0)).hasSize(2);
    assertThat(result.get(1)).hasSize(1);

    List<Integer> firstResultIds =
        ImmutableList.of(result.get(0).get(0)._number, result.get(0).get(1)._number);
    assertThat(firstResultIds).containsExactly(numericId1, numericId2);
    assertThat(result.get(1).get(0)._number).isEqualTo(numericId2);
  }

  @Test
  public void skipVisibility_rejectedForNonAdmin() throws Exception {
    requestScopeOperations.setApiUser(user.id());
    final QueryChanges queryChanges = queryChangesProvider.get();
    String query = "is:open repo:" + project.get();
    queryChanges.addQuery(query);
    AuthException thrown =
        assertThrows(AuthException.class, () -> queryChanges.skipVisibility(true));
    assertThat(thrown).hasMessageThat().isEqualTo("administrate server not permitted");
  }

  @Test
  @SuppressWarnings("unchecked")
  public void skipVisibility_noReadPermission() throws Exception {
    createChange().getChangeId();
    requestScopeOperations.setApiUser(admin.id());
    QueryChanges queryChanges = queryChangesProvider.get();

    queryChanges.addQuery("is:open repo:" + project.get());
    List<List<ChangeInfo>> result =
        (List<List<ChangeInfo>>) queryChanges.apply(TopLevelResource.INSTANCE).value();
    assertThat(result).hasSize(1);

    try (ProjectConfigUpdate u = updateProject(allProjects)) {
      ProjectConfig cfg = u.getConfig();
      removeAllBranchPermissions(cfg, Permission.READ);
      u.save();
    }

    queryChanges = queryChangesProvider.get();
    queryChanges.addQuery("is:open repo:" + project.get());
    List<List<ChangeInfo>> result2 =
        (List<List<ChangeInfo>>) queryChanges.apply(TopLevelResource.INSTANCE).value();
    assertThat(result2).hasSize(0);

    queryChanges = queryChangesProvider.get();
    queryChanges.addQuery("is:open repo:" + project.get());
    queryChanges.skipVisibility(true);
    List<List<ChangeInfo>> result3 =
        (List<List<ChangeInfo>>) queryChanges.apply(TopLevelResource.INSTANCE).value();
    assertThat(result3).hasSize(1);
  }

  @Test
  public void testInvalidListChangeOption() throws Exception {
    PushOneCommit.Result r = createChange();
    RestResponse rep = adminRestSession.get("/changes/" + r.getChange().getId() + "/?O=fffffff");
    rep.assertBadRequest();
  }

  @Test
  @SuppressWarnings("unchecked")
  public void skipVisibility_privateChange() throws Exception {
    TestRepository<InMemoryRepository> userRepo = cloneProject(project, user);
    PushOneCommit.Result result =
        pushFactory.create(user.newIdent(), userRepo).to("refs/for/master");
    requestScopeOperations.setApiUser(user.id());
    gApi.changes().id(result.getChangeId()).setPrivate(true);

    requestScopeOperations.setApiUser(admin.id());
    QueryChanges queryChanges = queryChangesProvider.get();

    queryChanges.addQuery("is:open repo:" + project.get());
    List<List<ChangeInfo>> result2 =
        (List<List<ChangeInfo>>) queryChanges.apply(TopLevelResource.INSTANCE).value();
    assertThat(result2).hasSize(0);

    queryChanges = queryChangesProvider.get();
    queryChanges.addQuery("is:open repo:" + project.get());
    queryChanges.skipVisibility(true);
    List<List<ChangeInfo>> result3 =
        (List<List<ChangeInfo>>) queryChanges.apply(TopLevelResource.INSTANCE).value();
    assertThat(result3).hasSize(1);
  }

  private static void assertNoChangeHasMoreChangesSet(List<ChangeInfo> results) {
    for (ChangeInfo info : results) {
      assertThat(info._moreChanges).isNull();
    }
  }

  private static void removeAllBranchPermissions(ProjectConfig cfg, String... permissions) {
    for (AccessSection s : cfg.getAccessSections()) {
      if (s.getName().startsWith("refs/heads/")
          || s.getName().startsWith("refs/for/")
          || s.getName().equals("refs/*")) {
        cfg.upsertAccessSection(
            s.getName(),
            updatedSection -> {
              Arrays.stream(permissions).forEach(p -> updatedSection.remove(Permission.builder(p)));
            });
      }
    }
  }
}
