// Copyright (C) 2021 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.codeowners.acceptance.api;

import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import static com.google.gerrit.extensions.common.SubmitRequirementResultInfo.Status.NOT_APPLICABLE;
import static com.google.gerrit.extensions.common.SubmitRequirementResultInfo.Status.SATISFIED;
import static com.google.gerrit.extensions.common.SubmitRequirementResultInfo.Status.UNSATISFIED;
import static com.google.gerrit.testing.GerritJUnit.assertThrows;
import static java.util.stream.Collectors.toList;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import com.google.common.collect.Streams;
import com.google.gerrit.acceptance.Sandboxed;
import com.google.gerrit.acceptance.config.GerritConfig;
import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
import com.google.gerrit.entities.BranchNameKey;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.SubmitRequirement;
import com.google.gerrit.entities.SubmitRequirementExpression;
import com.google.gerrit.extensions.api.changes.Changes.QueryRequest;
import com.google.gerrit.extensions.client.ListChangesOption;
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.common.SubmitRequirementResultInfo;
import com.google.gerrit.extensions.common.SubmitRequirementResultInfo.Status;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.plugins.codeowners.acceptance.AbstractCodeOwnersIT;
import com.google.gerrit.plugins.codeowners.backend.CodeOwnerApprovalHasOperand;
import com.google.gerrit.plugins.codeowners.backend.CodeOwnersInternalServerErrorException;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.ChangeQueryBuilder;
import com.google.inject.Inject;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import org.junit.Before;
import org.junit.Test;

@Sandboxed
public class CodeOwnerHasOperandsIT extends AbstractCodeOwnersIT {
  @Inject private RequestScopeOperations requestScopeOperations;
  @Inject private ChangeQueryBuilder changeQueryBuilder;

  private CodeOwnerApprovalHasOperand codeOwnerApprovalHasOperand;

  @Before
  public void setup() throws Exception {
    codeOwnerApprovalHasOperand =
        plugin.getSysInjector().getInstance(CodeOwnerApprovalHasOperand.class);

    configSubmitRequirement(
        project,
        SubmitRequirement.builder()
            .setName("Code-Owner-Approval")
            .setApplicabilityExpression(SubmitRequirementExpression.of("has:enabled_code-owners"))
            .setSubmittabilityExpression(
                SubmitRequirementExpression.create("has:approval_code-owners"))
            .setAllowOverrideInChildProjects(false)
            .build());
  }

  @Test
  public void hasApproval_notSupportedInSearchQueries() throws Exception {
    Exception thrown =
        assertThrows(BadRequestException.class, () -> assertQuery("has:approval_code-owners"));
    assertThat(thrown)
        .hasMessageThat()
        .isEqualTo("Operator 'has:approval_code-owners' cannot be used in queries");
  }

  @Test
  public void hasEnabled_notSupportedInSearchQueries() throws Exception {
    Exception thrown =
        assertThrows(BadRequestException.class, () -> assertQuery("has:enabled_code-owners"));
    assertThat(thrown)
        .hasMessageThat()
        .isEqualTo("Operator 'has:enabled_code-owners' cannot be used in queries");
  }

  @Test
  public void hasApproval_satisfied() throws Exception {
    codeOwnerConfigOperations
        .newCodeOwnerConfig()
        .project(project)
        .branch("master")
        .folderPath("/foo/")
        .addCodeOwnerEmail(user.email())
        .create();

    String path = "foo/bar.baz";
    ChangeData changeData = createChange("Change Adding A File", path, "file content").getChange();
    int changeId = changeData.change().getChangeId();
    ChangeInfo changeInfo = gApi.changes().id(changeId).get(ListChangesOption.SUBMIT_REQUIREMENTS);
    assertSubmitRequirement(changeInfo.submitRequirements, "Code-Owner-Approval", UNSATISFIED);

    // Add a Code-Review+1 from a code owner (by default this counts as code owner approval).
    requestScopeOperations.setApiUser(user.id());
    recommend(changeData.change().getKey().get());
    changeInfo = gApi.changes().id(changeId).get(ListChangesOption.SUBMIT_REQUIREMENTS);
    assertSubmitRequirement(changeInfo.submitRequirements, "Code-Owner-Approval", SATISFIED);
  }

  @Test
  public void hasApproval_unsatisfiedIfChangeIsClosed() throws Exception {
    codeOwnerConfigOperations
        .newCodeOwnerConfig()
        .project(project)
        .branch("master")
        .folderPath("/foo/")
        .addCodeOwnerEmail(user.email())
        .create();

    String path = "foo/bar.baz";
    ChangeData changeData = createChange("Change Adding A File", path, "file content").getChange();
    int changeId = changeData.change().getChangeId();

    // Add a Code-Review+1 from a code owner (by default this counts as code owner approval).
    requestScopeOperations.setApiUser(user.id());
    recommend(changeData.change().getKey().get());
    ChangeInfo changeInfo = gApi.changes().id(changeId).get(ListChangesOption.SUBMIT_REQUIREMENTS);
    assertSubmitRequirement(changeInfo.submitRequirements, "Code-Owner-Approval", SATISFIED);

    // Approve and submit.
    requestScopeOperations.setApiUser(admin.id());
    approve(changeData.change().getKey().get());
    gApi.changes().id(changeId).current().submit();
    changeInfo = gApi.changes().id(changeId).get(ListChangesOption.SUBMIT_REQUIREMENTS);
    // When the change is merged, submit requirement results are persisted in NoteDb. Later lookups
    // return the persisted snapshot. Currently writing to NoteDb is disabled.
    // TODO(ghareeb): update this check when we enable writing to NoteDb again.
    assertNonExistentSubmitRequirement(changeInfo.submitRequirements, "Code-Owner-Approval");
  }

  @Test
  public void hasApproval_internalServerError() throws Exception {
    ChangeData changeData = createChange().getChange();

    // Create a ChangeData without change notes to trigger an error.
    // Set change and current patch set, so that this info can be included into the error message.
    ChangeData changeDataWithoutChangeNotes = mock(ChangeData.class);
    when(changeDataWithoutChangeNotes.change()).thenReturn(changeData.change());
    when(changeDataWithoutChangeNotes.currentPatchSet()).thenReturn(changeData.currentPatchSet());

    CodeOwnersInternalServerErrorException exception =
        assertThrows(
            CodeOwnersInternalServerErrorException.class,
            () ->
                codeOwnerApprovalHasOperand
                    .create(changeQueryBuilder)
                    .asMatchable()
                    .match(changeDataWithoutChangeNotes));
    assertThat(exception)
        .hasMessageThat()
        .isEqualTo(
            String.format(
                "Failed to evaluate code owner statuses for patch set %d of change %d.",
                changeData.change().currentPatchSetId().get(), changeData.change().getId().get()));
  }

  @Test
  public void hasApproval_ruleErrorForNonParsableCodeOwnerConfig() throws Exception {
    String nameOfInvalidCodeOwnerConfigFile = getCodeOwnerConfigFileName();
    createNonParseableCodeOwnerConfig(nameOfInvalidCodeOwnerConfigFile);

    ChangeData changeData = createChange().getChange();
    ChangeInfo changeInfo =
        gApi.changes()
            .id(changeData.change().getChangeId())
            .get(ListChangesOption.SUBMIT_REQUIREMENTS);
    // Requirement is unsatisfied if a relevant code owner config file is not parseable and hence
    // the submit rule cannot be evaluated.
    assertSubmitRequirement(changeInfo.submitRequirements, "Code-Owner-Approval", UNSATISFIED);
  }

  @Test
  @GerritConfig(name = "plugin.code-owners.disabled", value = "true")
  public void hasEnabled_notMatchingWhenCodeOwnersIsDisabledForTheChange() throws Exception {
    Change change =
        createChange("Change Adding A File", "foo/bar.baz", "file content").getChange().change();
    String changeId = change.getKey().get();
    ChangeInfo changeInfo = gApi.changes().id(changeId).get(ListChangesOption.SUBMIT_REQUIREMENTS);
    assertSubmitRequirement(changeInfo.submitRequirements, "Code-Owner-Approval", NOT_APPLICABLE);

    requestScopeOperations.setApiUser(user.id());
    recommend(changeId);
    changeInfo = gApi.changes().id(changeId).get(ListChangesOption.SUBMIT_REQUIREMENTS);
    assertSubmitRequirement(changeInfo.submitRequirements, "Code-Owner-Approval", NOT_APPLICABLE);
  }

  private List<ChangeInfo> assertQuery(Object query, Change... changes) throws Exception {
    QueryRequest queryRequest = newQuery(query);
    Change.Id[] changeArray = Arrays.stream(changes).map(Change::getId).toArray(Change.Id[]::new);
    List<ChangeInfo> result = queryRequest.get();
    Iterable<Change.Id> ids = ids(result);
    assertWithMessage(format(queryRequest.getQuery(), ids, changeArray))
        .that(ids)
        .containsExactlyElementsIn(Arrays.asList(changeArray))
        .inOrder();
    return result;
  }

  private static Iterable<Change.Id> ids(Iterable<ChangeInfo> changes) {
    return Streams.stream(changes).map(c -> Change.id(c._number)).collect(toList());
  }

  private QueryRequest newQuery(Object query) {
    return gApi.changes().query(query.toString());
  }

  private void assertSubmitRequirement(
      Collection<SubmitRequirementResultInfo> requirements, String name, Status status) {
    for (SubmitRequirementResultInfo requirement : requirements) {
      if (requirement.name.equals(name) && requirement.status == status) {
        return;
      }
    }
    throw new AssertionError(
        String.format(
            "Could not find submit requirement %s with status %s (results = %s)",
            name,
            status,
            requirements.stream()
                .map(r -> String.format("%s=%s", r.name, r.status))
                .collect(toImmutableList())));
  }

  private void assertNonExistentSubmitRequirement(
      Collection<SubmitRequirementResultInfo> requirements, String name) {
    for (SubmitRequirementResultInfo requirement : requirements) {
      if (requirement.name.equals(name)) {
        throw new AssertionError("Found a submit requirement with name " + name);
      }
    }
  }

  private String format(String query, Iterable<Change.Id> actualIds, Change.Id... expectedChanges)
      throws RestApiException {
    return "query '"
        + query
        + "' with expected changes "
        + format(Arrays.asList(expectedChanges))
        + " and result "
        + format(actualIds);
  }

  private String format(Iterable<Change.Id> changeIds) throws RestApiException {
    Iterator<Change.Id> changeIdsItr = changeIds.iterator();
    StringBuilder b = new StringBuilder();
    b.append("[");
    while (changeIdsItr.hasNext()) {
      Change.Id id = changeIdsItr.next();
      ChangeInfo c = gApi.changes().id(id.get()).get();
      b.append("{")
          .append(id)
          .append(" (")
          .append(c.changeId)
          .append("), ")
          .append("dest=")
          .append(BranchNameKey.create(Project.nameKey(c.project), c.branch))
          .append(", ")
          .append("status=")
          .append(c.status)
          .append(", ")
          .append("lastUpdated=")
          .append(c.updated.getTime())
          .append("}");
      if (changeIdsItr.hasNext()) {
        b.append(", ");
      }
    }
    b.append("]");
    return b.toString();
  }
}
