// Copyright (C) 2020 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.server.restapi.change;

import static com.google.common.truth.Truth.assertThat;
import static java.util.Comparator.comparing;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyShort;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.truth.Correspondence;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.BranchNameKey;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.Comment;
import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.entities.Patch;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.Project;
import com.google.gerrit.metrics.DisabledMetricMaker;
import com.google.gerrit.server.CommentsUtil;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.patch.DiffNotAvailableException;
import com.google.gerrit.server.patch.DiffOperations;
import com.google.gerrit.server.patch.DiffOptions;
import com.google.gerrit.server.restapi.change.CommentPorter.Metrics;
import com.google.gerrit.truth.NullAwareCorrespondence;
import java.time.Instant;
import java.util.Arrays;
import java.util.Optional;
import org.eclipse.jgit.lib.ObjectId;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;

public class CommentPorterTest {

  private final ObjectId dummyObjectId =
      ObjectId.fromString("0123456789012345678901234567890123456789");

  @Rule public final MockitoRule mockito = MockitoJUnit.rule();

  @Mock private DiffOperations diffOperations;
  @Mock private CommentsUtil commentsUtil;

  private static final CommentPorter.Metrics metrics = new Metrics(new DisabledMetricMaker());

  private int uuidCounter = 0;

  @Test
  public void commentsAreNotDroppedWhenDiffNotAvailable() throws Exception {
    Project.NameKey project = Project.nameKey("myProject");
    Change.Id changeId = Change.id(1);
    Change change = createChange(project, changeId);
    PatchSet patchset1 = createPatchset(PatchSet.id(changeId, 1));
    PatchSet patchset2 = createPatchset(PatchSet.id(changeId, 2));
    ChangeNotes changeNotes = mockChangeNotes(project, change, patchset1, patchset2);

    CommentPorter commentPorter = new CommentPorter(diffOperations, commentsUtil, metrics);
    HumanComment comment = createComment(patchset1.id(), "myFile");
    when(commentsUtil.determineCommitId(any(), any(), anyShort()))
        .thenReturn(Optional.of(dummyObjectId));
    when(diffOperations.listModifiedFiles(
            any(Project.NameKey.class),
            any(ObjectId.class),
            any(ObjectId.class),
            any(DiffOptions.class)))
        .thenThrow(DiffNotAvailableException.class);
    ImmutableList<HumanComment> portedComments =
        commentPorter.portComments(
            changeNotes, patchset2, ImmutableList.of(comment), ImmutableList.of());

    assertThat(portedComments).isNotEmpty();
  }

  @Test
  public void commentsAreNotDroppedWhenDiffHasUnexpectedError() throws Exception {
    Project.NameKey project = Project.nameKey("myProject");
    Change.Id changeId = Change.id(1);
    Change change = createChange(project, changeId);
    PatchSet patchset1 = createPatchset(PatchSet.id(changeId, 1));
    PatchSet patchset2 = createPatchset(PatchSet.id(changeId, 2));
    ChangeNotes changeNotes = mockChangeNotes(project, change, patchset1, patchset2);

    CommentPorter commentPorter = new CommentPorter(diffOperations, commentsUtil, metrics);
    HumanComment comment = createComment(patchset1.id(), "myFile");
    when(commentsUtil.determineCommitId(any(), any(), anyShort()))
        .thenReturn(Optional.of(dummyObjectId));
    when(diffOperations.listModifiedFiles(
            any(Project.NameKey.class),
            any(ObjectId.class),
            any(ObjectId.class),
            any(DiffOptions.class)))
        .thenThrow(IllegalStateException.class);
    ImmutableList<HumanComment> portedComments =
        commentPorter.portComments(
            changeNotes, patchset2, ImmutableList.of(comment), ImmutableList.of());

    assertThat(portedComments).isNotEmpty();
  }

  @Test
  public void commentsAreNotDroppedWhenRetrievingCommitSha1sHasUnexpectedError() {
    Project.NameKey project = Project.nameKey("myProject");
    Change.Id changeId = Change.id(1);
    Change change = createChange(project, changeId);
    PatchSet patchset1 = createPatchset(PatchSet.id(changeId, 1));
    PatchSet patchset2 = createPatchset(PatchSet.id(changeId, 2));
    ChangeNotes changeNotes = mockChangeNotes(project, change, patchset1, patchset2);

    CommentPorter commentPorter = new CommentPorter(diffOperations, commentsUtil, metrics);
    HumanComment comment = createComment(patchset1.id(), "myFile");
    when(commentsUtil.determineCommitId(any(), any(), anyShort()))
        .thenThrow(IllegalStateException.class);
    ImmutableList<HumanComment> portedComments =
        commentPorter.portComments(
            changeNotes, patchset2, ImmutableList.of(comment), ImmutableList.of());

    assertThat(portedComments).isNotEmpty();
  }

  @Test
  public void commentsAreMappedToPatchsetLevelOnDiffError() throws Exception {
    Project.NameKey project = Project.nameKey("myProject");
    Change.Id changeId = Change.id(1);
    Change change = createChange(project, changeId);
    PatchSet patchset1 = createPatchset(PatchSet.id(changeId, 1));
    PatchSet patchset2 = createPatchset(PatchSet.id(changeId, 2));
    ChangeNotes changeNotes = mockChangeNotes(project, change, patchset1, patchset2);

    CommentPorter commentPorter = new CommentPorter(diffOperations, commentsUtil, metrics);
    HumanComment comment = createComment(patchset1.id(), "myFile");
    when(commentsUtil.determineCommitId(any(), any(), anyShort()))
        .thenReturn(Optional.of(dummyObjectId));
    when(diffOperations.listModifiedFiles(
            any(Project.NameKey.class),
            any(ObjectId.class),
            any(ObjectId.class),
            any(DiffOptions.class)))
        .thenThrow(IllegalStateException.class);
    ImmutableList<HumanComment> portedComments =
        commentPorter.portComments(
            changeNotes, patchset2, ImmutableList.of(comment), ImmutableList.of());

    assertThat(portedComments)
        .comparingElementsUsing(hasFilePath())
        .containsExactly(Patch.PATCHSET_LEVEL);
  }

  @Test
  public void commentsAreStillPortedWhenDiffOfOtherCommentsHasError() throws Exception {
    Project.NameKey project = Project.nameKey("myProject");
    Change.Id changeId = Change.id(1);
    Change change = createChange(project, changeId);
    PatchSet patchset1 = createPatchset(PatchSet.id(changeId, 1));
    PatchSet patchset2 = createPatchset(PatchSet.id(changeId, 2));
    PatchSet patchset3 = createPatchset(PatchSet.id(changeId, 3));
    ChangeNotes changeNotes = mockChangeNotes(project, change, patchset1, patchset2, patchset3);

    CommentPorter commentPorter = new CommentPorter(diffOperations, commentsUtil, metrics);
    // Place the comments on different patchsets to have two different diff requests.
    HumanComment comment1 = createComment(patchset1.id(), "myFile");
    HumanComment comment2 = createComment(patchset2.id(), "myFile");
    when(commentsUtil.determineCommitId(any(), any(), anyShort()))
        .thenReturn(Optional.of(dummyObjectId));
    // Throw an exception on the first diff request but return an actual value on the second.
    when(diffOperations.listModifiedFiles(
            any(Project.NameKey.class),
            any(ObjectId.class),
            any(ObjectId.class),
            any(DiffOptions.class)))
        .thenThrow(IllegalStateException.class)
        .thenReturn(ImmutableMap.of());
    ImmutableList<HumanComment> portedComments =
        commentPorter.portComments(
            changeNotes, patchset3, ImmutableList.of(comment1, comment2), ImmutableList.of());

    // One of the comments should still be ported as usual. -> Keeps its file name as the diff was
    // empty.
    assertThat(portedComments).comparingElementsUsing(hasFilePath()).contains("myFile");
  }

  @Test
  public void commentsWithInvalidPatchsetsAreIgnored() throws Exception {
    Project.NameKey project = Project.nameKey("myProject");
    Change.Id changeId = Change.id(1);
    Change change = createChange(project, changeId);
    PatchSet patchset1 = createPatchset(PatchSet.id(changeId, 1));
    PatchSet patchset2 = createPatchset(PatchSet.id(changeId, 2));
    // Leave out patchset 1 (e.g. reserved for draft patchsets in the past).
    ChangeNotes changeNotes = mockChangeNotes(project, change, patchset2);

    CommentPorter commentPorter = new CommentPorter(diffOperations, commentsUtil, metrics);
    HumanComment comment = createComment(patchset1.id(), "myFile");
    when(commentsUtil.determineCommitId(any(), any(), anyShort()))
        .thenReturn(Optional.of(dummyObjectId));
    when(diffOperations.listModifiedFiles(
            any(Project.NameKey.class),
            any(ObjectId.class),
            any(ObjectId.class),
            any(DiffOptions.class)))
        .thenReturn(ImmutableMap.of());
    ImmutableList<HumanComment> portedComments =
        commentPorter.portComments(
            changeNotes, patchset2, ImmutableList.of(comment), ImmutableList.of());

    assertThat(portedComments).isEmpty();
  }

  private Change createChange(Project.NameKey project, Change.Id changeId) {
    return new Change(
        Change.key("changeKey"),
        changeId,
        Account.id(123),
        BranchNameKey.create(project, "myBranch"),
        Instant.ofEpochMilli(12345));
  }

  private PatchSet createPatchset(PatchSet.Id id) {
    return PatchSet.builder()
        .id(id)
        .commitId(dummyObjectId)
        .uploader(Account.id(123))
        .createdOn(Instant.ofEpochMilli(12345))
        .build();
  }

  private ChangeNotes mockChangeNotes(
      Project.NameKey project, Change change, PatchSet... patchsets) {
    ChangeNotes changeNotes = mock(ChangeNotes.class);
    when(changeNotes.getProjectName()).thenReturn(project);
    when(changeNotes.getChange()).thenReturn(change);
    when(changeNotes.getChangeId()).thenReturn(change.getId());
    ImmutableSortedMap<PatchSet.Id, PatchSet> sortedPatchsets =
        Arrays.stream(patchsets)
            .collect(
                ImmutableSortedMap.toImmutableSortedMap(
                    comparing(PatchSet.Id::get), PatchSet::id, patchset -> patchset));
    when(changeNotes.getPatchSets()).thenReturn(sortedPatchsets);
    return changeNotes;
  }

  private HumanComment createComment(PatchSet.Id patchsetId, String filePath) {
    return new HumanComment(
        new Comment.Key(getUniqueUuid(), filePath, patchsetId.get()),
        Account.id(100),
        Instant.ofEpochMilli(1234),
        (short) 1,
        "Comment text",
        "serverId",
        true);
  }

  private String getUniqueUuid() {
    return "commentUuid" + uuidCounter++;
  }

  private Correspondence<HumanComment, String> hasFilePath() {
    return NullAwareCorrespondence.transforming(comment -> comment.key.filename, "hasFilePath");
  }
}
