/*
 * (c) 2020 Pluto Inc.
 */
package tv.pluto;

import static tv.pluto.ip.dal.subclip.SubClips.CreateResponse;
import static tv.pluto.ip.dal.subclip.SubClips.SubClip;

import io.grpc.StatusRuntimeException;
import io.qameta.allure.Description;
import io.qameta.allure.TmsLink;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.Collections;
import java.util.List;
import net.datafaker.Faker;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import org.testng.asserts.SoftAssert;
import tv.pluto.core.BaseTest;
import tv.pluto.grpc.subclips.SubClipsClient;
import tv.pluto.mongo.entities.subclips.SubClips;
import tv.pluto.mongo.utils.MongoUtils;
import tv.pluto.mongo.utils.SubClipsUtils;

public class SubClipsTestSuite extends BaseTest {
  private SubClipsClient subClipsClientNoMetadata;
  private SubClipsClient subClipsClient;
  private SubClipsClient subClipsClientAuth;
  private SubClipsUtils subClipsUtils;

  @BeforeClass(alwaysRun = true)
  private void setUp() {
    subClipsClientNoMetadata = new SubClipsClient(grpcChannelManager.getChannel());
    subClipsClient = new SubClipsClient(grpcChannelManager.getChannel(), false);
    subClipsClientAuth = new SubClipsClient(grpcChannelManager.getChannel(), true);
    subClipsUtils = new SubClipsUtils();
  }

  @Test
  @Description("Valid request - GetSubClipById")
  @TmsLink("28501419")
  public void C28501419_TEST() {
    SubClips mongoSubClip = subClipsUtils.getRandomDocument();

    SubClips normalizedSubClip =
        subClipsUtils.normaliseHSLSourceItem(Collections.singletonList(mongoSubClip)).get(0);

    String randomSubClipId = mongoSubClip.getId();

    SubClips mappedSubClip =
        subClipsUtils.mapGrpcObjectToPojo(
            subClipsClient.getSubClipById(randomSubClipId).getDocument(), SubClips.class);

    Assert.assertEquals(normalizedSubClip, mappedSubClip);
  }

  @Test(
      expectedExceptions = StatusRuntimeException.class,
      expectedExceptionsMessageRegExp = "NOT_FOUND: SubClip document for requested ID not found")
  @Description("Invalid request - GetSubClipById")
  @TmsLink("28501420")
  public void C28501420_TEST() {
    subClipsClient.getSubClipById(MongoUtils.INVALID_ID_VALUE);
  }

  @Test
  @Description("Valid request with single subclip - GetSubClipsByIds")
  @TmsLink("28501421")
  public void C28501421_TEST() {
    SubClips mongoSubClip = subClipsUtils.getRandomDocument();
    List<String> randomSubClipsIds = Collections.singletonList(mongoSubClip.getId());

    List<SubClips> mongoSubClipsList = subClipsUtils.getDocumentsByIds(randomSubClipsIds);
    List<SubClips> normalizedSubClipsList = subClipsUtils.normaliseHSLSourceItem(mongoSubClipsList);

    List<?> mappedSubClipsList =
        subClipsUtils.mapGrpcObjectsToPojo(
            subClipsClient.getSubClipsByIds(randomSubClipsIds).getDocumentsList(), SubClips.class);

    Assert.assertEquals(normalizedSubClipsList, mappedSubClipsList);
  }

  @Test
  @Description("Valid request with multiple subclips - GetSubClipsByIds")
  @TmsLink("28501422")
  public void C28501422_TEST() {
    List<String> randomSubClipsIds = subClipsUtils.getRandomSubClipsIds();

    List<SubClips> mongoSubClipsList = subClipsUtils.getDocumentsByIds(randomSubClipsIds);
    List<SubClips> normalizedSubClipsList = subClipsUtils.normaliseHSLSourceItem(mongoSubClipsList);

    List<?> mappedSubClipsList =
        subClipsUtils.mapGrpcObjectsToPojo(
            subClipsClient.getSubClipsByIds(randomSubClipsIds).getDocumentsList(), SubClips.class);

    Assert.assertEquals(normalizedSubClipsList, mappedSubClipsList);
  }

  @Test(
      expectedExceptions = StatusRuntimeException.class,
      expectedExceptionsMessageRegExp = "NOT_FOUND: SubClip documents for requested IDs not found")
  @Description("Invalid request with single subclip- GetSubClipsByIds")
  @TmsLink("28501423")
  public void C28501423_TEST() {
    List<String> randomSubClipsIds = Collections.singletonList(MongoUtils.INVALID_ID_VALUE);
    subClipsClient.getSubClipsByIds(randomSubClipsIds);
  }

  @Test
  @Description("Valid request with invalid subclips - GetSubClipsByIds")
  @TmsLink("28501424")
  public void C28501424_TEST() {
    List<String> randomSubClipsIds = subClipsUtils.getRandomSubClipsIds();
    randomSubClipsIds.add(MongoUtils.INVALID_ID_VALUE);

    List<SubClips> mongoSubClipsList = subClipsUtils.getDocumentsByIds(randomSubClipsIds);
    List<SubClips> normalizedSubClipsList = subClipsUtils.normaliseHSLSourceItem(mongoSubClipsList);

    List<?> mappedSubClipsList =
        subClipsUtils.mapGrpcObjectsToPojo(
            subClipsClient.getSubClipsByIds(randomSubClipsIds).getDocumentsList(), SubClips.class);

    Assert.assertEquals(normalizedSubClipsList, mappedSubClipsList);
  }

  @Test
  @Description("Create new subClip - Create")
  @TmsLink("28501425")
  public void C28501425_TEST() {
    Faker faker = new Faker();

    SubClip grpcRequestSubClip =
        SubClip.newBuilder()
            .setCreatedAt(LocalDateTime.now(ZoneOffset.UTC).toString())
            .setUpdatedAt(LocalDateTime.now(ZoneOffset.UTC).toString())
            .setStartAt(faker.random().nextInt(1, 100))
            .setUrl(faker.internet().url())
            .setDuration(faker.random().nextDouble())
            .setContentStatus("ready")
            .build();

    CreateResponse createResponse = subClipsClientAuth.create(grpcRequestSubClip);

    SubClip grpcResponseSubClip = createResponse.getDocument();

    SubClips mappedResponseSubClip =
        subClipsUtils.mapGrpcObjectToPojo(grpcResponseSubClip, SubClips.class);

    SubClips mongoSubClip = subClipsUtils.getDocumentById(mappedResponseSubClip.getId());

    Assert.assertEquals(mongoSubClip, mappedResponseSubClip);

    SoftAssert softAssert = new SoftAssert();

    softAssert.assertEquals(
        mappedResponseSubClip.getStartAt().intValue(), grpcRequestSubClip.getStartAt());
    softAssert.assertEquals(mappedResponseSubClip.getUrl(), grpcRequestSubClip.getUrl());
    softAssert.assertEquals(mappedResponseSubClip.getDuration(), grpcRequestSubClip.getDuration());
    softAssert.assertEquals(
        mappedResponseSubClip.getContentStatus(), grpcRequestSubClip.getContentStatus());
    softAssert.assertAll();
  }

  @Test(
      expectedExceptions = RuntimeException.class,
      expectedExceptionsMessageRegExp =
          "UNAUTHENTICATED: app_name must be provided in request metadata")
  @Description("Create new subClip - create no Metadata")
  @TmsLink("28501427")
  public void C28501427_TEST() {
    Faker faker = new Faker();

    SubClip grpcRequestSubClip =
        SubClip.newBuilder()
            .setCreatedAt(LocalDateTime.now(ZoneOffset.UTC).toString())
            .setUpdatedAt(LocalDateTime.now(ZoneOffset.UTC).toString())
            .setStartAt(faker.random().nextInt(1, 100))
            .setUrl(faker.internet().url())
            .setDuration(faker.random().nextDouble())
            .setContentStatus("ready")
            .build();

    subClipsClientNoMetadata.create(grpcRequestSubClip);
  }

  @Test
  @Description("Create new subClip - INTERNAL_ERROR")
  @TmsLink("28501426")
  public void C28501426_TEST() {
    boolean isTrue = false;

    try {
      SubClip grpcRequestSubClip = SubClip.newBuilder().setContentStatus("abs").build();

      subClipsClientAuth.create(grpcRequestSubClip);
    } catch (Exception e) {
      isTrue = true;
      Assert.assertTrue(e.getMessage().contains("INTERNAL"));
    }
    Assert.assertTrue(isTrue);
  }
}
