// 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.server.account;

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.gerrit.testing.GerritJUnit.assertThrows;

import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.config.GerritConfig;
import com.google.gerrit.acceptance.testsuite.account.AccountOperations;
import com.google.gerrit.acceptance.testsuite.account.TestAccount;
import com.google.gerrit.acceptance.testsuite.group.GroupOperations;
import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
import com.google.gerrit.entities.Account;
import com.google.gerrit.extensions.common.AccountVisibility;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.ServerInitiated;
import com.google.gerrit.server.account.AccountControl;
import com.google.gerrit.server.account.AccountResolver;
import com.google.gerrit.server.account.AccountResolver.Result;
import com.google.gerrit.server.account.AccountResolver.UnresolvableAccountException;
import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.account.AccountsUpdate;
import com.google.gerrit.server.account.externalids.ExternalId;
import com.google.gerrit.server.notedb.Sequences;
import com.google.gerrit.testing.ConfigSuite;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.util.Optional;
import org.eclipse.jgit.lib.Config;
import org.junit.Test;

public class AccountResolverIT extends AbstractDaemonTest {
  @ConfigSuite.Default
  public static Config defaultConfig() {
    Config cfg = new Config();
    cfg.setEnum("accounts", null, "visibility", AccountVisibility.SAME_GROUP);
    return cfg;
  }

  @Inject @ServerInitiated private Provider<AccountsUpdate> accountsUpdateProvider;
  @Inject private AccountOperations accountOperations;
  @Inject private AccountResolver accountResolver;
  @Inject private AccountControl.Factory accountControlFactory;
  @Inject private Provider<CurrentUser> self;
  @Inject private GroupOperations groupOperations;
  @Inject private RequestScopeOperations requestScopeOperations;
  @Inject private Sequences sequences;

  @Test
  public void bySelf() throws Exception {
    assertThat(resolve("Self")).isEmpty();
    accountOperations.newAccount().fullname("self").create();

    Result result = resolveAsResult("self");
    assertThat(result.asIdSet()).containsExactly(admin.id());
    assertThat(result.isSelf()).isTrue();
    assertThat(result.asUniqueUser()).isSameInstanceAs(self.get());

    result = resolveAsResult("me");
    assertThat(result.asIdSet()).containsExactly(admin.id());
    assertThat(result.isSelf()).isTrue();
    assertThat(result.asUniqueUser()).isSameInstanceAs(self.get());

    requestScopeOperations.setApiUserAnonymous();
    checkBySelfFails();

    requestScopeOperations.setApiUserInternal();
    checkBySelfFails();
  }

  private void checkBySelfFails() throws Exception {
    for (String input : ImmutableList.of("self", "me")) {
      Result result = resolveAsResult(input);
      assertThat(result.asIdSet()).isEmpty();
      assertThat(result.isSelf()).isTrue();
      UnresolvableAccountException thrown =
          assertThrows(UnresolvableAccountException.class, () -> result.asUnique());
      assertThat(thrown)
          .hasMessageThat()
          .isEqualTo(String.format("Resolving account '%s' requires login", input));
      assertThat(thrown.isSelf()).isTrue();
    }
  }

  @Test
  public void bySelfInactive() throws Exception {
    gApi.accounts().id(user.id().get()).setActive(false);

    requestScopeOperations.setApiUser(user.id());
    assertThat(gApi.accounts().id("self").getActive()).isFalse();

    Result result = resolveAsResult("self");
    assertThat(result.asIdSet()).containsExactly(user.id());
    assertThat(result.isSelf()).isTrue();
    assertThat(result.asUniqueUser()).isSameInstanceAs(self.get());
  }

  @Test
  public void byExactAccountId() throws Exception {
    Account.Id existingId = accountOperations.newAccount().create();
    Account.Id idWithExistingIdAsFullname =
        accountOperations.newAccount().fullname(existingId.toString()).create();

    Account.Id nonexistentId = Account.id(sequences.nextAccountId());
    accountOperations.newAccount().fullname(nonexistentId.toString()).create();

    assertThat(resolve(existingId)).containsExactly(existingId);
    assertThat(resolve(nonexistentId)).isEmpty();

    assertThat(resolveByNameOrEmail(existingId)).containsExactly(idWithExistingIdAsFullname);
  }

  @Test
  public void byParenthesizedAccountId() throws Exception {
    Account.Id existingId = accountOperations.newAccount().fullname("Test User").create();
    accountOperations.newAccount().fullname(existingId.toString()).create();

    Account.Id nonexistentId = Account.id(sequences.nextAccountId());
    accountOperations.newAccount().fullname("Any Name (" + nonexistentId + ")").create();
    accountOperations.newAccount().fullname(nonexistentId.toString()).create();

    String existingInput = "Any Name (" + existingId + ")";
    assertThat(resolve(existingInput)).containsExactly(existingId);
    assertThat(resolve("Any Name (" + nonexistentId + ")")).isEmpty();

    assertThat(resolveByNameOrEmail(existingInput)).isEmpty();
  }

  @Test
  public void byUsername() throws Exception {
    String existingUsername = "myusername";
    Account.Id idWithUsername = accountOperations.newAccount().username(existingUsername).create();
    Account.Id idWithExistingUsernameAsFullname =
        accountOperations.newAccount().fullname(existingUsername).create();

    String nonexistentUsername = "anotherusername";
    Account.Id idWithFullname = accountOperations.newAccount().fullname("anotherusername").create();

    assertThat(resolve(existingUsername)).containsExactly(idWithUsername);

    // Doesn't short-circuit just because the input looks like a valid username.
    assertThat(ExternalId.isValidUsername(nonexistentUsername)).isTrue();
    assertThat(resolve(nonexistentUsername)).containsExactly(idWithFullname);

    assertThat(resolveByNameOrEmail(existingUsername))
        .containsExactly(idWithExistingUsernameAsFullname);
  }

  @Test
  @GerritConfig(name = "auth.userNameCaseInsensitive", value = "true")
  public void byUsernameCaseInsensitive() throws Exception {
    String existingUsername = "myusername";
    Account.Id idWithUsername = accountOperations.newAccount().username(existingUsername).create();

    String existingMixedCaseUsername = "MyMixedCaseUsername";
    Account.Id idWithMixedCaseUsername =
        accountOperations.newAccount().username(existingMixedCaseUsername).create();

    assertThat(resolve(existingUsername)).containsExactly(idWithUsername);
    assertThat(resolve(existingMixedCaseUsername)).containsExactly(idWithMixedCaseUsername);
    assertThat(resolve(existingMixedCaseUsername.toLowerCase()))
        .containsExactly(idWithMixedCaseUsername);
  }

  @Test
  public void byNameAndEmail() throws Exception {
    String email = name("user@example.com");
    Account.Id idWithEmail = accountOperations.newAccount().preferredEmail(email).create();
    accountOperations.newAccount().fullname(email).create();

    String input = "First Last <" + email + ">";
    assertThat(resolve(input)).containsExactly(idWithEmail);
    assertThat(resolveByNameOrEmail(input)).containsExactly(idWithEmail);
  }

  @Test
  public void byUserNameOrFullNameOrEmailExact() throws Exception {
    String userName = "UserFoo";
    String fullName = "Name Foo";
    String email = "emailfoo@something.com";
    Account.Id id =
        accountOperations
            .newAccount()
            .username(userName)
            .fullname(fullName)
            .preferredEmail(email)
            .create();

    // resolver returns results for exact matches
    assertThat(resolveByExactNameOrEmail(userName)).containsExactly(id);
    assertThat(resolveByExactNameOrEmail(fullName)).containsExactly(id);
    assertThat(resolveByExactNameOrEmail(email)).containsExactly(id);

    // resolver does not match with prefixes
    assertThat(resolveByExactNameOrEmail("UserF")).isEmpty();
    assertThat(resolveByExactNameOrEmail("Name F")).isEmpty();
    assertThat(resolveByExactNameOrEmail("emailf")).isEmpty();

    /* The default name/email resolver accepts prefix matches */
    assertThat(resolveByNameOrEmail("emai")).containsExactly(id);
  }

  @Test
  public void byNameAndEmailPrefersAccountsWithMatchingFullName() throws Exception {
    String email = name("user@example.com");
    Account.Id id1 = accountOperations.newAccount().fullname("Aaa Bbb").create();
    setPreferredEmailBypassingUniquenessCheck(id1, email);
    Account.Id id2 = accountOperations.newAccount().fullname("Ccc Ddd").create();
    setPreferredEmailBypassingUniquenessCheck(id2, email);

    String input = "First Last <" + email + ">";
    assertThat(resolve(input)).containsExactly(id1, id2);
    assertThat(resolveByNameOrEmail(input)).containsExactly(id1, id2);

    Account.Id id3 = accountOperations.newAccount().fullname("First Last").create();
    setPreferredEmailBypassingUniquenessCheck(id3, email);
    assertThat(resolve(input)).containsExactly(id3);
    assertThat(resolveByNameOrEmail(input)).containsExactly(id3);

    Account.Id id4 = accountOperations.newAccount().fullname("First Last").create();
    setPreferredEmailBypassingUniquenessCheck(id4, email);
    assertThat(resolve(input)).containsExactly(id3, id4);
    assertThat(resolveByNameOrEmail(input)).containsExactly(id3, id4);
  }

  @Test
  public void byEmail() throws Exception {
    String email = name("user@example.com");
    Account.Id idWithEmail = accountOperations.newAccount().preferredEmail(email).create();
    accountOperations.newAccount().fullname(email).create();

    assertThat(resolve(email)).containsExactly(idWithEmail);
    assertThat(resolveByNameOrEmail(email)).containsExactly(idWithEmail);
  }

  // Can't test for ByRealm because DefaultRealm with the default (OPENID) auth type doesn't support
  // email expansion, so anything that would return a non-null value from DefaultRealm#lookup would
  // just be an email address, handled by other tests. This could be avoided if we inject some sort
  // of custom test realm instance, but the ugliness is not worth it for this small bit of test
  // coverage.

  @Test
  public void byFullName() throws Exception {
    Account.Id id1 = accountOperations.newAccount().fullname("Somebodys Name").create();
    accountOperations.newAccount().fullname("A totally different name").create();
    String input = "Somebodys name";
    assertThat(resolve(input)).containsExactly(id1);
    assertThat(resolveByNameOrEmail(input)).containsExactly(id1);
  }

  @Test
  public void byDefaultSearch() throws Exception {
    Account.Id id1 = accountOperations.newAccount().fullname("John Doe").create();
    Account.Id id2 = accountOperations.newAccount().fullname("Jane Doe").create();
    assertThat(resolve("doe")).containsExactly(id1, id2);
    assertThat(resolveByNameOrEmail("doe")).containsExactly(id1, id2);
  }

  @Test
  public void onlyExactIdReturnsInactiveAccounts() throws Exception {
    TestAccount account =
        accountOperations
            .account(
                accountOperations
                    .newAccount()
                    .fullname("Inactiveuser Name")
                    .preferredEmail("inactiveuser@example.com")
                    .username("inactiveusername")
                    .create())
            .get();
    Account.Id id = account.accountId();
    String nameEmail = account.fullname().get() + " <" + account.preferredEmail().get() + ">";
    ImmutableList<String> inputs =
        ImmutableList.of(
            account.fullname().get() + " (" + account.accountId() + ")",
            account.fullname().get(),
            account.preferredEmail().get(),
            nameEmail,
            Splitter.on(' ').splitToList(account.fullname().get()).get(0));

    assertThat(resolve(account.accountId())).containsExactly(id);
    for (String input : inputs) {
      assertWithMessage("results for %s (active)", input).that(resolve(input)).containsExactly(id);
    }

    gApi.accounts().id(id.get()).setActive(false);
    assertThat(resolve(account.accountId())).containsExactly(id);
    for (String input : inputs) {
      Result result = accountResolver.resolve(input);
      assertWithMessage("results for %s (inactive)", input).that(result.asIdSet()).isEmpty();
      UnresolvableAccountException thrown =
          assertThrows(UnresolvableAccountException.class, () -> result.asUnique());
      assertThat(thrown)
          .hasMessageThat()
          .isEqualTo(
              "Account '"
                  + input
                  + "' only matches inactive accounts. To use an inactive account, retry"
                  + " with one of the following exact account IDs:\n"
                  + id
                  + ": "
                  + nameEmail);
      assertWithMessage("results by name or email for %s (inactive)", input)
          .that(resolveByNameOrEmail(input))
          .isEmpty();
    }
  }

  @Test
  public void filterVisibility() throws Exception {
    Account.Id id1 =
        accountOperations
            .newAccount()
            .fullname("John Doe")
            .preferredEmail("johndoe@example.com")
            .create();
    Account.Id id2 =
        accountOperations
            .newAccount()
            .fullname("Jane Doe")
            .preferredEmail("janedoe@example.com")
            .create();

    // Admin can see all accounts. Use a variety of searches, including with/without
    // callerMayAssumeCandidatesAreVisible.
    assertThat(resolve(id1)).containsExactly(id1);
    assertThat(resolve("John Doe")).containsExactly(id1);
    assertThat(resolve("johndoe@example.com")).containsExactly(id1);
    assertThat(resolve(id2)).containsExactly(id2);
    assertThat(resolve("Jane Doe")).containsExactly(id2);
    assertThat(resolve("janedoe@example.com")).containsExactly(id2);
    assertThat(resolve("doe")).containsExactly(id1, id2);

    // id2 can't see id1, and vice versa.
    requestScopeOperations.setApiUser(id1);
    assertThat(resolve(id1)).containsExactly(id1);
    assertThat(resolve("John Doe")).containsExactly(id1);
    assertThat(resolve("johndoe@example.com")).containsExactly(id1);
    assertThat(resolve(id2)).isEmpty();
    assertThat(resolve("Jane Doe")).isEmpty();
    assertThat(resolve("janedoe@example.com")).isEmpty();
    assertThat(resolve("doe")).containsExactly(id1);

    requestScopeOperations.setApiUser(id2);
    assertThat(resolve(id1)).isEmpty();
    assertThat(resolve("John Doe")).isEmpty();
    assertThat(resolve("johndoe@example.com")).isEmpty();
    assertThat(resolve(id2)).containsExactly(id2);
    assertThat(resolve("Jane Doe")).containsExactly(id2);
    assertThat(resolve("janedoe@example.com")).containsExactly(id2);
    assertThat(resolve("doe")).containsExactly(id2);
  }

  @Test
  @GerritConfig(name = "accounts.visibility", value = "SAME_GROUP")
  public void resolveAsUser_byFullName_accountThatIsNotVisibleToCurrentUserIsFound()
      throws Exception {
    Account.Id currentUser = accountOperations.newAccount().create();
    Account.Id resolveAsUser = accountOperations.newAccount().create();
    Account.Id userToBeFound = accountOperations.newAccount().fullname("Somebodys Name").create();

    // Create a group that contains resolveAsUser and userToBeFound, so that resolveAsUser can see
    // userToBeFound.
    groupOperations.newGroup().addMember(resolveAsUser).addMember(userToBeFound).create();

    // Verify that resolveAsUser can see userToBeFound.
    assertThat(canSee(resolveAsUser, userToBeFound)).isTrue();

    // Verify that currentUser cannot see userToBeFound
    assertThat(canSee(currentUser, userToBeFound)).isFalse();

    // Resolving userToBeFound as resolveAsUser should work even if the currentUser cannot see
    // userToBeFound.
    requestScopeOperations.setApiUser(currentUser);
    String input = accountOperations.account(userToBeFound).get().fullname().get();
    assertThat(resolveAsUser(resolveAsUser, input)).containsExactly(userToBeFound);
  }

  private boolean canSee(Account.Id currentUser, Account.Id userToBeSeen) {
    return accountControlFactory
        .get(identifiedUserFactory.create(currentUser))
        .canSee(userToBeSeen);
  }

  private ImmutableSet<Account.Id> resolve(Object input) throws Exception {
    return resolveAsResult(input).asIdSet();
  }

  private Result resolveAsResult(Object input) throws Exception {
    return accountResolver.resolve(input.toString());
  }

  private ImmutableSet<Account.Id> resolveAsUser(Account.Id resolveAsUser, Object input)
      throws Exception {
    return resolveAsUserAsResult(resolveAsUser, input).asIdSet();
  }

  private Result resolveAsUserAsResult(Account.Id resolveAsUser, Object input) throws Exception {
    return accountResolver.resolveAsUser(
        identifiedUserFactory.create(resolveAsUser), input.toString());
  }

  @SuppressWarnings("deprecation")
  private ImmutableSet<Account.Id> resolveByNameOrEmail(Object input) throws Exception {
    return accountResolver.resolveByNameOrEmail(input.toString()).asIdSet();
  }

  @SuppressWarnings("deprecation")
  private ImmutableSet<Account.Id> resolveByExactNameOrEmail(Object input) throws Exception {
    return accountResolver.resolveByExactNameOrEmail(input.toString()).asIdSet();
  }

  private void setPreferredEmailBypassingUniquenessCheck(Account.Id id, String email)
      throws Exception {
    Optional<AccountState> result =
        accountsUpdateProvider
            .get()
            .update("Force set preferred email", id, (s, u) -> u.setPreferredEmail(email));
    assertThat(result.map(a -> a.account().preferredEmail())).hasValue(email);
  }
}
