// 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.plugins.checks.acceptance.api;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth8.assertThat;
import static com.google.gerrit.git.testing.CommitSubject.assertCommit;
import static com.google.gerrit.testing.GerritJUnit.assertThrows;

import com.google.common.collect.ImmutableSet;
import com.google.gerrit.acceptance.SkipProjectClone;
import com.google.gerrit.acceptance.UseClockStep;
import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
import com.google.gerrit.entities.Project;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
import com.google.gerrit.plugins.checks.Checker;
import com.google.gerrit.plugins.checks.CheckerQuery;
import com.google.gerrit.plugins.checks.CheckerUuid;
import com.google.gerrit.plugins.checks.acceptance.AbstractCheckersTest;
import com.google.gerrit.plugins.checks.acceptance.testsuite.CheckerOperations.PerCheckerOperations;
import com.google.gerrit.plugins.checks.acceptance.testsuite.CheckerTestData;
import com.google.gerrit.plugins.checks.api.BlockingCondition;
import com.google.gerrit.plugins.checks.api.CheckerInfo;
import com.google.gerrit.plugins.checks.api.CheckerInput;
import com.google.gerrit.plugins.checks.api.CheckerStatus;
import com.google.gerrit.plugins.checks.db.CheckersByRepositoryNotes;
import com.google.gerrit.testing.ConfigSuite;
import com.google.gerrit.testing.TestTimeUtil;
import com.google.inject.Inject;
import java.sql.Timestamp;
import java.util.Optional;
import org.eclipse.jgit.lib.Config;
import org.junit.Test;

@SkipProjectClone
@UseClockStep(startAtEpoch = true)
public class UpdateCheckerIT extends AbstractCheckersTest {
  private static final int MAX_INDEX_TERMS = 10;

  @ConfigSuite.Default
  public static Config defaultConfig() {
    Config cfg = new Config();
    cfg.setInt("index", null, "maxTerms", MAX_INDEX_TERMS);
    return cfg;
  }

  @Inject private RequestScopeOperations requestScopeOperations;
  @Inject private ProjectOperations projectOperations;

  @Test
  public void updateMultipleCheckerPropertiesAtOnce() throws Exception {
    CheckerUuid checkerUuid =
        checkerOperations.newChecker().name("my-checker").repository(allProjects).create();
    Checker checker = checkerOperations.checker(checkerUuid).get();

    Project.NameKey repositoryName = projectOperations.newProject().create();

    CheckerInput input = new CheckerInput();
    input.name = "my-renamed-checker";
    input.description = "A description.";
    input.url = "http://example.com/my-checker";
    input.repository = repositoryName.get();

    CheckerInfo info = checkersApi.id(checkerUuid).update(input);
    assertThat(info.uuid).isEqualTo(checkerUuid.get());
    assertThat(info.name).isEqualTo(input.name);
    assertThat(info.description).isEqualTo(input.description);
    assertThat(info.url).isEqualTo(input.url);
    assertThat(info.repository).isEqualTo(input.repository);
    assertThat(info.created).isEqualTo(checker.getCreated());
    assertThat(info.created).isLessThan(info.updated);

    PerCheckerOperations perCheckerOps = checkerOperations.checker(checkerUuid);
    assertCommit(
        perCheckerOps.commit(), "Update checker", info.updated, perCheckerOps.get().getRefState());
    assertThat(checkerOperations.sha1sOfRepositoriesWithCheckers())
        .containsExactly(CheckersByRepositoryNotes.computeRepositorySha1(repositoryName));
    assertThat(checkerOperations.checkersOf(repositoryName))
        .containsExactly(CheckerUuid.parse(info.uuid));
  }

  @Test
  public void uuidCannotBeUpdated() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().create();

    CheckerInput input = new CheckerInput();
    input.uuid = "some:id";

    BadRequestException thrown =
        assertThrows(BadRequestException.class, () -> checkersApi.id(checkerUuid).update(input));
    assertThat(thrown).hasMessageThat().contains("uuid cannot be updated");
  }

  @Test
  public void uuidIsAllowedIfItMatchesCurrentUuid() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().create();

    CheckerInput input = new CheckerInput();
    input.uuid = checkerUuid.get();
    input.name = "some-name";

    CheckerInfo info = checkersApi.id(checkerUuid).update(input);
    assertThat(info.uuid).isEqualTo(input.uuid);
    assertThat(info.name).isEqualTo(input.name);
  }

  @Test
  public void updateCheckerName() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().name("my-checker").create();

    CheckerInput input = new CheckerInput();
    input.name = "my-renamed-checker";

    CheckerInfo info = checkersApi.id(checkerUuid).update(input);
    assertThat(info.name).isEqualTo(input.name);

    PerCheckerOperations perCheckerOps = checkerOperations.checker(checkerUuid);
    assertCommit(
        perCheckerOps.commit(), "Update checker", info.updated, perCheckerOps.get().getRefState());
  }

  @Test
  public void cannotSetCheckerNameToEmptyString() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().name("my-checker").create();

    CheckerInput checkerInput = new CheckerInput();
    checkerInput.name = "";

    BadRequestException thrown =
        assertThrows(
            BadRequestException.class, () -> checkersApi.id(checkerUuid).update(checkerInput));
    assertThat(thrown).hasMessageThat().contains("name cannot be unset");
  }

  @Test
  public void cannotSetCheckerNameToStringWhichIsEmptyAfterTrim() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().name("my-checker").create();

    CheckerInput checkerInput = new CheckerInput();
    checkerInput.name = " ";

    BadRequestException thrown =
        assertThrows(
            BadRequestException.class, () -> checkersApi.id(checkerUuid).update(checkerInput));
    assertThat(thrown).hasMessageThat().contains("name cannot be unset");
  }

  @Test
  public void updateCheckerNameToNameThatIsAlreadyUsed() throws Exception {
    checkerOperations.newChecker().name("other-checker").create();

    CheckerUuid checkerUuid = checkerOperations.newChecker().name("my-checker").create();

    CheckerInput input = new CheckerInput();
    input.name = "other-checker";

    CheckerInfo info = checkersApi.id(checkerUuid).update(input);
    assertThat(info.name).isEqualTo(input.name);

    PerCheckerOperations perCheckerOps = checkerOperations.checker(checkerUuid);
    assertCommit(
        perCheckerOps.commit(), "Update checker", info.updated, perCheckerOps.get().getRefState());
  }

  @Test
  public void addCheckerDescription() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().create();

    CheckerInput input = new CheckerInput();
    input.description = "A description.";

    CheckerInfo info = checkersApi.id(checkerUuid).update(input);
    assertThat(info.description).isEqualTo(input.description);

    PerCheckerOperations perCheckerOps = checkerOperations.checker(checkerUuid);
    assertCommit(
        perCheckerOps.commit(), "Update checker", info.updated, perCheckerOps.get().getRefState());
  }

  @Test
  public void updateCheckerDescription() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().description("A description.").create();

    CheckerInput input = new CheckerInput();
    input.description = "A new description.";

    CheckerInfo info = checkersApi.id(checkerUuid).update(input);
    assertThat(info.description).isEqualTo(input.description);

    PerCheckerOperations perCheckerOps = checkerOperations.checker(checkerUuid);
    assertCommit(
        perCheckerOps.commit(), "Update checker", info.updated, perCheckerOps.get().getRefState());
  }

  @Test
  public void unsetCheckerDescription() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().description("A description.").create();

    CheckerInput checkerInput = new CheckerInput();
    checkerInput.description = "";

    CheckerInfo info = checkersApi.id(checkerUuid).update(checkerInput);
    assertThat(info.description).isNull();

    PerCheckerOperations perCheckerOps = checkerOperations.checker(checkerUuid);
    assertCommit(
        perCheckerOps.commit(), "Update checker", info.updated, perCheckerOps.get().getRefState());
  }

  @Test
  public void checkerDescriptionIsTrimmed() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().create();

    CheckerInput input = new CheckerInput();
    input.description = " A description. ";

    CheckerInfo info = checkersApi.id(checkerUuid).update(input);
    assertThat(info.description).isEqualTo("A description.");

    PerCheckerOperations perCheckerOps = checkerOperations.checker(checkerUuid);
    assertCommit(
        perCheckerOps.commit(), "Update checker", info.updated, perCheckerOps.get().getRefState());
  }

  @Test
  public void addCheckerUrl() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().create();

    CheckerInput input = new CheckerInput();
    input.url = "http://example.com/my-checker";

    CheckerInfo info = checkersApi.id(checkerUuid).update(input);
    assertThat(info.url).isEqualTo(input.url);

    PerCheckerOperations perCheckerOps = checkerOperations.checker(checkerUuid);
    assertCommit(
        perCheckerOps.commit(), "Update checker", info.updated, perCheckerOps.get().getRefState());
  }

  @Test
  public void updateCheckerUrl() throws Exception {
    CheckerUuid checkerUuid =
        checkerOperations.newChecker().url("http://example.com/my-checker").create();

    CheckerInput input = new CheckerInput();
    input.url = "http://example.com/my-checker-foo";

    CheckerInfo info = checkersApi.id(checkerUuid).update(input);
    assertThat(info.url).isEqualTo(input.url);

    PerCheckerOperations perCheckerOps = checkerOperations.checker(checkerUuid);
    assertCommit(
        perCheckerOps.commit(), "Update checker", info.updated, perCheckerOps.get().getRefState());
  }

  @Test
  public void unsetCheckerUrl() throws Exception {
    CheckerUuid checkerUuid =
        checkerOperations.newChecker().url("http://example.com/my-checker").create();

    CheckerInput checkerInput = new CheckerInput();
    checkerInput.url = "";

    CheckerInfo info = checkersApi.id(checkerUuid).update(checkerInput);
    assertThat(info.url).isNull();

    PerCheckerOperations perCheckerOps = checkerOperations.checker(checkerUuid);
    assertCommit(
        perCheckerOps.commit(), "Update checker", info.updated, perCheckerOps.get().getRefState());
  }

  @Test
  public void checkerUrlIsTrimmed() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().create();

    CheckerInput input = new CheckerInput();
    input.url = " http://example.com/my-checker ";

    CheckerInfo info = checkersApi.id(checkerUuid).update(input);
    assertThat(info.url).isEqualTo("http://example.com/my-checker");

    PerCheckerOperations perCheckerOps = checkerOperations.checker(checkerUuid);
    assertCommit(
        perCheckerOps.commit(), "Update checker", info.updated, perCheckerOps.get().getRefState());
  }

  @Test
  public void updateRepository() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().repository(allProjects).create();

    Project.NameKey repositoryName = projectOperations.newProject().create();

    CheckerInput input = new CheckerInput();
    input.repository = repositoryName.get();

    CheckerInfo info = checkersApi.id(checkerUuid).update(input);
    assertThat(info.repository).isEqualTo(input.repository);

    PerCheckerOperations perCheckerOps = checkerOperations.checker(checkerUuid);
    assertCommit(
        perCheckerOps.commit(), "Update checker", info.updated, perCheckerOps.get().getRefState());
    assertThat(checkerOperations.sha1sOfRepositoriesWithCheckers())
        .containsExactly(CheckersByRepositoryNotes.computeRepositorySha1(repositoryName));
    assertThat(checkerOperations.checkersOf(repositoryName))
        .containsExactly(CheckerUuid.parse(info.uuid));
  }

  @Test
  public void cannotSetRepositoryToEmptyString() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().create();

    CheckerInput checkerInput = new CheckerInput();
    checkerInput.repository = "";

    BadRequestException thrown =
        assertThrows(
            BadRequestException.class, () -> checkersApi.id(checkerUuid).update(checkerInput));
    assertThat(thrown).hasMessageThat().contains("repository cannot be unset");
  }

  @Test
  public void cannotSetRepositoryToStringWhichIsEmptyAfterTrim() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().create();

    CheckerInput checkerInput = new CheckerInput();
    checkerInput.repository = " ";

    BadRequestException thrown =
        assertThrows(
            BadRequestException.class, () -> checkersApi.id(checkerUuid).update(checkerInput));
    assertThat(thrown).hasMessageThat().contains("repository cannot be unset");
  }

  @Test
  public void cannotSetNonExistingRepository() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().create();

    CheckerInput checkerInput = new CheckerInput();
    checkerInput.repository = "non-existing";

    UnprocessableEntityException thrown =
        assertThrows(
            UnprocessableEntityException.class,
            () -> checkersApi.id(checkerUuid).update(checkerInput));
    assertThat(thrown).hasMessageThat().contains("repository non-existing not found");
  }

  @Test
  public void cannotSetUrlToInvalidUrl() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().create();

    CheckerInput input = new CheckerInput();
    input.url = CheckerTestData.INVALID_URL;
    BadRequestException thrown =
        assertThrows(BadRequestException.class, () -> checkersApi.id(checkerUuid).update(input));
    assertThat(thrown)
        .hasMessageThat()
        .contains("only http/https URLs supported: ftp://example.com/my-checker");
  }

  @Test
  public void disableAndReenable() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().repository(allProjects).create();
    assertThat(checkerOperations.checkersOf(allProjects)).containsExactly(checkerUuid);

    CheckerInput input = new CheckerInput();
    input.status = CheckerStatus.DISABLED;

    CheckerInfo info = checkersApi.id(checkerUuid).update(input);
    assertThat(info.status).isEqualTo(CheckerStatus.DISABLED);
    assertThat(checkerOperations.checkersOf(allProjects)).isEmpty();

    input = new CheckerInput();
    input.status = CheckerStatus.ENABLED;
    info = checkersApi.id(checkerUuid).update(input);
    assertThat(info.status).isEqualTo(CheckerStatus.ENABLED);
    assertThat(checkerOperations.checkersOf(allProjects)).containsExactly(checkerUuid);
  }

  @Test
  public void updateRepositoryDuringDisable() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().repository(allProjects).create();

    Project.NameKey repositoryName = projectOperations.newProject().create();

    CheckerInput input = new CheckerInput();
    input.repository = repositoryName.get();
    input.status = CheckerStatus.DISABLED;

    CheckerInfo info = checkersApi.id(checkerUuid).update(input);
    assertThat(info.repository).isEqualTo(input.repository);
    assertThat(info.status).isEqualTo(CheckerStatus.DISABLED);
    assertThat(checkerOperations.checkersOf(allProjects)).isEmpty();
  }

  @Test
  public void updateRepositoryDuringEnable() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().repository(allProjects).create();

    Project.NameKey repositoryName = projectOperations.newProject().create();
    assertThat(checkerOperations.checkersOf(allProjects)).containsExactly(checkerUuid);
    assertThat(checkerOperations.checkersOf(repositoryName)).isEmpty();

    CheckerInput input = new CheckerInput();
    input.status = CheckerStatus.DISABLED;

    CheckerInfo info = checkersApi.id(checkerUuid).update(input);
    assertThat(info.status).isEqualTo(CheckerStatus.DISABLED);
    assertThat(checkerOperations.checkersOf(allProjects)).isEmpty();
    assertThat(checkerOperations.checkersOf(repositoryName)).isEmpty();

    input = new CheckerInput();
    input.status = CheckerStatus.ENABLED;
    input.repository = repositoryName.get();
    info = checkersApi.id(checkerUuid).update(input);
    assertThat(info.status).isEqualTo(CheckerStatus.ENABLED);
    assertThat(checkerOperations.checkersOf(allProjects)).isEmpty();
    assertThat(checkerOperations.checkersOf(repositoryName)).containsExactly(checkerUuid);
  }

  @Test
  public void updateCheckerWithBlockingConditions() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().create();

    CheckerInput input = new CheckerInput();
    input.blocking = ImmutableSet.of(BlockingCondition.STATE_NOT_PASSING);
    CheckerInfo info = checkersApi.id(checkerUuid).update(input);
    assertThat(info.blocking).containsExactly(BlockingCondition.STATE_NOT_PASSING);
  }

  @Test
  public void updateQuery() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().create();

    CheckerInput input = new CheckerInput();
    input.query = "f:foo";

    CheckerInfo info = checkersApi.id(checkerUuid).update(input);
    assertThat(info.query).isEqualTo("f:foo");

    input = new CheckerInput();
    input.query = "";

    info = checkersApi.id(checkerUuid).update(input);
    assertThat(info.query).isNull();
  }

  @Test
  public void updateWithEmptyQueryAfterTrimClearsQuery() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().create();

    CheckerInput input = new CheckerInput();
    input.query = "f:foo";

    CheckerInfo info = checkersApi.id(checkerUuid).update(input);
    assertThat(info.query).isEqualTo("f:foo");

    input = new CheckerInput();
    input.query = " ";

    info = checkersApi.id(checkerUuid).update(input);
    assertThat(info.query).isNull();
  }

  @Test
  public void updateWithUnsupportedOperatorInQuery() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().create();
    Optional<String> oldQuery = checkerOperations.checker(checkerUuid).get().getQuery();

    CheckerInput input = new CheckerInput();
    input.query = CheckerTestData.QUERY_WITH_UNSUPPORTED_OPERATOR;
    BadRequestException thrown =
        assertThrows(BadRequestException.class, () -> checkersApi.id(checkerUuid).update(input));
    assertThat(thrown)
        .hasMessageThat()
        .isEqualTo("Unsupported operator: " + CheckerTestData.UNSUPPORTED_OPERATOR);

    assertThat(checkerOperations.checker(checkerUuid).get().getQuery()).isEqualTo(oldQuery);
  }

  @Test
  public void updateWithInvalidQuery() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().create();
    Optional<String> oldQuery = checkerOperations.checker(checkerUuid).get().getQuery();

    CheckerInput input = new CheckerInput();
    input.query = CheckerTestData.INVALID_QUERY;
    BadRequestException thrown =
        assertThrows(BadRequestException.class, () -> checkersApi.id(checkerUuid).update(input));
    assertThat(thrown).hasMessageThat().contains("Invalid query: " + input.query);

    assertThat(checkerOperations.checker(checkerUuid).get().getQuery()).isEqualTo(oldQuery);
  }

  @Test
  public void updateWithTooLongQuery() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().create();
    Optional<String> oldQuery = checkerOperations.checker(checkerUuid).get().getQuery();

    CheckerInput input = new CheckerInput();
    input.query = CheckerTestData.longQueryWithSupportedOperators(MAX_INDEX_TERMS * 2);
    assertThat(CheckerQuery.clean(input.query)).isEqualTo(input.query);
    BadRequestException thrown =
        assertThrows(BadRequestException.class, () -> checkersApi.id(checkerUuid).update(input));
    assertThat(thrown)
        .hasMessageThat()
        .isEqualTo(
            "change query of checker "
                + checkerUuid
                + " is invalid: "
                + input.query
                + " (too many terms in query)");

    assertThat(checkerOperations.checker(checkerUuid).get().getQuery()).isEqualTo(oldQuery);
  }

  @Test
  public void updateResultsInNewUpdatedTimestamp() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().create();

    Timestamp expectedUpdateTimestamp = TestTimeUtil.getCurrentTimestamp();
    CheckerInput input = new CheckerInput();
    input.name = "My Checker";
    CheckerInfo info = checkersApi.id(checkerUuid).update(input);
    assertThat(info.updated).isEqualTo(expectedUpdateTimestamp);
  }

  @Test
  public void noOpUpdateDoesntResultInNewUpdatedTimestamp() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().name("My Checker").create();

    Timestamp expectedUpdateTimestamp = checkerOperations.checker(checkerUuid).get().getUpdated();

    CheckerInput input = new CheckerInput();
    input.name = "My Checker";
    CheckerInfo info = checkersApi.id(checkerUuid).update(input);
    assertThat(info.updated).isEqualTo(expectedUpdateTimestamp);
  }

  @Test
  public void updateCheckerWithoutAdministrateCheckersCapabilityFails() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().create();

    requestScopeOperations.setApiUser(user.id());

    CheckerInput input = new CheckerInput();
    input.name = "my-renamed-checker";

    AuthException thrown =
        assertThrows(AuthException.class, () -> checkersApi.id(checkerUuid).update(input));
    assertThat(thrown)
        .hasMessageThat()
        .contains("administrateCheckers for plugin checks not permitted");
  }

  @Test
  public void updateCheckerAnonymouslyFails() throws Exception {
    CheckerUuid checkerUuid = checkerOperations.newChecker().create();

    requestScopeOperations.setApiUserAnonymous();

    CheckerInput input = new CheckerInput();
    input.name = "my-renamed-checker";

    AuthException thrown =
        assertThrows(AuthException.class, () -> checkersApi.id(checkerUuid).update(input));
    assertThat(thrown).hasMessageThat().contains("Authentication required");
  }
}
