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

import static tv.pluto.mongo.utils.MongoUtils.INVALID_ID_VALUE;

import com.google.gson.GsonBuilder;
import com.mongodb.BasicDBObject;
import com.plutotv.test.lib.LogUtils;
import io.grpc.StatusRuntimeException;
import io.qameta.allure.Description;
import io.qameta.allure.Issue;
import io.qameta.allure.TmsLink;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.Instant;
import java.time.ZoneOffset;
import java.time.temporal.ChronoUnit;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.bson.types.ObjectId;
import org.everit.json.schema.Schema;
import org.everit.json.schema.loader.SchemaLoader;
import org.json.JSONObject;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import tv.pluto.core.BaseTest;
import tv.pluto.grpc.timelinedrafts.TimelineDraftsClient;
import tv.pluto.ip.dal.timelinedrafts.TimelineDrafts.DeleteTimelinesDraftInChannelByDatesResponse;
import tv.pluto.ip.dal.timelinedrafts.TimelineDrafts.GetPopulatedTimelineDraftsByChannelIdResponse;
import tv.pluto.ip.dal.timelinedrafts.TimelineDrafts.GetTimelineDraftsByChannelIdResponse;
import tv.pluto.ip.dal.timelinedrafts.TimelineDrafts.GetTimelineDraftsLiteByChannelIdResponse;
import tv.pluto.ip.dal.timelinedrafts.TimelineDrafts.TimelineDraft;
import tv.pluto.mongo.entities.episodes.Episodes;
import tv.pluto.mongo.entities.timelinedrafts.TimelineDrafts;
import tv.pluto.mongo.entities.timelinedrafts.populated_timeline_drafts.Episode;
import tv.pluto.mongo.entities.timelinedrafts.populated_timeline_drafts.TimelineDraftPopulated;
import tv.pluto.mongo.entities.timelines.Timelines;
import tv.pluto.mongo.utils.TimelineDraftsUtils;
import tv.pluto.mongo.utils.episodes.EpisodeUtils;
import tv.pluto.mongo.utils.populated_timeline_drafts.TimelineDraftsByChannelIdUtils;

public class TimelineDraftsTestSuite extends BaseTest {
  private TimelineDraftsClient timelineDraftsClient;
  private TimelineDraftsClient authTimelineDraftsClient;
  private TimelineDraftsUtils timelineDraftUtils;
  private EpisodeUtils episodeUtils;
  private TimelineDraftsByChannelIdUtils timelineDraftsByChannelIdUtils;

  @BeforeClass(alwaysRun = true)
  private void setUp() {
    timelineDraftsClient = new TimelineDraftsClient(grpcChannelManager.getChannel(), false);
    authTimelineDraftsClient = new TimelineDraftsClient(grpcChannelManager.getChannel(), true);
    timelineDraftUtils = new TimelineDraftsUtils();
    episodeUtils = new EpisodeUtils();
    timelineDraftsByChannelIdUtils = new TimelineDraftsByChannelIdUtils();
  }

  @Test(enabled = false)
  @Description("UpdateTimelinesBulk - delete")
  @TmsLink("28501550")
  public void C28501550_TEST() {
    List<TimelineDrafts> listTimelines = timelineDraftUtils.getDocuments(2);
    List<String> listIds = List.of(listTimelines.get(0).getId(), listTimelines.get(1).getId());
    new TimelineDraftsClient(grpcChannelManager.getChannel(), false)
        .updateTimelinesBulk(listIds, null);

    List<Timelines> documentsByIds = timelineDraftUtils.getDocumentsByIds(listIds);
    Assert.assertTrue(documentsByIds.isEmpty());
  }

  @Test
  @Description("UpdateTimelinesBulk - create a new DraftTimeline")
  @TmsLink("28501551")
  public void C28501551_TEST() {
    TimelineDrafts timelines = timelineDraftUtils.getRandomDocument();
    String newChannel = timelines.getEpisode();
    String newEpisode = timelines.getChannel();

    Instant timeNow = Instant.now();
    String stringTimeNow = timeNow.toString();

    TimelineDraft timelineDraft =
        TimelineDraft.newBuilder()
            .setChannel(newChannel)
            .setEpisode(newEpisode)
            .setStart(timelines.getStart().toString())
            .setStop(timelines.getStop().toString())
            .setCreatedAt(stringTimeNow)
            .setUpdatedAt(stringTimeNow)
            .setManualOverrideMarker(stringTimeNow)
            .setFeatured(timelines.getFeatured())
            .build();

    timelineDraftsClient.updateTimelinesBulk(null, timelineDraft);

    BasicDBObject query = new BasicDBObject();
    query.put("channel", new ObjectId(newChannel));
    query.put("episode", new ObjectId(newEpisode));

    List<TimelineDrafts> listTimelines = timelineDraftUtils.getDocuments(query, 10);
    Assert.assertFalse(listTimelines.isEmpty());
    TimelineDrafts timelineDrafts = listTimelines.get(listTimelines.size() - 1);

    Instant now = timeNow.truncatedTo(ChronoUnit.MINUTES);
    Assert.assertEquals(
        now, timelineDrafts.getCreatedAt().toInstant().truncatedTo(ChronoUnit.MINUTES));
    Assert.assertEquals(
        now,
        timelineDrafts.getUpdatedAt().toInstant(ZoneOffset.UTC).truncatedTo(ChronoUnit.MINUTES));
    //        Assert.assertEquals(now,
    // timelineDrafts.getManualOverrideMarker().toInstant().truncatedTo(ChronoUnit.MINUTES));

    timelineDraftsClient.updateTimelinesBulk(List.of(timelineDrafts.getId()), null);
  }

  @Test
  @Description("UpdateTimelinesBulk - update existing DraftTimeline")
  @TmsLink("28501552")
  public void C28501552_TEST() {
    TimelineDrafts timelines = timelineDraftUtils.getRandomDocument();
    String newChannel = timelines.getEpisode();
    String newEpisode = timelines.getChannel();

    Instant timeNow = Instant.now();
    String stringTimeNow = timeNow.toString();
    String testId = timelines.getId();

    TimelineDraft timelineDraft =
        TimelineDraft.newBuilder()
            .setChannel(newChannel)
            .setEpisode(newEpisode)
            .setStart(timelines.getStart().toString())
            .setStop(timelines.getStop().toString())
            .setId(testId)
            .setCreatedAt(stringTimeNow)
            .setUpdatedAt(stringTimeNow)
            .setManualOverrideMarker(stringTimeNow)
            .setFeatured(timelines.getFeatured())
            .build();

    new TimelineDraftsClient(grpcChannelManager.getChannel(), false)
        .updateTimelinesBulk(null, timelineDraft);
    TimelineDrafts updatedTimeline = timelineDraftUtils.getDocumentById(testId);
    Assert.assertFalse(updatedTimeline.getId().isEmpty());

    Instant now = timeNow.truncatedTo(ChronoUnit.MINUTES);
    Assert.assertEquals(
        now, updatedTimeline.getCreatedAt().toInstant().truncatedTo(ChronoUnit.MINUTES));
    Assert.assertEquals(
        now,
        updatedTimeline.getUpdatedAt().toInstant(ZoneOffset.UTC).truncatedTo(ChronoUnit.MINUTES));
    //        Assert.assertEquals(now,
    // updatedTimeline.getManualOverrideMarker().toInstant().truncatedTo(ChronoUnit.MINUTES));
    new TimelineDraftsClient(grpcChannelManager.getChannel(), false)
        .updateTimelinesBulk(List.of(testId), null);
  }

  @Test(
      expectedExceptions = RuntimeException.class,
      expectedExceptionsMessageRegExp =
          "INVALID_ARGUMENT: DeleteIds and/or CreateObjects parameters cannot be empty.")
  @Description("UpdateTimelinesBulk - empty body")
  @TmsLink("28501553")
  public void C28501553_TEST() {
    timelineDraftsClient.updateTimelinesBulk(null, null);
  }

  @Test
  @Description("GetPopulatedTimelineDraftsByChannelId - existing ID")
  @TmsLink("28501554")
  public void C28501554_TEST() {
    TimelineDrafts timelineDrafts = timelineDraftUtils.getRandomDocument();

    String channelId = timelineDrafts.getChannel();
    long start = timelineDrafts.getStart().getTime();
    long stop = timelineDrafts.getStop().getTime();

    LogUtils.logInfoMessage("Running test case C23866534_TEST");
    LogUtils.logInfoMessage("ChannelID = " + channelId);
    LogUtils.logInfoMessage("start = " + start);
    LogUtils.logInfoMessage("stop = " + stop);
    LogUtils.logInfoMessage("TimelineDrafts id: " + timelineDrafts.getId());

    List<TimelineDraftPopulated> grpcTimelineDrafts =
        timelineDraftUtils.mapGrpcObjectsToPojo(
            timelineDraftsClient
                .getPopulatedTimelineDraftsByChannelId(channelId, start, stop)
                .getDocumentsList(),
            TimelineDraftPopulated.class);

    List<TimelineDraftPopulated> mongoTimelineDrafts =
        timelineDraftsByChannelIdUtils.getPopulatedTimelineDraftsByChannelId(
            channelId, start, stop);

    // To do. Need to check some test data if remove Not Rated line
    mongoTimelineDrafts.forEach(d -> d.getEpisode().setRating("Not Rated"));
    grpcTimelineDrafts.forEach(d -> d.getEpisode().setRating("Not Rated"));

    Assert.assertEquals(mongoTimelineDrafts, grpcTimelineDrafts);
  }

  @Test(
      expectedExceptions = RuntimeException.class,
      expectedExceptionsMessageRegExp = "INVALID_ARGUMENT: Channel ID cannot be undefined or empty")
  @Description("GetPopulatedTimelineDraftsByChannelId - empty ID")
  @TmsLink("28501558")
  public void C28501558_TEST() {
    timelineDraftsClient.getPopulatedTimelineDraftsByChannelId("", 0, 0);
  }

  @Test(
      expectedExceptions = RuntimeException.class,
      expectedExceptionsMessageRegExp =
          "NOT_FOUND: TimelineDraft document for requested ID not found")
  @Description("GetPopulatedTimelineDraftsByChannelId - invalid request")
  @TmsLink("28501556")
  public void C28501556_TEST() {
    timelineDraftsClient.getPopulatedTimelineDraftsByChannelId(INVALID_ID_VALUE, 0, 0);
  }

  @Test
  @Description("GetPopulatedTimelineDraftsByChannelId - valid schema")
  @TmsLink("28501557")
  public void C28501557_TEST() throws IOException {
    String channelId = ((TimelineDrafts) timelineDraftUtils.getRandomDocument()).getChannel();
    GetPopulatedTimelineDraftsByChannelIdResponse populatedByChannelId =
        timelineDraftsClient.getPopulatedTimelineDraftsByChannelId(channelId, 0, 0);

    String stringComScore =
        Files.readString(
            Paths.get("src/main/resources/schema/getPopulatedTimelineDraftsChannelId.json"));

    String populated = new GsonBuilder().create().toJson(populatedByChannelId);
    JSONObject populatedStringJson = new JSONObject(populated);

    JSONObject schemaJson = new JSONObject(stringComScore);
    Schema schema = SchemaLoader.load(populatedStringJson);

    JSONObject responseJson = new JSONObject(schemaJson);
    schema.validate(responseJson);
  }

  @Test
  @Description("DeleteTimelinesDraftInChannelUsingDates - happy path")
  @TmsLink("28501559")
  public void C28501559_TEST() {
    TimelineDrafts timelineDraft = timelineDraftUtils.getRandomDocument();
    Instant stop = timelineDraft.getStop().toInstant().plusMillis(1);

    BasicDBObject query = new BasicDBObject();
    query.put("channel", new ObjectId(timelineDraft.getChannel()));
    query.put("start", new BasicDBObject("$gte", timelineDraft.getStart()));
    query.put("stop", new BasicDBObject("$lt", stop));

    List<TimelineDrafts> listTimelines = timelineDraftUtils.getDocuments(query, 500);

    Assert.assertTrue(listTimelines.size() > 0);

    DeleteTimelinesDraftInChannelByDatesResponse response =
        timelineDraftsClient.deleteTimelinesDraftInChannelByDatesRequest(
            timelineDraft.getChannel(),
            timelineDraft.getStart().toInstant().toString(),
            stop.toString());

    Assert.assertEquals(response.getDeletedCount(), listTimelines.size());
    Assert.assertNull(timelineDraftUtils.getDocumentById(timelineDraft.getId()));
  }

  @Test
  @Description("DeleteTimelinesInChannelDraftUsingDates - invalid channelId")
  @TmsLink("28501560")
  public void C28501560_TEST() {
    TimelineDrafts timelineDraft = timelineDraftUtils.getRandomDocument();
    Instant stop = timelineDraft.getStop().toInstant().plusMillis(1);

    DeleteTimelinesDraftInChannelByDatesResponse response =
        timelineDraftsClient.deleteTimelinesDraftInChannelByDatesRequest(
            "00000000dbdaaa0000000000",
            timelineDraft.getStart().toInstant().toString(),
            stop.toString());
    Assert.assertEquals(0, response.getDeletedCount());
  }

  @Test
  @Description("DeleteTimelinesInChannelDraftUsingDates - start date and stop dates are the same")
  @TmsLink("28501561")
  public void C28501561_TEST() {
    TimelineDrafts timelineDraft = timelineDraftUtils.getRandomDocument();

    BasicDBObject query = new BasicDBObject();
    query.put("channel", new ObjectId(timelineDraft.getChannel()));
    query.put("start", new BasicDBObject("$gte", timelineDraft.getStart()));
    query.put("stop", new BasicDBObject("$lt", timelineDraft.getStart()));

    List<TimelineDrafts> listTimelines = timelineDraftUtils.getDocuments(query, 500);

    Assert.assertEquals(listTimelines.size(), 0);
    String start = timelineDraft.getStart().toInstant().toString();

    DeleteTimelinesDraftInChannelByDatesResponse response =
        timelineDraftsClient.deleteTimelinesDraftInChannelByDatesRequest(
            timelineDraft.getChannel(), start, start);

    Assert.assertEquals(response.getDeletedCount(), 0);
  }

  @Test
  @Description("GetLatestManuallyCreatedTimelineDraft - get document")
  @TmsLink("28501562")
  public void C28501562_TEST() {
    BasicDBObject queryManual = new BasicDBObject();
    queryManual.put("manualOverrideMarker", new BasicDBObject("$exists", true));

    TimelineDrafts timelineDraft =
        (TimelineDrafts) timelineDraftUtils.getDocuments(queryManual, 1).get(0);
    Instant stop = timelineDraft.getStop().toInstant().plusMillis(1);

    BasicDBObject query = new BasicDBObject();
    query.put("channel", new ObjectId(timelineDraft.getChannel()));
    query.put("start", new BasicDBObject("$gte", timelineDraft.getStart()));
    query.put("stop", new BasicDBObject("$lt", stop));
    query.put("manualOverrideMarker", new BasicDBObject("$exists", true));

    List<TimelineDrafts> listTimelines = timelineDraftUtils.getDocuments(query, 10);

    Assert.assertTrue(listTimelines.size() > 0);

    TimelineDraft responseTimelineDraft =
        timelineDraftsClient
            .getLatestManuallyCreatedTimelineDraft(
                timelineDraft.getChannel(),
                timelineDraft.getStart().toInstant().toString(),
                stop.toString())
            .getDocument();

    TimelineDrafts timelineDraftsGrpc =
        timelineDraftUtils.mapGrpcObjectToPojo(responseTimelineDraft, TimelineDrafts.class);
    Assert.assertEquals(timelineDraft, timelineDraftsGrpc);
  }

  @Test(
      expectedExceptions = RuntimeException.class,
      expectedExceptionsMessageRegExp =
          "NOT_FOUND: TimelineDraft document for requested ID not found")
  @Description("GetLatestManuallyCreatedTimelineDraft - invalid channelId")
  @TmsLink("28501563")
  public void C28501563_TEST() {
    BasicDBObject queryManual = new BasicDBObject();
    queryManual.put("manualOverrideMarker", new BasicDBObject("$exists", true));

    TimelineDrafts timelineDraft =
        (TimelineDrafts) timelineDraftUtils.getDocuments(queryManual, 1).get(0);
    Instant stop = timelineDraft.getStop().toInstant().plusMillis(1);

    timelineDraftsClient.getLatestManuallyCreatedTimelineDraft(
        "00000f988ab9780007f00000",
        timelineDraft.getStart().toInstant().toString(),
        stop.toString());
  }

  @Issue("TestDateIssueStringDate")
  @Test(enabled = false)
  @Description("GetLatestManuallyCreatedTimelineDraft - get document without end field")
  @TmsLink("28501564")
  public void C28501564_TEST() {
    BasicDBObject queryManual = new BasicDBObject();
    queryManual.put("manualOverrideMarker", new BasicDBObject("$exists", true));

    TimelineDrafts timelineDraft =
        (TimelineDrafts) timelineDraftUtils.getDocuments(queryManual, 1).get(0);

    BasicDBObject query = new BasicDBObject();
    query.put("channel", new ObjectId(timelineDraft.getChannel()));
    query.put("start", new BasicDBObject("$gte", timelineDraft.getStart()));
    query.put("manualOverrideMarker", new BasicDBObject("$exists", true));

    List<TimelineDrafts> listTimelines = timelineDraftUtils.getDocuments(query, 99_999);

    Assert.assertTrue(listTimelines.size() > 0);

    TimelineDraft responseTimelineDraft =
        timelineDraftsClient
            .getLatestManuallyCreatedTimelineDraft(
                timelineDraft.getChannel(), timelineDraft.getStart().toInstant().toString(), "")
            .getDocument();

    TimelineDrafts timelineDraftsGrpc =
        timelineDraftUtils.mapGrpcObjectToPojo(responseTimelineDraft, TimelineDrafts.class);

    //        listTimelines.sort(Comparator.comparing(TimelineDrafts::getManualOverrideMarker));

    Assert.assertTrue(listTimelines.contains(timelineDraftsGrpc));
    Assert.assertEquals(listTimelines.get(listTimelines.size() - 1), timelineDraftsGrpc);
  }

  @Test
  @Description("Create TimeDraft - happy path")
  @TmsLink("28501565")
  public void C28501565_TEST() {
    TimelineDraft draft =
        tv.pluto.ip.dal.timelinedrafts.TimelineDrafts.TimelineDraft.newBuilder()
            .setStart("2023-10-10T00:00:00.000Z")
            .setStop("2023-10-11T00:00:00.000Z")
            .setEpisode("5595a7284cfe2e6c2e4da995")
            .setFeatured(true)
            .setChannel("52740c58ed08727d5800058a")
            .setManualOverrideMarker("")
            .build();

    tv.pluto.ip.dal.timelinedrafts.TimelineDrafts.TimelineDraft createdDraft =
        authTimelineDraftsClient.createDrafts(draft).getDocument();

    String createdId = createdDraft.getId();
    LogUtils.logInfoMessage("Created a new id: " + createdId);

    Assert.assertFalse(draft.getEpisode().isEmpty());
    Assert.assertFalse(createdId.isEmpty());
    Assert.assertFalse(createdDraft.getCreatedAt().isEmpty());
    Assert.assertFalse(createdDraft.getUpdatedAt().isEmpty());
    Assert.assertEquals(draft.getEpisode(), createdDraft.getEpisode());
    Assert.assertEquals(draft.getChannel(), createdDraft.getChannel());
    Assert.assertEquals(draft.getStart(), createdDraft.getStart());
    Assert.assertEquals(draft.getStop(), createdDraft.getStop());
    Assert.assertEquals(draft.getFeatured(), createdDraft.getFeatured());
    Assert.assertEquals(draft.getManualOverrideMarker(), createdDraft.getManualOverrideMarker());

    Assert.assertNotNull(timelineDraftUtils.getDocumentById(createdId));
  }

  @Test(
      expectedExceptions = StatusRuntimeException.class,
      expectedExceptionsMessageRegExp = "INTERNAL.*")
  @Description("Create TimeDraft - no start date")
  @TmsLink("28501566")
  public void C28501566_TEST() {
    TimelineDraft draft =
        tv.pluto.ip.dal.timelinedrafts.TimelineDrafts.TimelineDraft.newBuilder()
            .setStop("2023-10-11T00:00:00.000Z")
            .setEpisode("5595a7284cfe2e6c2e4da995")
            .setFeatured(true)
            .setChannel("52740c58ed08727d5800058a")
            .setManualOverrideMarker("")
            .build();

    authTimelineDraftsClient.createDrafts(draft).getDocument();
  }

  @Test(
      expectedExceptions = StatusRuntimeException.class,
      expectedExceptionsMessageRegExp = "INTERNAL.*")
  @Description("Create TimeDraft - no stop date")
  @TmsLink("28501567")
  public void C28501567_TEST() {
    TimelineDraft draft =
        tv.pluto.ip.dal.timelinedrafts.TimelineDrafts.TimelineDraft.newBuilder()
            .setStart("2023-10-11T00:00:00.000Z")
            .setEpisode("5595a7284cfe2e6c2e4da995")
            .setFeatured(true)
            .setChannel("52740c58ed08727d5800058a")
            .setManualOverrideMarker("")
            .build();

    authTimelineDraftsClient.createDrafts(draft).getDocument();
  }

  @Test
  @Description("GetTimelinesByChannelId - happy path")
  @TmsLink("28501568")
  public void C28501568_TEST() {
    TimelineDrafts timelineDraft = timelineDraftUtils.getRandomDocument();
    Instant stop = timelineDraft.getStop().toInstant().plusSeconds(5);

    BasicDBObject query = new BasicDBObject();
    query.put("channel", new ObjectId(timelineDraft.getChannel()));
    query.put("start", new BasicDBObject("$gte", timelineDraft.getStart()));
    query.put("stop", new BasicDBObject("$lt", stop));

    List<TimelineDrafts> listTimelines = timelineDraftUtils.getDocuments(query, 500);

    Assert.assertTrue(listTimelines.size() > 0);

    GetTimelineDraftsByChannelIdResponse timelinesByChannelId =
        timelineDraftsClient.getTimelineDraftsByChannelId(
            timelineDraft.getChannel(),
            timelineDraft.getStart().toInstant().toString(),
            stop.toString());

    List<TimelineDrafts> timelineDraftsList =
        timelineDraftUtils.mapGrpcObjectsToPojo(
            timelinesByChannelId.getDocumentsList(), TimelineDrafts.class);

    Assert.assertFalse(timelineDraftsList.isEmpty());

    listTimelines.sort(Comparator.comparing(TimelineDrafts::getId));
    timelineDraftsList.sort(Comparator.comparing(TimelineDrafts::getId));

    Assert.assertEquals(timelineDraftsList.size(), listTimelines.size());
    Assert.assertEquals(timelineDraftsList, listTimelines);
  }

  @Test(
      expectedExceptions = RuntimeException.class,
      expectedExceptionsMessageRegExp =
          "NOT_FOUND: TimelineDraft document for requested ID not found")
  @Description("GetTimelinesByChannelId - invalid channelId")
  @TmsLink("28501569")
  public void C28501569_TEST() {
    TimelineDrafts timelineDraft = timelineDraftUtils.getRandomDocument();
    Instant stop = timelineDraft.getStop().toInstant().plusMillis(1);

    GetTimelineDraftsByChannelIdResponse response =
        timelineDraftsClient.getTimelineDraftsByChannelId(
            "00000000dbdaaa0000000000",
            timelineDraft.getStart().toInstant().toString(),
            stop.toString());
    Assert.assertEquals(0, response.getDocumentsList().size());
  }

  @Test(
      expectedExceptions = RuntimeException.class,
      expectedExceptionsMessageRegExp =
          "NOT_FOUND: TimelineDraft document for requested ID not found")
  @Description("GetTimelinesByChannelId - start date and stop dates are the same")
  @TmsLink("28501570")
  public void C28501570_TEST() {
    TimelineDrafts timelineDraft = timelineDraftUtils.getRandomDocument();

    BasicDBObject query = new BasicDBObject();
    query.put("channel", new ObjectId(timelineDraft.getChannel()));
    query.put("start", new BasicDBObject("$gte", timelineDraft.getStart()));
    query.put("stop", new BasicDBObject("$lt", timelineDraft.getStart()));

    List<TimelineDrafts> listTimelines = timelineDraftUtils.getDocuments(query, 500);

    Assert.assertEquals(listTimelines.size(), 0);
    String start = timelineDraft.getStart().toInstant().toString();

    timelineDraftsClient.getTimelineDraftsByChannelId(timelineDraft.getChannel(), start, start);
  }

  @Test
  @Description("GetTimelinesByChannelId - happy path no stop")
  @TmsLink("28501571")
  public void C28501571_TEST() {
    TimelineDrafts timelineDraft = timelineDraftUtils.getSortedDocumentByField("start", -1);
    BasicDBObject query = new BasicDBObject();
    query.put("channel", new ObjectId(timelineDraft.getChannel()));
    query.put("start", new BasicDBObject("$gte", timelineDraft.getStart()));

    List<TimelineDrafts> listTimelines = timelineDraftUtils.getDocuments(query, 99000);

    Assert.assertTrue(listTimelines.size() > 0);

    GetTimelineDraftsByChannelIdResponse timelinesByChannelId =
        timelineDraftsClient.getTimelineDraftsByChannelId(
            timelineDraft.getChannel(), timelineDraft.getStart().toInstant().toString(), "");

    List<TimelineDrafts> timelineDraftsList =
        timelineDraftUtils.mapGrpcObjectsToPojo(
            timelinesByChannelId.getDocumentsList(), TimelineDrafts.class);

    Assert.assertFalse(timelineDraftsList.isEmpty());

    listTimelines.sort(Comparator.comparing(TimelineDrafts::getId));
    timelineDraftsList.sort(Comparator.comparing(TimelineDrafts::getId));

    Assert.assertEquals(timelineDraftsList.size(), listTimelines.size());
    Assert.assertEquals(timelineDraftsList, listTimelines);
  }

  @Test
  @Description("GetTimelinesByChannelId - channel, start, stop")
  @TmsLink("28501573")
  public void C28501573_TEST() {
    TimelineDrafts timelines = timelineDraftUtils.getRandomDocument();
    Instant start = timelines.getStart().toInstant();
    Instant stop = timelines.getStop().toInstant();
    LogUtils.logInfoMessage(
        "ChannelId: "
            + timelines.getChannel()
            + ", start: "
            + start.toEpochMilli()
            + ", stop: "
            + stop.toEpochMilli());

    GetTimelineDraftsLiteByChannelIdResponse request =
        timelineDraftsClient.getTimelineDraftsLiteByChannelIdRequest(
            timelines.getChannel(), start.toEpochMilli(), stop.toEpochMilli());
    tv.pluto.ip.dal.timelinedrafts.TimelineDrafts.TimelineDraftLite timelineLite =
        request.getDocumentsList().get(0);
    Assert.assertEquals(timelines.getEpisode(), timelineLite.getEpisode().getId());

    long startResponse = Instant.parse(timelineLite.getStart()).toEpochMilli();
    long stopResponse = Instant.parse(timelineLite.getStop()).toEpochMilli();

    Assert.assertTrue(start.toEpochMilli() <= startResponse);
    Assert.assertTrue(stop.toEpochMilli() <= stopResponse);
  }

  @Test
  @Description("GetTimelinesByChannelId - channel, start")
  @TmsLink("28501572")
  public void C28501572_TEST() {
    TimelineDrafts timelines = timelineDraftUtils.getRandomDocument();
    Instant start = timelines.getStart().toInstant();
    LogUtils.logInfoMessage(
        "ChannelId: " + timelines.getChannel() + ", start: " + start.toEpochMilli());

    GetTimelineDraftsLiteByChannelIdResponse request =
        timelineDraftsClient.getTimelineDraftsLiteByChannelIdRequest(
            timelines.getChannel(), start.toEpochMilli(), null);

    request
        .getDocumentsList()
        .forEach(
            timelineLite -> {
              long startResponse = Instant.parse(timelineLite.getStart()).toEpochMilli();

              Assert.assertTrue(start.toEpochMilli() <= startResponse);
            });
  }

  @Test
  @Description("GetTimelinesByChannelId - channel")
  @TmsLink("28501574")
  public void C28501574_TEST() {
    TimelineDrafts timelines = timelineDraftUtils.getRandomDocument();
    LogUtils.logInfoMessage("ChannelId: " + timelines.getChannel());

    GetTimelineDraftsLiteByChannelIdResponse request =
        timelineDraftsClient.getTimelineDraftsLiteByChannelIdRequest(
            timelines.getChannel(), null, null);
    Set<String> setGrpcIds =
        request.getDocumentsList().stream().map(t -> t.getId()).collect(Collectors.toSet());

    List<TimelineDrafts> timelinesList =
        timelineDraftUtils.getDocumentsByFieldAndId("channel", timelines.getChannel());
    Set<String> setIds = timelinesList.stream().map(t -> t.getId()).collect(Collectors.toSet());

    Assert.assertEquals(setIds, setGrpcIds);
  }

  @Test
  @Description("GetPopulatedTimelineDraftsByChannelId - episode.rating exist")
  @TmsLink("28501555")
  public void C28501555_TEST() {
    TimelineDrafts timeline = timelineDraftUtils.getRandomDocument();

    String channelId = timeline.getChannel();
    long start = timeline.getStart().getTime();
    long stop = timeline.getStop().getTime();

    List<TimelineDraftPopulated> timelinesGrpc =
        timelineDraftUtils.mapGrpcObjectsToPojo(
            timelineDraftsClient
                .getPopulatedTimelineDraftsByChannelId(channelId, start, stop)
                .getDocumentsList(),
            TimelineDraftPopulated.class);

    Episode episode = timelinesGrpc.get(0).getEpisode();
    Episodes episodesDb = episodeUtils.getDocumentById(episode.getId());
    Assert.assertEquals(episodesDb.getRating(), episode.getRating());
    Assert.assertNotNull(episodesDb.getRating());
  }

  @Test(
      expectedExceptions = RuntimeException.class,
      expectedExceptionsMessageRegExp = "INVALID_ARGUMENT: Channel ID cannot be undefined or empty")
  @Description("GetTimelinesByChannelId - no channel")
  @TmsLink("28501575")
  public void C28501575_TEST() {
    timelineDraftsClient.getTimelineDraftsLiteByChannelIdRequest(null, null, null);
  }

  @Test
  @Description("GetPopulatedTimelineDraftsByChannelId - Validate has_live_broadcast is present")
  @TmsLink("28501576")
  public void C28501576_TEST() {
    TimelineDrafts timelineDrafts = timelineDraftUtils.getRandomDocument();
    Assert.assertNotNull(timelineDrafts, "TimelineDrafts is null");

    String channelId = timelineDrafts.getChannel();
    long start = timelineDrafts.getStart().getTime();
    long stop = timelineDrafts.getStop().getTime();

    LogUtils.logInfoMessage("Running test case ValidateHasLiveBroadcastField_TEST");
    LogUtils.logInfoMessage("ChannelID = " + channelId);
    LogUtils.logInfoMessage("start = " + start);
    LogUtils.logInfoMessage("stop = " + stop);

    List<TimelineDraftPopulated> grpcTimelineDrafts =
        timelineDraftUtils.mapGrpcObjectsToPojo(
            timelineDraftsClient
                .getPopulatedTimelineDraftsByChannelId(channelId, start, stop)
                .getDocumentsList(),
            TimelineDraftPopulated.class);

    Assert.assertNotNull(grpcTimelineDrafts, "gRPC response is null");
    Assert.assertFalse(grpcTimelineDrafts.isEmpty(), "No timeline drafts found in gRPC response");

    for (TimelineDraftPopulated grpcDraft : grpcTimelineDrafts) {
      Assert.assertNotNull(grpcDraft, "TimelineDraftPopulated is null");

      Assert.assertNotNull(
          grpcDraft.getHasLiveBroadcast(),
          "has_live_broadcast field is not accessible for timeline draft ID: ");
    }
  }
}
