// Copyright (C) 2017 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.server.query.group;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import static com.google.common.truth.Truth8.assertThat;
import static com.google.common.truth.TruthJUnit.assume;
import static com.google.gerrit.testing.GerritJUnit.assertThrows;
import static java.util.stream.Collectors.toList;

import com.google.common.base.CharMatcher;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.AccountGroup;
import com.google.gerrit.entities.InternalGroup;
import com.google.gerrit.extensions.api.GerritApi;
import com.google.gerrit.extensions.api.accounts.AccountInput;
import com.google.gerrit.extensions.api.groups.GroupInput;
import com.google.gerrit.extensions.api.groups.Groups.QueryRequest;
import com.google.gerrit.extensions.common.AccountInfo;
import com.google.gerrit.extensions.common.GroupInfo;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.index.IndexConfig;
import com.google.gerrit.index.QueryOptions;
import com.google.gerrit.index.Schema;
import com.google.gerrit.index.query.FieldBundle;
import com.google.gerrit.lifecycle.LifecycleManager;
import com.google.gerrit.server.AnonymousUser;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.ServerInitiated;
import com.google.gerrit.server.account.AccountCache;
import com.google.gerrit.server.account.AccountManager;
import com.google.gerrit.server.account.Accounts;
import com.google.gerrit.server.account.AccountsUpdate;
import com.google.gerrit.server.account.AuthRequest;
import com.google.gerrit.server.account.GroupCache;
import com.google.gerrit.server.config.AllProjectsName;
import com.google.gerrit.server.group.db.GroupDelta;
import com.google.gerrit.server.group.db.GroupsUpdate;
import com.google.gerrit.server.index.group.GroupField;
import com.google.gerrit.server.index.group.GroupIndex;
import com.google.gerrit.server.index.group.GroupIndexCollection;
import com.google.gerrit.server.schema.SchemaCreator;
import com.google.gerrit.server.util.ManualRequestContext;
import com.google.gerrit.server.util.OneOffRequestContext;
import com.google.gerrit.server.util.RequestContext;
import com.google.gerrit.server.util.ThreadLocalRequestContext;
import com.google.gerrit.testing.GerritServerTests;
import com.google.gerrit.testing.GerritTestName;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Provider;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;

@Ignore
public abstract class AbstractQueryGroupsTest extends GerritServerTests {
  @Rule public final GerritTestName testName = new GerritTestName();

  @Inject protected Accounts accounts;

  @Inject @ServerInitiated protected Provider<AccountsUpdate> accountsUpdate;

  @Inject protected AccountCache accountCache;

  @Inject protected AccountManager accountManager;

  @Inject protected GerritApi gApi;

  @Inject protected IdentifiedUser.GenericFactory userFactory;

  @Inject private Provider<AnonymousUser> anonymousUser;

  @Inject protected SchemaCreator schemaCreator;

  @Inject protected ThreadLocalRequestContext requestContext;

  @Inject protected OneOffRequestContext oneOffRequestContext;

  @Inject protected AllProjectsName allProjects;

  @Inject protected GroupCache groupCache;

  @Inject @ServerInitiated protected Provider<GroupsUpdate> groupsUpdateProvider;

  @Inject protected GroupIndexCollection indexes;

  @Inject protected AuthRequest.Factory authRequestFactory;

  @Inject private GroupIndexCollection groupIndexes;

  protected LifecycleManager lifecycle;
  protected Injector injector;
  protected AccountInfo currentUserInfo;
  protected CurrentUser user;

  protected abstract Injector createInjector();

  protected void validateAssumptions() {}

  @Before
  public void setUpInjector() throws Exception {
    lifecycle = new LifecycleManager();
    injector = createInjector();
    lifecycle.add(injector);
    injector.injectMembers(this);
    lifecycle.start();
    initAfterLifecycleStart();
    setUpDatabase();
    validateAssumptions();
  }

  @After
  public void cleanUp() {
    lifecycle.stop();
  }

  protected void setUpDatabase() throws Exception {
    schemaCreator.create();

    Account.Id userId =
        createAccountOutsideRequestContext("user", "User", "user@example.com", true);
    user = userFactory.create(userId);
    requestContext.setContext(newRequestContext(userId));
    currentUserInfo = gApi.accounts().id(userId.get()).get();
  }

  protected void initAfterLifecycleStart() throws Exception {}

  protected RequestContext newRequestContext(Account.Id requestUserId) {
    final CurrentUser requestUser = userFactory.create(requestUserId);
    return () -> requestUser;
  }

  protected void setAnonymous() {
    requestContext.setContext(anonymousUser::get);
  }

  @After
  public void tearDownInjector() {
    if (lifecycle != null) {
      lifecycle.stop();
    }
    if (requestContext != null) {
      requestContext.setContext(null);
    }
  }

  @Test
  public void byUuid() throws Exception {
    assertQuery("uuid:6d70856bc40ded50f2585c4c0f7e179f3544a272");
    assertQuery("uuid:non-existing");

    GroupInfo group = createGroup(name("group"));
    assertQuery("uuid:" + group.id, group);

    GroupInfo admins = gApi.groups().id("Administrators").get();
    assertQuery("uuid:" + admins.id, admins);
  }

  @Test
  public void byName() throws Exception {
    assertQuery("name:non-existing");

    GroupInfo group = createGroup(name("Group"));
    assertQuery("name:" + group.name, group);
    assertQuery("name:" + group.name.toLowerCase(Locale.US));

    // only exact match
    GroupInfo groupWithHyphen = createGroup(name("group-with-hyphen"));
    createGroup(name("group-no-match-with-hyphen"));
    assertQuery("name:" + groupWithHyphen.name, groupWithHyphen);
  }

  @Test
  public void byInname() throws Exception {
    String namePart = testName.getSanitizedMethodName();
    namePart = CharMatcher.is('_').removeFrom(namePart);

    GroupInfo group1 = createGroup("group-" + namePart);
    GroupInfo group2 = createGroup("group-" + namePart + "-2");
    GroupInfo group3 = createGroup("group-" + namePart + "3");
    assertQuery("inname:" + namePart, group1, group2, group3);
    assertQuery("inname:" + namePart.toUpperCase(Locale.US), group1, group2, group3);
    assertQuery("inname:" + namePart.toLowerCase(Locale.US), group1, group2, group3);
  }

  @Test
  public void byDescription() throws Exception {
    GroupInfo group1 = createGroupWithDescription(name("group1"), "This is a test group.");
    GroupInfo group2 = createGroupWithDescription(name("group2"), "ANOTHER TEST GROUP.");
    createGroupWithDescription(name("group3"), "Maintainers of project foo.");
    assertQuery("description:test", group1, group2);

    assertQuery("description:non-existing");

    BadRequestException thrown =
        assertThrows(BadRequestException.class, () -> assertQuery("description:\"\""));
    assertThat(thrown).hasMessageThat().contains("description operator requires a value");
  }

  @Test
  public void byOwner() throws Exception {
    GroupInfo ownerGroup = createGroup(name("owner-group"));
    GroupInfo group = createGroupWithOwner(name("group"), ownerGroup);
    createGroup(name("group2"));

    assertQuery("owner:" + group.id);

    // ownerGroup owns itself
    assertQuery("owner:" + ownerGroup.id, group, ownerGroup);
    assertQuery("owner:" + ownerGroup.name, group, ownerGroup);
  }

  @Test
  public void byIsVisibleToAll() throws Exception {
    assertQuery("is:visibletoall");

    GroupInfo groupThatIsVisibleToAll =
        createGroupThatIsVisibleToAll(name("group-that-is-visible-to-all"));
    createGroup(name("group"));

    assertQuery("is:visibletoall", groupThatIsVisibleToAll);
  }

  @Test
  public void byMember() throws Exception {
    assume().that(getSchemaVersion() >= 4).isTrue();

    AccountInfo user1 = createAccount("user1", "User1", "user1@example.com");
    AccountInfo user2 = createAccount("user2", "User2", "user2@example.com");

    GroupInfo group1 = createGroup(name("group1"), user1);
    GroupInfo group2 = createGroup(name("group2"), user2);
    GroupInfo group3 = createGroup(name("group3"), user1);

    assertQuery("member:" + user1.name, group1, group3);
    assertQuery("member:" + user1.email, group1, group3);

    gApi.groups().id(group3.id).removeMembers(user1.username);
    gApi.groups().id(group2.id).addMembers(user1.username);

    assertQuery("member:" + user1.name, group1, group2);
  }

  @Test
  public void bySubgroups() throws Exception {
    assume().that(getSchemaVersion() >= 4).isTrue();

    GroupInfo superParentGroup = createGroup(name("superParentGroup"));
    GroupInfo parentGroup1 = createGroup(name("parentGroup1"));
    GroupInfo parentGroup2 = createGroup(name("parentGroup2"));
    GroupInfo subGroup = createGroup(name("subGroup"));

    gApi.groups().id(superParentGroup.id).addGroups(parentGroup1.id, parentGroup2.id);
    gApi.groups().id(parentGroup1.id).addGroups(subGroup.id);
    gApi.groups().id(parentGroup2.id).addGroups(subGroup.id);

    assertQuery("subgroup:" + subGroup.id, parentGroup1, parentGroup2);
    assertQuery("subgroup:" + parentGroup1.id, superParentGroup);

    gApi.groups().id(superParentGroup.id).addGroups(subGroup.id);
    gApi.groups().id(parentGroup1.id).removeGroups(subGroup.id);

    assertQuery("subgroup:" + subGroup.id, superParentGroup, parentGroup2);
  }

  @Test
  public void byDefaultField() throws Exception {
    GroupInfo group1 = createGroup(name("foo-group"));
    GroupInfo group2 = createGroup(name("group2"));
    GroupInfo group3 =
        createGroupWithDescription(
            name("group3"), "decription that contains foo and the UUID of group2: " + group2.id);

    assertQuery("non-existing");
    assertQuery("foo", group1, group3);
    assertQuery(group2.id, group2, group3);
  }

  @Test
  public void withLimit() throws Exception {
    GroupInfo group1 = createGroup(name("group1"));
    GroupInfo group2 = createGroup(name("group2"));
    GroupInfo group3 = createGroup(name("group3"));

    String query = "uuid:" + group1.id + " OR uuid:" + group2.id + " OR uuid:" + group3.id;
    List<GroupInfo> result = assertQuery(query, group1, group2, group3);
    assertThat(result.get(result.size() - 1)._moreGroups).isNull();

    result = assertQuery(newQuery(query).withLimit(2), result.subList(0, 2));
    assertThat(result.get(result.size() - 1)._moreGroups).isTrue();
  }

  @Test
  public void withStart() throws Exception {
    GroupInfo group1 = createGroup(name("group1"));
    GroupInfo group2 = createGroup(name("group2"));
    GroupInfo group3 = createGroup(name("group3"));

    String query = "uuid:" + group1.id + " OR uuid:" + group2.id + " OR uuid:" + group3.id;
    List<GroupInfo> result = assertQuery(query, group1, group2, group3);

    assertQuery(newQuery(query).withStart(1), result.subList(1, 3));
  }

  @Test
  public void sortedByUuid() throws Exception {
    GroupInfo group1 = createGroup(name("group1"));
    GroupInfo group2 = createGroup(name("group2"));
    GroupInfo group3 = createGroup(name("group3"));

    String query = "uuid:" + group1.id + " OR uuid:" + group2.id + " OR uuid:" + group3.id;
    // assertQuery sorts the expected groups by UUID
    assertQuery(newQuery(query), group1, group2, group3);
  }

  @Test
  public void asAnonymous() throws Exception {
    GroupInfo group = createGroup(name("group"));

    setAnonymous();
    assertQuery("uuid:" + group.id);
  }

  // reindex permissions are tested by {@link GroupsIT#reindexPermissions}
  @Test
  public void reindex() throws Exception {
    GroupInfo group1 = createGroupWithDescription(name("group"), "barX");

    // update group in the database so that group index is stale
    String newDescription = "barY";
    AccountGroup.UUID groupUuid = AccountGroup.uuid(group1.id);
    GroupDelta groupDelta = GroupDelta.builder().setDescription(newDescription).build();
    groupsUpdateProvider.get().updateGroupInNoteDb(groupUuid, groupDelta);

    assertQuery("description:" + group1.description, group1);
    assertQuery("description:" + newDescription);

    gApi.groups().id(group1.id).index();
    assertQuery("description:" + group1.description);
    assertQuery("description:" + newDescription, group1);
  }

  @Test
  public void rawDocument() throws Exception {
    GroupInfo group1 = createGroup(name("group1"));
    AccountGroup.UUID uuid = AccountGroup.uuid(group1.id);

    Optional<FieldBundle> rawFields =
        indexes
            .getSearchIndex()
            .getRaw(
                uuid,
                QueryOptions.create(
                    IndexConfig.createDefault(),
                    0,
                    10,
                    indexes.getSearchIndex().getSchema().getStoredFields().keySet()));

    assertThat(rawFields).isPresent();
    assertThat(rawFields.get().getValue(GroupField.UUID)).isEqualTo(uuid.get());
  }

  @Test
  public void byDeletedGroup() throws Exception {
    GroupInfo group = createGroup(name("group"));
    AccountGroup.UUID uuid = AccountGroup.uuid(group.id);
    String query = "uuid:" + uuid;
    assertQuery(query, group);

    for (GroupIndex index : groupIndexes.getWriteIndexes()) {
      index.delete(uuid);
    }
    assertQuery(query);
  }

  private Account.Id createAccountOutsideRequestContext(
      String username, String fullName, String email, boolean active) throws Exception {
    try (ManualRequestContext ctx = oneOffRequestContext.open()) {
      Account.Id id =
          accountManager.authenticate(authRequestFactory.createForUser(username)).getAccountId();
      if (email != null) {
        accountManager.link(id, authRequestFactory.createForEmail(email));
      }
      accountsUpdate
          .get()
          .update(
              "Update Test Account",
              id,
              u -> {
                u.setFullName(fullName).setPreferredEmail(email).setActive(active);
              });
      return id;
    }
  }

  protected AccountInfo createAccount(String username, String fullName, String email)
      throws Exception {
    String uniqueName = name(username);
    AccountInput accountInput = new AccountInput();
    accountInput.username = uniqueName;
    accountInput.name = fullName;
    accountInput.email = email;
    return gApi.accounts().create(accountInput).get();
  }

  protected GroupInfo createGroup(String name, AccountInfo... members) throws Exception {
    return createGroupWithDescription(name, null, members);
  }

  protected GroupInfo createGroupWithDescription(
      String name, String description, AccountInfo... members) throws Exception {
    GroupInput in = new GroupInput();
    in.name = name;
    in.description = description;
    in.members =
        Arrays.asList(members).stream().map(a -> String.valueOf(a._accountId)).collect(toList());
    return gApi.groups().create(in).get();
  }

  protected GroupInfo createGroupWithOwner(String name, GroupInfo ownerGroup) throws Exception {
    GroupInput in = new GroupInput();
    in.name = name;
    in.ownerId = ownerGroup.id;
    return gApi.groups().create(in).get();
  }

  protected GroupInfo createGroupThatIsVisibleToAll(String name) throws Exception {
    GroupInput in = new GroupInput();
    in.name = name;
    in.visibleToAll = true;
    return gApi.groups().create(in).get();
  }

  protected GroupInfo getGroup(AccountGroup.UUID uuid) throws Exception {
    return gApi.groups().id(uuid.get()).get();
  }

  protected List<GroupInfo> assertQuery(Object query, GroupInfo... groups) throws Exception {
    return assertQuery(newQuery(query), groups);
  }

  protected List<GroupInfo> assertQuery(QueryRequest query, GroupInfo... groups) throws Exception {
    return assertQuery(query, Arrays.asList(groups));
  }

  protected List<GroupInfo> assertQuery(QueryRequest query, List<GroupInfo> groups)
      throws Exception {
    List<GroupInfo> result = query.get();
    Iterable<String> uuids = uuids(result);
    assertWithMessage(format(query, result, groups))
        .that(uuids)
        .containsExactlyElementsIn(uuids(groups))
        .inOrder();
    return result;
  }

  protected QueryRequest newQuery(Object query) {
    return gApi.groups().query(query.toString());
  }

  protected String format(
      QueryRequest query, List<GroupInfo> actualGroups, List<GroupInfo> expectedGroups) {
    StringBuilder b = new StringBuilder();
    b.append("query '").append(query.getQuery()).append("' with expected groups ");
    b.append(format(expectedGroups));
    b.append(" and result ");
    b.append(format(actualGroups));
    return b.toString();
  }

  protected String format(Iterable<GroupInfo> groups) {
    StringBuilder b = new StringBuilder();
    b.append("[");
    Iterator<GroupInfo> it = groups.iterator();
    while (it.hasNext()) {
      GroupInfo g = it.next();
      b.append("{")
          .append(g.id)
          .append(", ")
          .append("name=")
          .append(g.name)
          .append(", ")
          .append("groupId=")
          .append(g.groupId)
          .append(", ")
          .append("url=")
          .append(g.url)
          .append(", ")
          .append("ownerId=")
          .append(g.ownerId)
          .append(", ")
          .append("owner=")
          .append(g.owner)
          .append(", ")
          .append("description=")
          .append(g.description)
          .append(", ")
          .append("visibleToAll=")
          .append(toBoolean(g.options.visibleToAll))
          .append("}");
      if (it.hasNext()) {
        b.append(", ");
      }
    }
    b.append("]");
    return b.toString();
  }

  protected static boolean toBoolean(Boolean b) {
    return b == null ? false : b;
  }

  protected static Iterable<String> ids(GroupInfo... groups) {
    return uuids(Arrays.asList(groups));
  }

  protected static Iterable<String> uuids(List<GroupInfo> groups) {
    return groups.stream().map(g -> g.id).sorted().collect(toList());
  }

  protected String name(String name) {
    if (name == null) {
      return null;
    }

    return name + "_" + testName.getSanitizedMethodName();
  }

  protected int getSchemaVersion() {
    return getSchema().getVersion();
  }

  protected Schema<InternalGroup> getSchema() {
    return indexes.getSearchIndex().getSchema();
  }
}
