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

import com.plutotv.test.lib.LogUtils;
import io.grpc.StatusRuntimeException;
import io.qameta.allure.Description;
import io.qameta.allure.TmsLink;
import java.util.Collections;
import java.util.List;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import tv.pluto.core.BaseTest;
import tv.pluto.grpc.lab_partner.LabPartnerClient;
import tv.pluto.mongo.entities.labpartner.GetLabPartnerObjectByEpisodeIdsResponse;
import tv.pluto.mongo.utils.MongoUtils;
import tv.pluto.mongo.utils.episodes.EpisodeUtils;
import tv.pluto.mongo.utils.labpartner.LabPartnerEpisodeUtils;
import tv.pluto.mongo.utils.labpartner.LabPartnerUtils;

public class LabPartnerTestSuite extends BaseTest {
  private LabPartnerClient labPartnerClient;
  private LabPartnerUtils labPartnerUtils;
  private LabPartnerEpisodeUtils labPartnerEpisodeUtils;
  private EpisodeUtils episodeUtils;

  @BeforeClass(alwaysRun = true)
  private void setUp() {
    labPartnerClient = new LabPartnerClient(grpcChannelManager.getChannel());
    labPartnerUtils = new LabPartnerUtils();
    labPartnerEpisodeUtils = new LabPartnerEpisodeUtils();
    episodeUtils = new EpisodeUtils();
  }

  @Test
  @Description("Multiple episodes with ageRange of one series - GetLabPartnerObjectByEpisodeIds")
  @TmsLink("28501018")
  public void C28501018_TEST() {
    List<String> episodesIds = labPartnerEpisodeUtils.getIdsOfEpisodesWithSingleSeriesAndAgeRange();
    LogUtils.logInfoMessage("C2656214_TEST episodesIds = " + episodesIds);

    GetLabPartnerObjectByEpisodeIdsResponse mongoResponse =
        labPartnerUtils.getLabPartnerObjectByEpisodeIds(episodesIds);

    GetLabPartnerObjectByEpisodeIdsResponse grpcMappedResponse =
        episodeUtils.mapGrpcObjectToPojo(
            labPartnerClient.getLabPartnerObjectByEpisodeIds(episodesIds),
            GetLabPartnerObjectByEpisodeIdsResponse.class);

    labPartnerUtils.sortInnerLists(mongoResponse.getSeries());
    labPartnerUtils.sortInnerLists(grpcMappedResponse.getSeries());

    Assert.assertEquals(mongoResponse, grpcMappedResponse);
  }

  @Test
  @Description("Multiple episodes without ageRange of one series - GetLabPartnerObjectByEpisodeIds")
  @TmsLink("28501019")
  public void C28501019_TEST() {
    List<String> episodesIds =
        labPartnerEpisodeUtils.getIdsOfEpisodesWithSingleSeriesWithoutAgeRange();

    LogUtils.logInfoMessage("C6034359_TEST episodesIds = " + episodesIds);

    GetLabPartnerObjectByEpisodeIdsResponse mongoResponse =
        labPartnerUtils.getLabPartnerObjectByEpisodeIds(episodesIds);

    GetLabPartnerObjectByEpisodeIdsResponse grpcMappedResponse =
        labPartnerUtils.mapGrpcObjectToPojo(
            labPartnerClient.getLabPartnerObjectByEpisodeIds(episodesIds),
            GetLabPartnerObjectByEpisodeIdsResponse.class);

    labPartnerUtils.sortInnerLists(mongoResponse.getSeries());
    labPartnerUtils.sortInnerLists(grpcMappedResponse.getSeries());

    mongoResponse
        .getSeries()
        .getEpisodes()
        .forEach(
            e -> {
              if (e.getClips() == null) e.setClips(Collections.emptyList());
            });

    Assert.assertEquals(mongoResponse, grpcMappedResponse);
  }

  @Test
  @Description(
      "Multiple episodes with ageRange size 0 of one series - GetLabPartnerObjectByEpisodeIds")
  @TmsLink("28501020")
  public void C28501020_TEST() {
    List<String> episodesIds =
        labPartnerEpisodeUtils.getIdsOfEpisodesWithSingleSeriesAndAgeRangeZero();

    LogUtils.logInfoMessage("C6034360_TEST episodesIds = " + episodesIds);

    GetLabPartnerObjectByEpisodeIdsResponse mongoResponse =
        labPartnerUtils.getLabPartnerObjectByEpisodeIds(episodesIds);

    GetLabPartnerObjectByEpisodeIdsResponse grpcMappedResponse =
        episodeUtils.mapGrpcObjectToPojo(
            labPartnerClient.getLabPartnerObjectByEpisodeIds(episodesIds),
            GetLabPartnerObjectByEpisodeIdsResponse.class);

    labPartnerUtils.sortInnerLists(mongoResponse.getSeries());
    labPartnerUtils.sortInnerLists(grpcMappedResponse.getSeries());

    Assert.assertEquals(mongoResponse, grpcMappedResponse);
  }

  @Test
  @Description(
      "Single episode of one series. Series with ratingDescriptors - GetLabPartnerObjectByEpisodeIds")
  @TmsLink("28501021")
  public void C28501021_TEST() {
    List<String> episodesIds = labPartnerEpisodeUtils.getIdsOfEpisodesWithSingleSeriesAndRdSeries();

    LogUtils.logInfoMessage("C6035612_TEST episodesIds = " + episodesIds);

    GetLabPartnerObjectByEpisodeIdsResponse mongoResponse =
        labPartnerUtils.getLabPartnerObjectByEpisodeIds(episodesIds);

    GetLabPartnerObjectByEpisodeIdsResponse grpcMappedResponse =
        episodeUtils.mapGrpcObjectToPojo(
            labPartnerClient.getLabPartnerObjectByEpisodeIds(episodesIds),
            GetLabPartnerObjectByEpisodeIdsResponse.class);

    labPartnerUtils.sortInnerLists(mongoResponse.getSeries());
    labPartnerUtils.sortInnerLists(grpcMappedResponse.getSeries());

    Assert.assertEquals(mongoResponse, grpcMappedResponse);
  }

  @Test
  @Description(
      "Single episode of one series. Series without ratingDescriptors - GetLabPartnerObjectByEpisodeIds")
  @TmsLink("28501022")
  public void C28501022_TEST() {
    List<String> episodesIds =
        labPartnerEpisodeUtils.getIdsOfEpisodesWithSingleSeriesWithoutRdSeries();

    LogUtils.logInfoMessage("C6035613_TEST episodesIds = " + episodesIds);

    GetLabPartnerObjectByEpisodeIdsResponse mongoResponse =
        labPartnerUtils.getLabPartnerObjectByEpisodeIds(episodesIds);

    GetLabPartnerObjectByEpisodeIdsResponse grpcMappedResponse =
        episodeUtils.mapGrpcObjectToPojo(
            labPartnerClient.getLabPartnerObjectByEpisodeIds(episodesIds),
            GetLabPartnerObjectByEpisodeIdsResponse.class);

    labPartnerUtils.sortInnerLists(mongoResponse.getSeries());
    labPartnerUtils.sortInnerLists(grpcMappedResponse.getSeries());

    Assert.assertEquals(mongoResponse, grpcMappedResponse);
  }

  @Test
  @Description(
      "Single episode of one series. Series ratingDescriptors size is 0 - GetLabPartnerObjectByEpisodeIds")
  @TmsLink("28501023")
  public void C28501023_TEST() {
    List<String> episodesIds =
        labPartnerEpisodeUtils.getIdsOfEpisodesWithSingleSeriesAndRdZeroSeries();

    LogUtils.logInfoMessage("C6035614_TEST episodesIds = " + episodesIds);

    GetLabPartnerObjectByEpisodeIdsResponse mongoResponse =
        labPartnerUtils.getLabPartnerObjectByEpisodeIds(episodesIds);

    GetLabPartnerObjectByEpisodeIdsResponse grpcMappedResponse =
        episodeUtils.mapGrpcObjectToPojo(
            labPartnerClient.getLabPartnerObjectByEpisodeIds(episodesIds),
            GetLabPartnerObjectByEpisodeIdsResponse.class);

    labPartnerUtils.sortInnerLists(mongoResponse.getSeries());
    labPartnerUtils.sortInnerLists(grpcMappedResponse.getSeries());

    Assert.assertEquals(mongoResponse, grpcMappedResponse);
  }

  @Test
  @Description(
      "Single episode of one series. Episode with ratingDescriptors - GetLabPartnerObjectByEpisodeIds")
  @TmsLink("28501024")
  public void C28501024_TEST() {
    List<String> episodesIds =
        labPartnerEpisodeUtils.getIdsOfEpisodesWithSingleSeriesAndRdEpisodes();

    LogUtils.logInfoMessage("C6035614_TEST episodesIds = " + episodesIds);

    GetLabPartnerObjectByEpisodeIdsResponse mongoResponse =
        labPartnerUtils.getLabPartnerObjectByEpisodeIds(episodesIds);

    GetLabPartnerObjectByEpisodeIdsResponse grpcMappedResponse =
        episodeUtils.mapGrpcObjectToPojo(
            labPartnerClient.getLabPartnerObjectByEpisodeIds(episodesIds),
            GetLabPartnerObjectByEpisodeIdsResponse.class);

    labPartnerUtils.sortInnerLists(mongoResponse.getSeries());
    labPartnerUtils.sortInnerLists(grpcMappedResponse.getSeries());

    Assert.assertEquals(mongoResponse, grpcMappedResponse);
  }

  @Test
  @Description(
      "Single episode of one series. Episode without ratingDescriptors - GetLabPartnerObjectByEpisodeIds")
  @TmsLink("28501025")
  public void C28501025_TEST() {
    List<String> episodesIds =
        labPartnerEpisodeUtils.getIdsOfEpisodesWithSingleSeriesWithoutRdEpisodes();

    LogUtils.logInfoMessage("C6035616_TEST episodesIds = " + episodesIds);

    GetLabPartnerObjectByEpisodeIdsResponse mongoResponse =
        labPartnerUtils.getLabPartnerObjectByEpisodeIds(episodesIds);

    GetLabPartnerObjectByEpisodeIdsResponse grpcMappedResponse =
        episodeUtils.mapGrpcObjectToPojo(
            labPartnerClient.getLabPartnerObjectByEpisodeIds(episodesIds),
            GetLabPartnerObjectByEpisodeIdsResponse.class);

    labPartnerUtils.sortInnerLists(mongoResponse.getSeries());
    labPartnerUtils.sortInnerLists(grpcMappedResponse.getSeries());

    Assert.assertEquals(mongoResponse, grpcMappedResponse);
  }

  @Test
  @Description(
      "Single episode of one series. Episode ratingDescriptors size is 0 - GetLabPartnerObjectByEpisodeIds")
  @TmsLink("28501026")
  public void C28501026_TEST() {
    List<String> episodesIds =
        labPartnerEpisodeUtils.getIdsOfEpisodesWithSingleSeriesAndRdEpisodesZero();

    LogUtils.logInfoMessage("C6035617_TEST episodesIds = " + episodesIds);

    GetLabPartnerObjectByEpisodeIdsResponse mongoResponse =
        labPartnerUtils.getLabPartnerObjectByEpisodeIds(episodesIds);

    GetLabPartnerObjectByEpisodeIdsResponse grpcMappedResponse =
        episodeUtils.mapGrpcObjectToPojo(
            labPartnerClient.getLabPartnerObjectByEpisodeIds(episodesIds),
            GetLabPartnerObjectByEpisodeIdsResponse.class);

    labPartnerUtils.sortInnerLists(mongoResponse.getSeries());
    labPartnerUtils.sortInnerLists(grpcMappedResponse.getSeries());

    mongoResponse
        .getSeries()
        .getEpisodes()
        .forEach(
            e -> {
              if (e.getClips() == null) e.setClips(Collections.emptyList());
            });

    Assert.assertEquals(mongoResponse, grpcMappedResponse);
  }

  @Test
  @Description(
      "Single episode of one series. Clips with ratingDescriptors - GetLabPartnerObjectByEpisodeIds")
  @TmsLink("28501027")
  public void C28501027_TEST() {
    List<String> episodesIds = labPartnerEpisodeUtils.getIdsOfEpisodesWithSingleSeriesAndRdClips();

    LogUtils.logInfoMessage("C6035813_TEST episodesIds = " + episodesIds);

    GetLabPartnerObjectByEpisodeIdsResponse mongoResponse =
        labPartnerUtils.getLabPartnerObjectByEpisodeIds(episodesIds);

    GetLabPartnerObjectByEpisodeIdsResponse grpcMappedResponse =
        episodeUtils.mapGrpcObjectToPojo(
            labPartnerClient.getLabPartnerObjectByEpisodeIds(episodesIds),
            GetLabPartnerObjectByEpisodeIdsResponse.class);

    labPartnerUtils.sortInnerLists(mongoResponse.getSeries());
    labPartnerUtils.sortInnerLists(grpcMappedResponse.getSeries());

    Assert.assertEquals(mongoResponse, grpcMappedResponse);
  }

  // Run locally. Runs too long. fix query performance
  @Test(enabled = false)
  @Description(
      "Single episode of one series. Clips without ratingDescriptors - GetLabPartnerObjectByEpisodeIds")
  @TmsLink("28501028")
  public void C28501028_TEST() {
    List<String> episodesIds =
        labPartnerEpisodeUtils.getIdsOfEpisodesWithSingleSeriesWithoutRdClips();

    LogUtils.logInfoMessage("C6035814_TEST episodesIds = " + episodesIds);

    GetLabPartnerObjectByEpisodeIdsResponse mongoResponse =
        labPartnerUtils.getLabPartnerObjectByEpisodeIds(episodesIds);

    GetLabPartnerObjectByEpisodeIdsResponse grpcMappedResponse =
        episodeUtils.mapGrpcObjectToPojo(
            labPartnerClient.getLabPartnerObjectByEpisodeIds(episodesIds),
            GetLabPartnerObjectByEpisodeIdsResponse.class);

    labPartnerUtils.sortInnerLists(mongoResponse.getSeries());
    labPartnerUtils.sortInnerLists(grpcMappedResponse.getSeries());

    Assert.assertEquals(mongoResponse, grpcMappedResponse);
  }

  @Test
  @Description(
      "Single episode of one series. Clips ratingDescriptors size 0 - GetLabPartnerObjectByEpisodeIds")
  @TmsLink("28501029")
  public void C28501029_TEST() {
    List<String> episodesIds =
        labPartnerEpisodeUtils.getIdsOfEpisodesWithSingleSeriesAndRdClipsZero();

    LogUtils.logInfoMessage("C6035815_TEST episodesIds = " + episodesIds);

    GetLabPartnerObjectByEpisodeIdsResponse mongoResponse =
        labPartnerUtils.getLabPartnerObjectByEpisodeIds(episodesIds);

    GetLabPartnerObjectByEpisodeIdsResponse grpcMappedResponse =
        episodeUtils.mapGrpcObjectToPojo(
            labPartnerClient.getLabPartnerObjectByEpisodeIds(episodesIds),
            GetLabPartnerObjectByEpisodeIdsResponse.class);

    labPartnerUtils.sortInnerLists(mongoResponse.getSeries());
    labPartnerUtils.sortInnerLists(grpcMappedResponse.getSeries());

    Assert.assertEquals(mongoResponse, grpcMappedResponse);
  }

  @Test(
      expectedExceptions = StatusRuntimeException.class,
      expectedExceptionsMessageRegExp =
          "INTERNAL: EpisodeIds are associated with more than one series. Only include episodes associated with one series.")
  @Description(
      "Multiple episodes associated with multiple series - GetLabPartnerObjectByEpisodeIds")
  @TmsLink("28501030")
  public void C28501030_TEST() {
    List<String> episodesIds = labPartnerEpisodeUtils.getIdsOfEpisodesForMultipleSeries();
    labPartnerClient.getLabPartnerObjectByEpisodeIds(episodesIds);
  }

  @Test(
      expectedExceptions = StatusRuntimeException.class,
      expectedExceptionsMessageRegExp =
          "NOT_FOUND: No Episodes found matching provided episodeIds.")
  @Description("Non existing episode - GetLabPartnerObjectByEpisodeIds")
  @TmsLink("28501031")
  public void C28501031_TEST() {
    List<String> randomEpisodesIds = Collections.singletonList(MongoUtils.INVALID_ID_VALUE);
    labPartnerClient.getLabPartnerObjectByEpisodeIds(randomEpisodesIds);
  }

  @Test(
      expectedExceptions = StatusRuntimeException.class,
      expectedExceptionsMessageRegExp = "INTERNAL: Series matching episode fk seriesId not found.")
  @Description("Episode without series - GetLabPartnerObjectByEpisodeIds")
  @TmsLink("28501032")
  public void C28501032_TEST() {
    labPartnerClient.getLabPartnerObjectByEpisodeIds(
        Collections.singletonList(episodeUtils.getIdOfEpisodeWithoutSeries()));
  }
}
