// 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.ericsson.gerrit.plugins.highavailability.autoreindex;

import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import com.ericsson.gerrit.plugins.highavailability.forwarder.ForwardedIndexChangeHandler;
import com.ericsson.gerrit.plugins.highavailability.forwarder.ForwardedIndexingHandler.Operation;
import com.ericsson.gerrit.plugins.highavailability.forwarder.rest.AbstractIndexRestApiServlet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.BranchNameKey;
import com.google.gerrit.entities.Change;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.group.db.Groups;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.notedb.ChangeNotes.Factory.ChangeNotesResult;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.util.OneOffRequestContext;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.Optional;
import java.util.stream.Stream;
import org.eclipse.jgit.lib.Repository;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class ChangeReindexRunnableTest {

  @Mock private ForwardedIndexChangeHandler indexer;
  @Mock private IndexTs indexTs;
  @Mock private OneOffRequestContext ctx;
  @Mock private ProjectCache projectCache;
  @Mock private Groups groups;
  @Mock private GitRepositoryManager repoManager;
  @Mock private AllUsersName allUsers;
  @Mock private ChangeNotes.Factory changeNotesFactory;
  @Mock private Repository repo;
  @Mock private ChangeNotesResult changeNotesRes;
  @Mock private ChangeNotes changeNotes;

  private ChangeReindexRunnable changeReindexRunnable;

  @Before
  public void setUp() throws Exception {
    changeReindexRunnable =
        new ChangeReindexRunnable(
            indexer, indexTs, ctx, projectCache, repoManager, changeNotesFactory);
  }

  @Test
  public void changeIsIndexedWhenItIsCreatedAfterLastChangeReindex() throws Exception {
    Timestamp currentTime = Timestamp.valueOf(LocalDateTime.now());
    Timestamp afterCurrentTime = new Timestamp(currentTime.getTime() + 1000L);
    Change change = newChange(afterCurrentTime);

    Optional<Timestamp> changeLastTs = changeReindexRunnable.indexIfNeeded(change, currentTime);
    assertThat(changeLastTs.isPresent()).isTrue();
    assertThat(changeLastTs.get()).isEqualTo(afterCurrentTime);
    verify(indexer).index(changeProjectIndexKey(change), Operation.INDEX, Optional.empty());
  }

  @Test
  public void changeIsIndexedDuringRun() throws Exception {
    LocalDateTime currentTime = LocalDateTime.now(ZoneOffset.UTC);
    Timestamp afterCurrentTime =
        new Timestamp(currentTime.toEpochSecond(ZoneOffset.UTC) * 1000 + 1000L);
    Change change = newChange(afterCurrentTime);

    when(indexTs.getUpdateTs(AbstractIndexRestApiServlet.IndexName.CHANGE))
        .thenReturn(Optional.of(currentTime));
    when(projectCache.all()).thenReturn(ImmutableSortedSet.of(change.getProject()));
    when(repoManager.openRepository(change.getProject())).thenReturn(repo);
    when(changeNotesFactory.scan(repo, change.getProject())).thenReturn(Stream.of(changeNotesRes));
    lenient().when(changeNotesRes.error()).thenReturn(Optional.empty());
    when(changeNotesRes.notes()).thenReturn(changeNotes);
    when(changeNotes.getChange()).thenReturn(change);

    changeReindexRunnable.run();

    verify(indexer).index(changeProjectIndexKey(change), Operation.INDEX, Optional.empty());
  }

  @Test
  public void changeIsIndexedDuringRun_withInvalidExtraChange() throws Exception {
    LocalDateTime currentTime = LocalDateTime.now(ZoneOffset.UTC);
    Timestamp afterCurrentTime =
        new Timestamp(currentTime.toEpochSecond(ZoneOffset.UTC) * 1000 + 1000L);
    Change change = newChange(afterCurrentTime);

    when(indexTs.getUpdateTs(AbstractIndexRestApiServlet.IndexName.CHANGE))
        .thenReturn(Optional.of(currentTime));
    when(projectCache.all()).thenReturn(ImmutableSortedSet.of(change.getProject()));
    when(repoManager.openRepository(change.getProject())).thenReturn(repo);
    ChangeNotesResult invalidChangeRes = mock(ChangeNotesResult.class);
    lenient().when(invalidChangeRes.notes()).thenThrow(IllegalStateException.class);
    when(invalidChangeRes.error()).thenReturn(Optional.of(new IllegalStateException()));
    when(changeNotesFactory.scan(repo, change.getProject()))
        .thenReturn(Stream.of(invalidChangeRes, changeNotesRes));
    when(changeNotesRes.error()).thenReturn(Optional.empty());
    when(changeNotesRes.notes()).thenReturn(changeNotes);
    when(changeNotes.getChange()).thenReturn(change);

    changeReindexRunnable.run();

    verify(indexer).index(changeProjectIndexKey(change), Operation.INDEX, Optional.empty());
  }

  @Test
  public void groupIsNotIndexedWhenItIsCreatedBeforeLastGroupReindex() throws Exception {
    Timestamp currentTime = Timestamp.valueOf(LocalDateTime.now());
    Timestamp beforeCurrentTime = new Timestamp(currentTime.getTime() - 1000L);
    Change change = newChange(beforeCurrentTime);

    Optional<Timestamp> changeLastTs = changeReindexRunnable.indexIfNeeded(change, currentTime);
    assertThat(changeLastTs.isPresent()).isFalse();
    verify(indexer, never())
        .index(changeProjectIndexKey(change), Operation.INDEX, Optional.empty());
  }

  private String changeProjectIndexKey(Change change) {
    return change.getProject() + "~" + change.getChangeId();
  }

  private Change newChange(Timestamp changeTs) {
    return new Change(
        Change.key("changekey"),
        Change.id(123),
        Account.id(1000000),
        BranchNameKey.create("projectname", "main"),
        changeTs.toInstant());
  }
}
