// Copyright (C) 2023 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.googlesource.gerrit.owners.restapi;

import static com.google.common.truth.Truth.assertThat;
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.allowLabel;
import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;

import com.google.gerrit.acceptance.TestAccount;
import com.google.gerrit.acceptance.TestPlugin;
import com.google.gerrit.acceptance.UseLocalDisk;
import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
import com.google.gerrit.entities.LabelId;
import com.google.gerrit.entities.LabelType;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.extensions.api.changes.ReviewInput;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.server.project.testing.TestLabels;
import com.google.inject.Inject;
import com.googlesource.gerrit.owners.common.LabelDefinition;
import com.googlesource.gerrit.owners.entities.FilesOwnersResponse;
import com.googlesource.gerrit.owners.entities.Owner;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
import java.util.Map;
import org.apache.commons.compress.utils.Sets;
import org.eclipse.jgit.lib.Config;
import org.junit.Test;

@TestPlugin(name = "owners", sysModule = "com.googlesource.gerrit.owners.OwnersModule")
@UseLocalDisk
public class GetFilesOwnersSubmitRequirementsIT extends GetFilesOwnersITAbstract {
  @Inject private ProjectOperations projectOperations;

  @Override
  public void setUpTestPlugin() throws Exception {
    Config pluginCfg = pluginConfig.getGlobalPluginConfig("owners");
    // enable submit requirements and store them to the file as there is no `ConfigSuite` mechanism
    // for plugin config and there is no other way (but adding it to each test case) to enable it
    // globally
    pluginCfg.setBoolean("owners", null, "enableSubmitRequirement", true);
    Files.writeString(
        server.getSitePath().resolve("etc").resolve("owners.config"),
        pluginCfg.toText(),
        StandardOpenOption.CREATE,
        StandardOpenOption.APPEND);
    super.setUpTestPlugin();
  }

  @Test
  public void shouldRequireConfiguredCodeReviewScore() throws Exception {
    // configure submit requirement to require CR+1 only
    addOwnerFileToRoot(LabelDefinition.parse("Code-Review,1").get(), admin);

    String changeId = createChange("Add a file", "foo", "bar").getChangeId();

    Response<FilesOwnersResponse> resp =
        assertResponseOk(ownersApi.apply(parseCurrentRevisionResource(changeId)));
    assertThat(resp.value().files)
        .containsExactly("foo", Sets.newHashSet(new Owner(admin.fullName(), admin.id().get())));
    assertThat(resp.value().ownersLabels).isEmpty();

    // give CR+1 as requested
    recommend(changeId);

    resp = assertResponseOk(ownersApi.apply(parseCurrentRevisionResource(changeId)));
    assertThat(resp.value().files).isEmpty();
    assertThat(resp.value().ownersLabels)
        .containsExactly(admin.id().get(), Map.of(LabelId.CODE_REVIEW, 1));
  }

  @Test
  public void shouldRequireConfiguredLabelAndScore() throws Exception {
    // configure submit requirement to require LabelFoo+1
    String label = "LabelFoo";
    addOwnerFileToRoot(LabelDefinition.parse(String.format("%s,1", label)).get(), admin);
    replaceCodeReviewWithLabel(label);

    String changeId = createChange("Add a file", "foo", "bar").getChangeId();

    Response<FilesOwnersResponse> resp =
        assertResponseOk(ownersApi.apply(parseCurrentRevisionResource(changeId)));
    assertThat(resp.value().files)
        .containsExactly("foo", Sets.newHashSet(new Owner(admin.fullName(), admin.id().get())));
    assertThat(resp.value().ownersLabels).isEmpty();

    // give LabelFoo+1 as requested
    gApi.changes().id(changeId).current().review(new ReviewInput().label(label, 1));

    resp = assertResponseOk(ownersApi.apply(parseCurrentRevisionResource(changeId)));
    assertThat(resp.value().files).isEmpty();
    assertThat(resp.value().ownersLabels).containsEntry(admin.id().get(), Map.of(label, 1));
  }

  private void addOwnerFileToRoot(LabelDefinition label, TestAccount u) throws Exception {
    // Add OWNERS file to root:
    //
    // inherited: true
    // label: label,score # score is optional
    // owners:
    // - u.email()
    String owners =
        String.format(
            "inherited: true\nlabel: %s\nowners:\n- %s\n",
            String.format(
                "%s%s",
                label.getName(),
                label.getScore().map(value -> String.format(",%d", value)).orElse("")),
            u.email());
    pushFactory
        .create(admin.newIdent(), testRepo, "Add OWNER file", "OWNERS", owners)
        .to(RefNames.fullName("master"))
        .assertOkStatus();
  }

  private void replaceCodeReviewWithLabel(String labelId) throws Exception {
    LabelType label =
        TestLabels.label(labelId, TestLabels.value(1, "OK"), TestLabels.value(-1, "Not OK"));

    replaceCodeReviewWithLabel(label);

    // grant label to RegisteredUsers so that it is vote-able
    String heads = RefNames.REFS_HEADS + "*";
    projectOperations
        .project(project)
        .forUpdate()
        .add(allowLabel(label.getName()).ref(heads).group(REGISTERED_USERS).range(-1, 1))
        .update();
  }
}
