// 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.collect.MoreCollectors.onlyElement;
import static com.google.common.truth.Truth.assertThat;

import com.google.common.collect.ImmutableList;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.ChangeMessage;
import com.google.gerrit.extensions.common.AccountInfo;
import com.google.gerrit.extensions.common.CommentInfo;
import com.google.gerrit.server.ChangeMessagesUtil;
import com.google.gerrit.server.CommentsUtil;
import java.sql.Timestamp;
import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

@RunWith(JUnit4.class)
public class ListChangeCommentsTest {

  @Test
  public void commentsLinkedToChangeMessagesIgnoreGerritAutoGenTaggedMessages() {
    /* Comments should not be linked to Gerrit's autogenerated messages */
    List<CommentInfo> comments = createComments("c1", "00", "c2", "10", "c3", "25");
    List<ChangeMessage> changeMessages =
        createChangeMessages("cm1", "00", "cm2", "16", "cm3", "30");

    changeMessages.add(
        newChangeMessage("ignore", "cmAutoGenByGerrit", "15", ChangeMessagesUtil.TAG_MERGED));

    CommentsUtil.linkCommentsToChangeMessages(comments, changeMessages, true);

    assertThat(getComment(comments, "c1").changeMessageId)
        .isEqualTo(getChangeMessage(changeMessages, "cm1").getKey().uuid());
    /* comment 2 ignored the auto-generated message because it has a Gerrit tag */
    assertThat(getComment(comments, "c2").changeMessageId)
        .isEqualTo(getChangeMessage(changeMessages, "cm2").getKey().uuid());
    assertThat(getComment(comments, "c3").changeMessageId)
        .isEqualTo(getChangeMessage(changeMessages, "cm3").getKey().uuid());

    // Make sure no comment is linked to the auto-gen message
    Set<String> changeMessageIds =
        comments.stream().map(c -> c.changeMessageId).collect(Collectors.toSet());
    assertThat(changeMessageIds)
        .doesNotContain(getChangeMessage(changeMessages, "cmAutoGenByGerrit").getKey().uuid());
  }

  @Test
  public void commentsLinkedToCorrectAccounts() {

    List<CommentInfo> comments =
        createComments("c0", "10", "c1", "11", "c2", "11", "c3", "11", "c4", "11", "c5", "21");
    int accountId1 = 12345;
    int accountId2 = 12346;
    int accountId3 = 12347;
    linkAuthor(comments.get(0), accountId1);
    // comments 1-4 have same timestamp
    linkAuthor(comments.get(1), accountId2);
    linkAuthor(comments.get(2), accountId1);
    linkAuthor(comments.get(3), accountId1);
    linkAuthor(comments.get(4), accountId2);

    linkAuthor(comments.get(5), accountId1);

    // Change massages have exactly same timestamps
    List<ChangeMessage> changeMessages =
        ImmutableList.of(
            createChangeMessage("cm0", "10", Account.id(accountId1)),
            createChangeMessage("cm1", "11", Account.id(accountId1)),
            createChangeMessage("cm2", "11", Account.id(accountId2)),
            // unrelated message by other account in-between
            createChangeMessage("cm2.2", "15", Account.id(accountId3)),
            createChangeMessage("cm3", "21", Account.id(accountId1)));

    CommentsUtil.linkCommentsToChangeMessages(comments, changeMessages, true);

    assertThat(getComment(comments, "c0").changeMessageId)
        .isEqualTo(getChangeMessage(changeMessages, "cm0").getKey().uuid());

    // belongs to account2 -assigned to account2
    assertThat(getComment(comments, "c1").changeMessageId)
        .isEqualTo(getChangeMessage(changeMessages, "cm2").getKey().uuid());

    // belongs to account1 -assigned to account1
    assertThat(getComment(comments, "c2").changeMessageId)
        .isEqualTo(getChangeMessage(changeMessages, "cm1").getKey().uuid());
    assertThat(getComment(comments, "c3").changeMessageId)
        .isEqualTo(getChangeMessage(changeMessages, "cm1").getKey().uuid());

    // belongs to account2 - assigned to account2
    assertThat(getComment(comments, "c4").changeMessageId)
        .isEqualTo(getChangeMessage(changeMessages, "cm2").getKey().uuid());

    // different timestamp - assigned to a different message
    assertThat(getComment(comments, "c5").changeMessageId)
        .isEqualTo(getChangeMessage(changeMessages, "cm3").getKey().uuid());

    // Make sure no comment is linked to the auto-gen message
    Set<String> changeMessageIds =
        comments.stream().map(c -> c.changeMessageId).collect(Collectors.toSet());
    assertThat(changeMessageIds)
        .doesNotContain(getChangeMessage(changeMessages, "cm2.2").getKey().uuid());
  }

  @Test
  public void commentsLinkedToCorrectAccountsIfUserNotMatched() {

    String tsCm0 = "10";
    String tsCm1 = "11";
    String tsCm2 = "12";
    List<CommentInfo> comments =
        createComments(
            "commentMessage0", tsCm0, "commentMessage1", tsCm1, "commentMessage2", tsCm2);
    int accountId1 = 1;
    int accountId2 = 2;
    int accountId2Imported = 0;
    int accountId3 = 3;
    linkAuthor(comments.get(0), accountId1);
    linkAuthor(comments.get(1), accountId2Imported);
    linkAuthor(comments.get(2), accountId3);

    List<ChangeMessage> changeMessages =
        ImmutableList.of(
            createChangeMessage("changeMessage0", tsCm0, Account.id(accountId1)),
            createChangeMessage("changeMessage1", tsCm1, Account.id(accountId2)),
            createChangeMessage("changeMessage2", tsCm2, Account.id(accountId3)));

    CommentsUtil.linkCommentsToChangeMessages(comments, changeMessages, false);

    assertThat(getComment(comments, "commentMessage0").changeMessageId)
        .isEqualTo(getChangeMessage(changeMessages, "changeMessage0").getKey().uuid());

    assertThat(getComment(comments, "commentMessage1").changeMessageId).isNull();

    assertThat(getComment(comments, "commentMessage2").changeMessageId)
        .isEqualTo(getChangeMessage(changeMessages, "changeMessage2").getKey().uuid());
  }

  @Test
  public void commentsLinkedToChangeMessagesAllowLinkingToAutoGenTaggedMessages() {
    /* Human comments are allowed to be linked to autogenerated messages */
    List<CommentInfo> comments = createComments("c1", "00", "c2", "10", "c3", "25");
    List<ChangeMessage> changeMessages =
        createChangeMessages("cm1", "00", "cm2", "16", "cm3", "30");

    changeMessages.add(
        newChangeMessage(
            "cmAutoGen", "cmAutoGen", "15", ChangeMessagesUtil.AUTOGENERATED_TAG_PREFIX));

    CommentsUtil.linkCommentsToChangeMessages(comments, changeMessages, true);

    assertThat(getComment(comments, "c1").changeMessageId)
        .isEqualTo(getChangeMessage(changeMessages, "cm1").getKey().uuid());
    /* comment 2 did not ignore the auto-generated change message */
    assertThat(getComment(comments, "c2").changeMessageId)
        .isEqualTo(getChangeMessage(changeMessages, "cmAutoGen").getKey().uuid());
    assertThat(getComment(comments, "c3").changeMessageId)
        .isEqualTo(getChangeMessage(changeMessages, "cm3").getKey().uuid());
  }

  /**
   * Create a list of comments from the specified args args should be passed as consecutive pairs of
   * messages and timestamps example: (m1, t1, m2, t2, ...)
   */
  private static List<CommentInfo> createComments(String... args) {
    List<CommentInfo> comments = new ArrayList<>();
    for (int i = 0; i < args.length; i += 2) {
      String message = args[i];
      String ts = args[i + 1];
      comments.add(newCommentInfo(message, ts));
    }
    return comments;
  }

  private void linkAuthor(CommentInfo commentInfo, int accountId) {
    commentInfo.author = new AccountInfo(accountId);
  }

  /**
   * Create a list of change messages from the specified args args should be passed as consecutive
   * pairs of messages and timestamps example: (m1, t1, m2, t2, ...). the tag parameter for the
   * created change messages will be null.
   */
  private static List<ChangeMessage> createChangeMessages(String... args) {
    List<ChangeMessage> changeMessages = new ArrayList<>();
    for (int i = 0; i < args.length; i += 2) {
      String message = args[i];
      String ts = args[i + 1];
      changeMessages.add(createChangeMessage(message, ts, Optional.empty()));
    }
    return changeMessages;
  }

  /** Creates a ChangeMessages with the specified author. */
  private static ChangeMessage createChangeMessage(String message, String ts, Account.Id author) {
    return createChangeMessage(message, ts, Optional.of(author));
  }

  private static ChangeMessage createChangeMessage(
      String message, String ts, Optional<Account.Id> author) {
    String key = message + "Key";
    return newChangeMessage(key, author, message, ts, null);
  }

  /** Create a new CommentInfo with a given message and timestamp */
  private static CommentInfo newCommentInfo(String message, String ts) {
    CommentInfo c = new CommentInfo();
    c.message = message;
    c.updated = Timestamp.valueOf("2000-01-01 00:00:" + ts);
    return c;
  }

  /** Create a new change message with an id, message, timestamp and tag */
  private static ChangeMessage newChangeMessage(String id, String message, String ts, String tag) {
    return newChangeMessage(id, Optional.empty(), message, ts, tag);
  }

  private static ChangeMessage newChangeMessage(
      String id, Optional<Account.Id> accountId, String message, String ts, String tag) {
    ChangeMessage.Key key = ChangeMessage.key(Change.id(1), id);
    Instant timestamp =
        DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
            .withZone(ZoneId.systemDefault())
            .parse("2000-01-01 00:00:" + ts, Instant::from);
    ChangeMessage cm =
        ChangeMessage.create(key, accountId.orElse(null), timestamp, null, message, null, tag);
    return cm;
  }

  /** Return the change message from the list of messages that has specific message text */
  private static ChangeMessage getChangeMessage(List<ChangeMessage> messages, String messageText) {
    return messages.stream().filter(m -> m.getMessage().equals(messageText)).collect(onlyElement());
  }

  /** Return the comment from the list of comments that has specific message text */
  private CommentInfo getComment(List<CommentInfo> comments, String messageText) {
    return comments.stream().filter(c -> c.message.equals(messageText)).collect(onlyElement());
  }
}
