// 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.criteo.gerrit.plugins.automerge;

import static com.google.common.truth.Truth.assertThat;
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.allow;
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.allowLabel;
import static com.google.gerrit.entities.Permission.SUBMIT;

import com.google.gerrit.acceptance.LightweightPluginDaemonTest;
import com.google.gerrit.acceptance.NoHttpd;
import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.acceptance.TestAccount;
import com.google.gerrit.acceptance.TestPlugin;
import com.google.gerrit.acceptance.config.GerritConfig;
import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
import com.google.gerrit.extensions.api.changes.ChangeApi;
import com.google.gerrit.extensions.api.changes.Changes;
import com.google.gerrit.extensions.api.changes.ReviewInput;
import com.google.gerrit.extensions.client.ChangeStatus;
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.server.account.externalids.ExternalIds;
import com.google.inject.Inject;
import org.junit.Before;
import org.junit.Test;

@NoHttpd
@TestPlugin(
    name = "autosubmitter",
    sysModule = "com.criteo.gerrit.plugins.automerge.AutomergeModule")
public class AutomaticMergerTest extends LightweightPluginDaemonTest {
  private static final String BOT_USERS = "Bot Users";
  private static final String DEVELOPERS = "Developers";
  private TestAccount botUser;
  private TestAccount regularUser;
  @Inject ExternalIds extIds;
  @Inject RequestScopeOperations requestScopeOperations;
  @Inject private ProjectOperations projectOperations;

  @Before
  public void setup() throws Exception {
    gApi.groups().create(BOT_USERS);
    gApi.groups().create(DEVELOPERS);
    botUser =
        accountCreator.create(
            "botuser", "botuser@mycompany.com", "Bot User", "Bot User", BOT_USERS);
    regularUser =
        accountCreator.create(
            "developer", "developer@mycompany.com", "Developer", "Developer", DEVELOPERS);

    projectOperations
        .project(project)
        .forUpdate()
        .add(allow(SUBMIT).ref("refs/*").group(groupUuid(BOT_USERS)))
        .add(allowLabel("Code-Review").ref("refs/*").group(groupUuid(DEVELOPERS)).range(-2, 2))
        .update();
  }

  @Test
  @GerritConfig(name = "automerge.botEmail", value = "botuser@mycompany.com")
  public void changeReviewedShouldNotBeAutomaticallyMergedIfNotApproved() throws Exception {
    String changeId = createChange(user);

    assertThat(changesApi().id(changeId).get().status).isEqualTo(ChangeStatus.NEW);
  }

  @Test
  @GerritConfig(name = "automerge.botEmail", value = "botuser@mycompany.com")
  public void changeReviewedShouldBeAutomaticallyMergedOnceApproved() throws Exception {
    String changeId = createChange(user);
    changesApi().id(changeId).current().review(ReviewInput.approve());

    assertThat(changesApi().id(changeId).get().status).isEqualTo(ChangeStatus.MERGED);
  }

  @Test
  @GerritConfig(name = "automerge.botEmail", value = "botuser@mycompany.com")
  public void changeShouldBeAutomaticallyMergedByBotUser() throws Exception {
    requestScopeOperations.setApiUser(regularUser.id());
    String changeId = createChange(user);
    ChangeApi changeApi = changesApi().id(changeId);
    changeApi.current().review(ReviewInput.approve());

    ChangeInfo changeInfo = gApi.changes().id(changeId).get();
    assertThat(changeInfo.submitter).isNotNull();
    assertThat(changeInfo.submitter._accountId).isEqualTo(new Integer(botUser.id().get()));
    assertThat(changeInfo.submitter.email).isEqualTo(botUser.email());
  }

  private Changes changesApi() {
    return gApi.changes();
  }

  private String createChange(TestAccount user) throws Exception {
    return createChangeAsUser("refs/for/master", user).getChangeId();
  }

  protected PushOneCommit.Result createChangeAsUser(String ref, TestAccount user) throws Exception {
    PushOneCommit.Result result = pushFactory.create(user.newIdent(), testRepo).to(ref);
    result.assertOkStatus();
    return result;
  }
}
