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

import static com.mongodb.client.model.Projections.include;
import static com.mongodb.client.model.Sorts.ascending;
import static com.mongodb.client.model.Sorts.descending;
import static com.mongodb.client.model.Sorts.orderBy;
import static tv.pluto.ip.dal.channels.Channels.Channel.newBuilder;
import static tv.pluto.ip.dal.channels.Channels.ChannelLite;
import static tv.pluto.ip.dal.channels.Channels.GetAllPagedChannelLiteResponse;
import static tv.pluto.ip.dal.channels.Channels.GetAllPagedResponse;
import static tv.pluto.ip.dal.channels.Channels.GetAllPagedSort;
import static tv.pluto.ip.dal.channels.Channels.GetCFaasIntegratedChannelResponse;
import static tv.pluto.ip.dal.channels.Channels.GetChannelByFilterRequest;
import static tv.pluto.ip.dal.channels.Channels.GetChannelByFilterResponse;
import static tv.pluto.ip.dal.channels.Channels.GetLibrarySumDurationRequest;
import static tv.pluto.ip.dal.channels.Channels.GetLibrarySumDurationResponse;
import static tv.pluto.ip.dal.channels.Channels.GetQueueSumDurationRequest;
import static tv.pluto.ip.dal.channels.Channels.GetQueueSumDurationResponse;
import static tv.pluto.ip.dal.channels.Channels.UpdateFieldsResponse;
import static tv.pluto.mongo.utils.MongoUtils.INVALID_ID_VALUE;
import static tv.pluto.mongo.utils.MongoUtils.addYearsToDate;

import com.google.gson.Gson;
import com.mongodb.BasicDBObject;
import com.plutotv.test.lib.LogUtils;
import com.plutotv.test.lib.ttfb.grpc.GrpcCall;
import com.plutotv.test.lib.ttfb.grpc.TTFBGrpcValidator;
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.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import net.datafaker.Faker;
import org.assertj.core.api.SoftAssertions;
import org.bson.conversions.Bson;
import org.bson.types.ObjectId;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import org.testng.asserts.SoftAssert;
import tv.pluto.core.BaseTest;
import tv.pluto.grpc.channels.ActiveContent;
import tv.pluto.grpc.channels.ChannelsClient;
import tv.pluto.grpc.utils.ProtoJsonUtil;
import tv.pluto.ip.dal.channels.Channels.Filter;
import tv.pluto.ip.dal.channels.Channels.SamsungChannelProperty;
import tv.pluto.mongo.dto.DocumentQuery;
import tv.pluto.mongo.entities.channels.Channels;
import tv.pluto.mongo.entities.channels.non_stitched_channels_with_multiple_scheduled_clips.CfaasIntegration;
import tv.pluto.mongo.entities.channels.non_stitched_channels_with_multiple_scheduled_clips.Channel;
import tv.pluto.mongo.entities.clips.Clips;
import tv.pluto.mongo.entities.common.EpisodesQueue;
import tv.pluto.mongo.entities.common.Window;
import tv.pluto.mongo.entities.devices.Devices;
import tv.pluto.mongo.entities.episodes.Episodes;
import tv.pluto.mongo.entities.episodes.Source;
import tv.pluto.mongo.entities.maincategories.MainCategories;
import tv.pluto.mongo.entities.samsungchannelproperties.SamsungChannelProperties;
import tv.pluto.mongo.entities.series.Series;
import tv.pluto.mongo.entities.timelines.Timelines;
import tv.pluto.mongo.entities.timelines.TimelinesForActiveContent;
import tv.pluto.mongo.entities.vod.VodCategories;
import tv.pluto.mongo.utils.ChannelsUtils;
import tv.pluto.mongo.utils.ClipsUtils;
import tv.pluto.mongo.utils.DevicesUtils;
import tv.pluto.mongo.utils.MainCategoriesUtils;
import tv.pluto.mongo.utils.MongoUtils;
import tv.pluto.mongo.utils.SamsungChannelPropertiesUtils;
import tv.pluto.mongo.utils.SeriesUtils;
import tv.pluto.mongo.utils.TimelinesUtils;
import tv.pluto.mongo.utils.VodCategoryUtils;
import tv.pluto.mongo.utils.episodes.EpisodeUtils;
import tv.pluto.utils.CommonUtils;

public class ChannelsTestSuite extends BaseTest {
  private ChannelsClient channelsClient;
  private ChannelsClient channelsClientAuth;
  private ChannelsUtils channelsUtils;
  private MainCategoriesUtils mainCategoriesUtils;
  private TimelinesUtils timelinesUtils;
  private ClipsUtils clipsUtils;
  private EpisodeUtils episodeUtils;
  private DevicesUtils devicesUtils;
  private SamsungChannelPropertiesUtils samsungChannelPropertiesUtils;
  private VodCategoryUtils vodCategoryUtils;
  private SeriesUtils seriesUtils;
  private static final int LIMIT_FIFTY = 50;
  private Channels regexChannel;
  private final String CHANNEL_NOT_FOUND = "NOT_FOUND: Channel document for requested ID not found";
  private static final List<String> LIST_RANDOM_INVALID_EPISODES =
      List.of(
          "55df880f07fc0e165cb86000",
          "55df880f07fc0e165cb00000",
          "55df880f07fc0e1651100000",
          "55df880f07fc0e165c100000");

  @BeforeClass(alwaysRun = true)
  private void setUp() {
    channelsClient = new ChannelsClient(grpcChannelManager.getChannel(), false);
    channelsClientAuth = new ChannelsClient(grpcChannelManager.getChannel(), true);
    channelsUtils = new ChannelsUtils();
    mainCategoriesUtils = new MainCategoriesUtils();
    timelinesUtils = new TimelinesUtils();
    clipsUtils = new ClipsUtils();
    episodeUtils = new EpisodeUtils();
    devicesUtils = new DevicesUtils();
    samsungChannelPropertiesUtils = new SamsungChannelPropertiesUtils();
    vodCategoryUtils = new VodCategoryUtils();
    seriesUtils = new SeriesUtils();
    regexChannel = channelsUtils.getDocumentWithoutSpecialCharactersInName();
  }

  @Test(priority = 1)
  @Description("GetDocumentsUpdatedBetweenDates - Time period for which there is a channel")
  @TmsLink("28500479")
  public void C28500479_TEST() {
    ChannelsUtils channelsUtils = new ChannelsUtils();

    List<Channels> mongoChannels =
        channelsUtils.getDocumentsForContentFeeds(
            channelsUtils.updatedAtMin, channelsUtils.updatedAtMax);
    List<Channels> grpcChannels = new ArrayList<>();

    Iterator<tv.pluto.ip.dal.channels.Channels.Channel> channels =
        new ChannelsClient(grpcChannelManager.getChannel(), false)
            .getDocumentsUpdatedBetweenDates(
                channelsUtils.updatedAtMinString, channelsUtils.updatedAtMaxString);

    while (channels.hasNext()) {
      grpcChannels.add(channelsUtils.mapGrpcObjectToPojo(channels.next(), Channels.class));
    }

    mongoChannels.sort(Comparator.comparing(Channels::getId));
    grpcChannels.sort(Comparator.comparing(Channels::getId));

    Assert.assertEquals(mongoChannels, grpcChannels);
  }

  @Test
  @Description("Valid request - GetStitchedActiveChannelIds")
  @TmsLink("28500452")
  public void C28500452_TEST() {
    String randomActiveRegionId = channelsUtils.getValidActiveRegion();
    List<String> grpcStitchedActiveChannelIds =
        new ArrayList<>(
            channelsClient.getStitchedActiveChannelIds(randomActiveRegionId).getIdsList());

    List<String> mongoStitchedActiveChannelIds =
        channelsUtils.getStitchedActiveChannelIds(randomActiveRegionId);
    Collections.sort(grpcStitchedActiveChannelIds);
    Collections.sort(mongoStitchedActiveChannelIds);
    Assert.assertEquals(grpcStitchedActiveChannelIds, mongoStitchedActiveChannelIds);
  }

  @Test(
      expectedExceptions = StatusRuntimeException.class,
      expectedExceptionsMessageRegExp = "NOT_FOUND: stitched active channels not found")
  @Description("Invalid request - GetStitchedActiveChannelIds ")
  @TmsLink("28500453")
  public void C28500453_TEST() {
    Assert.assertTrue(
        channelsClient
            .getStitchedActiveChannelIds(MongoUtils.INVALID_ID_VALUE)
            .getIdsList()
            .isEmpty());
  }

  @Test
  @Description("Valid request - GetChannelForActiveContent")
  @TmsLink("28500454")
  public void C28500454_TEST() {
    SoftAssert softAssertion = new SoftAssert();
    tv.pluto.mongo.entities.channels.Channels randomMongoChannel =
        channelsUtils.getRandomDocument();
    String randomChannelId = randomMongoChannel.getId();
    tv.pluto.ip.dal.channels.Channels.GetChannelForActiveContentResponse grpcChannel =
        channelsClient.getChannelForActiveContent(randomChannelId);
    tv.pluto.mongo.entities.channels.Channels mongoChannel =
        channelsUtils.getDocumentById(randomChannelId);
    softAssertion.assertEquals(grpcChannel.getId(), mongoChannel.getId());
    softAssertion.assertEquals(grpcChannel.getName(), mongoChannel.getName());
    softAssertion.assertEquals(grpcChannel.getCategory(), mongoChannel.getCategory());
    softAssertion.assertEquals(grpcChannel.getActiveRegion(), mongoChannel.getActiveRegion());
    softAssertion.assertTrue(grpcChannel.getIsStitched() == mongoChannel.getIsStitched());
    softAssertion.assertTrue(grpcChannel.getLiveBroadcast() == mongoChannel.getLiveBroadcast());
    softAssertion.assertAll();
  }

  @Test(
      expectedExceptions = StatusRuntimeException.class,
      expectedExceptionsMessageRegExp = "NOT_FOUND: channel for requested ID not found")
  @Description("Invalid request - GetChannelForActiveContent")
  @TmsLink("28500455")
  public void C28500455_TEST() {
    channelsClient.getChannelForActiveContent(MongoUtils.INVALID_ID_VALUE);
  }

  @Test
  @Description("Valid request - GetTimelinesForActiveContent")
  @TmsLink("28500456")
  public void C28500456_TEST() {
    ActiveContent activeContent = new ActiveContent();
    Timelines randomTimeline = timelinesUtils.getRandomDocument();
    activeContent.setChannelId(randomTimeline.getChannel());
    // Updating dates to increase range of search
    activeContent.setFrom(addYearsToDate(randomTimeline.getStop(), -10));
    activeContent.setTo(addYearsToDate(randomTimeline.getStart(), 10));
    // Sort by start field
    activeContent.setSort("start");
    activeContent.setLimit(MongoUtils.LIMIT);

    List<TimelinesForActiveContent> mappedTimelinesList =
        timelinesUtils.mapGrpcObjectsToPojo(
            channelsClient.getTimelinesForActiveContent(activeContent).getItemsList(),
            TimelinesForActiveContent.class);

    List<Timelines> mongoTimelinesList =
        timelinesUtils.getTimelinesForActiveContent(activeContent, null);

    List<TimelinesForActiveContent> mongoTimelinesForActiveContents =
        timelinesUtils.convertToTimelinesForActiveContent(mongoTimelinesList);

    Assert.assertFalse(mongoTimelinesForActiveContents.isEmpty());

    mongoTimelinesForActiveContents.sort(Comparator.comparing(TimelinesForActiveContent::getId));
    mappedTimelinesList.sort(Comparator.comparing(TimelinesForActiveContent::getId));

    Assert.assertEquals(mappedTimelinesList, mappedTimelinesList);
  }

  @Test(dataProvider = "start-stop-channel")
  @TmsLink("28500457")
  @Description("Valid request - GetTimelinesForActiveContent projection")
  public void C28500457_TEST(String projection) {
    List<String> listProjections = List.of(projection);
    ActiveContent activeContent = new ActiveContent();
    Timelines randomTimeline = timelinesUtils.getRandomDocument();
    activeContent.setChannelId(randomTimeline.getChannel());
    activeContent.setFrom(addYearsToDate(randomTimeline.getStop(), -10));
    activeContent.setTo(addYearsToDate(randomTimeline.getStart(), 10));
    activeContent.setSort("id");
    activeContent.setLimit(MongoUtils.LIMIT);
    activeContent.setProjection(listProjections);

    List<TimelinesForActiveContent> mappedTimelinesList =
        timelinesUtils.mapGrpcObjectsToPojo(
            channelsClient.getTimelinesForActiveContent(activeContent).getItemsList(),
            TimelinesForActiveContent.class);

    List<Timelines> mongoTimelinesList =
        timelinesUtils.getTimelinesForActiveContent(activeContent, listProjections);

    List<TimelinesForActiveContent> mongoTimelinesForActiveContents =
        timelinesUtils.convertToTimelinesForActiveContent(mongoTimelinesList);

    Assert.assertFalse(mongoTimelinesForActiveContents.isEmpty());

    mongoTimelinesForActiveContents.sort(Comparator.comparing(TimelinesForActiveContent::getId));
    mappedTimelinesList.sort(Comparator.comparing(TimelinesForActiveContent::getId));

    Assert.assertEquals(mappedTimelinesList, mappedTimelinesList);
  }

  @Test
  @Description("Invalid request - GetTimelinesForActiveContent")
  @TmsLink("28500458")
  public void C28500458_TEST() {
    ActiveContent activeContent = new ActiveContent();
    Timelines randomTimeline = timelinesUtils.getRandomDocument();
    activeContent.setChannelId(MongoUtils.INVALID_ID_VALUE);
    activeContent.setFrom(randomTimeline.getStop());
    activeContent.setTo(randomTimeline.getStart());
    Assert.assertTrue(
        channelsClient.getTimelinesForActiveContent(activeContent).getItemsList().isEmpty());
  }

  @Test
  @Description("Valid request - GetChannelById")
  @TmsLink("28500459")
  public void C28500459_TEST() {
    Channels mongoChannel = channelsUtils.getRandomDocument();
    String randomChannelId = mongoChannel.getId();

    Channels mappedChannel =
        channelsUtils.mapGrpcObjectToPojo(
            channelsClient.getChannelById(randomChannelId).getDocument(), Channels.class);

    Assert.assertEquals(mongoChannel, mappedChannel);
  }

  @Test
  @Description("Valid request - GetChannelById with projections")
  @TmsLink("28500460")
  public void C28500460_TEST() {
    String[] projection = {"_id", "name"};

    Channels mongoChannel = channelsUtils.getRandomDocument(projection);
    String randomChannelId = mongoChannel.getId();

    Channels mappedChannel =
        channelsUtils.mapGrpcObjectToPojo(
            channelsClient.getChannelById(randomChannelId, projection).getDocument(),
            Channels.class);

    Assert.assertEquals(mongoChannel, mappedChannel);
  }

  @Test(
      expectedExceptions = StatusRuntimeException.class,
      expectedExceptionsMessageRegExp = CHANNEL_NOT_FOUND)
  @Description("Invalid request - GetChannelById")
  @TmsLink("28500461")
  public void C28500461_TEST() {
    channelsClient.getChannelById(MongoUtils.INVALID_ID_VALUE);
  }

  @Test
  @Description("Valid request with single channel - GetChannelsByIds")
  @TmsLink("28500462")
  public void C28500462_TEST() {
    tv.pluto.mongo.entities.channels.Channels mongoChannel = channelsUtils.getRandomDocument();
    List<String> randomChannelsIds = Collections.singletonList(mongoChannel.getId());

    List<tv.pluto.mongo.entities.channels.Channels> mongoChannelsList =
        Collections.singletonList(mongoChannel);
    List<?> mappedChannelsList =
        channelsUtils.mapGrpcObjectsToPojo(
            channelsClient.getChannelsByIds(randomChannelsIds).getDocumentsList(),
            tv.pluto.mongo.entities.channels.Channels.class);

    Assert.assertEquals(mongoChannelsList, mappedChannelsList);
  }

  @Test
  @Description("Valid request with multiple channels - GetChannelsByIds")
  @TmsLink("28500463")
  public void C28500463_TEST() {
    List<String> randomChannelsIds = channelsUtils.getRandomChannelsIds();

    List<tv.pluto.mongo.entities.channels.Channels> mongoChannelsList =
        channelsUtils.getDocumentsByIds(randomChannelsIds);
    List<?> mappedChannelsList =
        channelsUtils.mapGrpcObjectsToPojo(
            channelsClient.getChannelsByIds(randomChannelsIds).getDocumentsList(),
            tv.pluto.mongo.entities.channels.Channels.class);

    Assert.assertEquals(mongoChannelsList, mappedChannelsList);
  }

  @Test(
      expectedExceptions = StatusRuntimeException.class,
      expectedExceptionsMessageRegExp = "NOT_FOUND: Channel documents for requested IDs not found")
  @Description("Invalid request with single channel - GetChannelsByIds")
  @TmsLink("28500464")
  public void C28500464_TEST() {
    List<String> invalidChannelsIds = Collections.singletonList(MongoUtils.INVALID_ID_VALUE);
    Assert.assertTrue(
        channelsClient.getChannelsByIds(invalidChannelsIds).getDocumentsList().isEmpty());
  }

  @Test
  @Description("Valid request with invalid channels - GetChannelsByIds")
  @TmsLink("28500465")
  public void C28500465_TEST() {
    List<String> randomChannelsIds = channelsUtils.getRandomChannelsIds();
    randomChannelsIds.add(MongoUtils.INVALID_ID_VALUE);

    List<tv.pluto.mongo.entities.channels.Channels> mongoChannelsList =
        channelsUtils.getDocumentsByIds(randomChannelsIds);
    List<?> mappedChannelsList =
        channelsUtils.mapGrpcObjectsToPojo(
            channelsClient.getChannelsByIds(randomChannelsIds).getDocumentsList(),
            tv.pluto.mongo.entities.channels.Channels.class);

    Assert.assertEquals(mongoChannelsList, mappedChannelsList);
  }

  @Test
  @Description("Valid request: GetNonStitchedChannelsWithMultipleScheduledClips")
  @TmsLink("28500625")
  public void C28500625_TEST() {
    List<Channel> mongoChannels = channelsUtils.getNonStitchedChannelsWithMultipleScheduledClips();

    // In case there are no non-stitched channels with more than one clip
    if (mongoChannels.isEmpty()) {
      try {
        channelsClient.getNonStitchedChannelsWithMultipleScheduledClips();
      } catch (StatusRuntimeException ex) {
        Assert.assertEquals(
            ex.getMessage(),
            "NOT_FOUND: No non-stitched channels with more than one clip scheduled.");
      }
    } else {
      List<Channel> grpcChannels =
          channelsUtils.mapGrpcObjectsToPojo(
              channelsClient.getNonStitchedChannelsWithMultipleScheduledClips().getChannelsList(),
              Channel.class);
      Assert.assertEquals(mongoChannels, grpcChannels);
    }
  }

  @Test(
      expectedExceptions = StatusRuntimeException.class,
      expectedExceptionsMessageRegExp = NOT_FOUND_MESSAGE)
  @Description("GetDocumentsUpdatedBetweenDates - Time period without channel")
  @TmsLink("28500480")
  public void C28500480_TEST() {
    new ChannelsClient(grpcChannelManager.getChannel(), false)
        .getDocumentsUpdatedBetweenDates(failStartDateTime, failEndDateTime)
        .next();
  }

  @Test(
      dataProvider = "fail-content-feeds-test-data",
      expectedExceptions = StatusRuntimeException.class,
      expectedExceptionsMessageRegExp = INVALID_ARGUMENT_MESSAGE)
  @Description(
      "GetDocumentsUpdatedBetweenDates - Invalid values for start_date_time and end_date_time")
  @TmsLink("28500481")
  public void C28500481_TEST(String startDateTime, String endDateTime) {
    new ChannelsClient(grpcChannelManager.getChannel(), false)
        .getDocumentsUpdatedBetweenDates(startDateTime, endDateTime)
        .next();
  }

  @Test(
      dataProvider = "less-or-equal-fail-content-feeds-test-data",
      expectedExceptions = StatusRuntimeException.class,
      expectedExceptionsMessageRegExp = INTERNAL_ERROR_MESSAGE)
  @TmsLink("28500482")
  @Description(
      "GetDocumentsUpdatedBetweenDates - end_date_time is less than or equal to start_date_time")
  public void C28500482_TEST(String startDateTime, String endDateTime) {
    new ChannelsClient(grpcChannelManager.getChannel(), false)
        .getDocumentsUpdatedBetweenDates(startDateTime, endDateTime)
        .next();
  }

  @Test
  @Description(
      "GetAllPaged - get documents with limit and offset, sorting ascending by single field")
  @TmsLink("28500491")
  public void C28500491_TEST() {
    ChannelsClient channelsClient = new ChannelsClient(grpcChannelManager.getChannel(), false);
    Bson sort = orderBy(ascending("_id"));
    List<Channels> mongoChannels = channelsUtils.getDocuments(20, 10, sort);

    List<GetAllPagedSort> grpcSort = channelsClient.singleListSortObject("_id", 1);

    GetAllPagedResponse response = channelsClient.getAllPaged(20, 10, grpcSort, null, null);

    List<Channels> grpcChannels =
        channelsUtils.mapGrpcObjectsToPojo(response.getDocumentsList(), Channels.class);

    mongoChannels.sort(Comparator.comparing(Channels::getId));
    grpcChannels.sort(Comparator.comparing(Channels::getId));

    mongoChannels.forEach(chan -> chan.setMainCategories(null));
    grpcChannels.forEach(chan -> chan.setMainCategories(null));

    Assert.assertEquals(mongoChannels, grpcChannels);
  }

  @Test
  @Description(
      "GetAllPaged - get documents with limit and offset, sorting ascending by multiple fields")
  @TmsLink("28500492")
  public void C28500492_TEST() {
    ChannelsClient channelsClient = new ChannelsClient(grpcChannelManager.getChannel(), false);
    Bson sort = orderBy(ascending("_id"), ascending("name"));
    List<Channels> mongoChannels = channelsUtils.getDocuments(20, 10, sort);

    List<GetAllPagedSort> grpcSort =
        Arrays.asList(channelsClient.sortObject("_id", 1), channelsClient.sortObject("name", 1));

    GetAllPagedResponse response =
        new ChannelsClient(grpcChannelManager.getChannel(), false)
            .getAllPaged(20, 10, grpcSort, null, null);

    List<Channels> grpcChannels =
        channelsUtils.mapGrpcObjectsToPojo(response.getDocumentsList(), Channels.class);

    mongoChannels.forEach(chan -> chan.setMainCategories(null));
    grpcChannels.forEach(chan -> chan.setMainCategories(null));

    mongoChannels.sort(Comparator.comparing(Channels::getId));
    grpcChannels.sort(Comparator.comparing(Channels::getId));

    Assert.assertEquals(mongoChannels, grpcChannels);
  }

  @Test(dataProvider = "sort-values")
  @TmsLink("28500545")
  @Description("GetAllPaged - sort by name")
  public void C28500545_TEST(int sortValue) {
    int limit = 500;
    ChannelsClient channelsClient = new ChannelsClient(grpcChannelManager.getChannel(), false);
    Bson sort;

    if (sortValue == 1) sort = orderBy(ascending("name"));
    else sort = orderBy(descending("name"));

    List<Channels> mongoChannels = channelsUtils.getChannelsWithCollation(limit, 0, sort, true);

    List<GetAllPagedSort> grpcSort = channelsClient.singleListSortObject("name", sortValue);

    GetAllPagedResponse response =
        new ChannelsClient(grpcChannelManager.getChannel(), false)
            .getAllPaged(limit, 0, grpcSort, null, null);

    List<Channels> grpcChannels =
        channelsUtils.mapGrpcObjectsToPojo(response.getDocumentsList(), Channels.class);

    List<String> mongoNames =
        mongoChannels.stream().map(Channels::getName).collect(Collectors.toList());
    List<String> grpcNames =
        grpcChannels.stream().map(Channels::getName).collect(Collectors.toList());

    Assert.assertEquals(mongoNames, grpcNames);
  }

  @Test
  @Description("GetAllPagedResponse - has a new object Metadata")
  @TmsLink("28500515")
  public void C28500515_TEST() {
    ChannelsClient channelsClient = new ChannelsClient(grpcChannelManager.getChannel(), false);
    int total = 5;
    int offset = new Random().nextInt(total);

    GetAllPagedResponse responseAllPagedTest =
        channelsClient.getAllPaged(total + 1, offset, null, null, true);
    Assert.assertEquals(responseAllPagedTest.getDocumentsList().size(), total + 1);

    for (int i = total; i > 1; i--) {
      GetAllPagedResponse responseAllPaged =
          channelsClient.getAllPaged(i, offset, null, null, true);
      Assert.assertEquals(offset, responseAllPaged.getMetadata().getCurrentOffset());
      Assert.assertEquals(i, responseAllPaged.getMetadata().getTotalItems());
    }
  }

  @Test
  @Description(
      "GetAllPaged - get documents with limit and offset, sorting descending by single field")
  @TmsLink("28500493")
  public void C28500493_TEST() {
    ChannelsClient channelsClient = new ChannelsClient(grpcChannelManager.getChannel(), false);
    Bson sort = orderBy(descending("_id"));
    List<Channels> mongoChannels = channelsUtils.getDocuments(20, 10, sort);

    List<GetAllPagedSort> grpcSort = channelsClient.singleListSortObject("_id", -1);

    GetAllPagedResponse response = channelsClient.getAllPaged(20, 10, grpcSort, null, null);

    List<Channels> grpcChannels =
        channelsUtils.mapGrpcObjectsToPojo(response.getDocumentsList(), Channels.class);

    mongoChannels.forEach(chan -> chan.setMainCategories(null));
    grpcChannels.forEach(chan -> chan.setMainCategories(null));

    mongoChannels.sort(Comparator.comparing(Channels::getId));
    grpcChannels.sort(Comparator.comparing(Channels::getId));

    Assert.assertEquals(mongoChannels, grpcChannels);
  }

  @Test
  @Description(
      "GetAllPaged - get documents with limit and offset, sorting descending by multiple fields")
  @TmsLink("28500494")
  public void C28500494_TEST() {
    ChannelsClient channelsClient = new ChannelsClient(grpcChannelManager.getChannel(), false);
    Bson sort = orderBy(descending("_id"), descending("name"));
    List<Channels> mongoChannels = channelsUtils.getDocuments(20, 10, sort);

    List<GetAllPagedSort> grpcSort =
        Arrays.asList(channelsClient.sortObject("_id", -1), channelsClient.sortObject("name", -1));

    GetAllPagedResponse response = channelsClient.getAllPaged(20, 10, grpcSort, null, null);

    try {
      List<tv.pluto.ip.dal.channels.Channels.Channel> list = response.getDocumentsList();
      LogUtils.logInfoMessage("List size: " + list.size());
    } catch (NullPointerException e) {
      LogUtils.logInfoMessage("Response: " + response);
    }

    List<Channels> grpcChannels =
        channelsUtils.mapGrpcObjectsToPojo(response.getDocumentsList(), Channels.class);

    mongoChannels.forEach(chan -> chan.setMainCategories(null));
    grpcChannels.forEach(chan -> chan.setMainCategories(null));

    mongoChannels.sort(Comparator.comparing(Channels::getId));
    grpcChannels.sort(Comparator.comparing(Channels::getId));

    Assert.assertEquals(mongoChannels, grpcChannels);
  }

  @Test
  @Description("GetAllPaged - get documents with default values")
  @TmsLink("28500495")
  public void C28500495_TEST() {
    // TODO investigate client issue
    ChannelsClient newClient = new ChannelsClient(grpcChannelManager.getChannel(), false);
    GetAllPagedResponse response = newClient.getAllPaged(null, null, null, null, null);

    Assert.assertEquals(response.getDocumentsList().size(), DEFAULT_LIMIT); // Default value
  }

  @Test
  @Description("GetAllPaged - filter valid values")
  @TmsLink("28500496")
  public void C28500496_TEST()
      throws NoSuchFieldException, InvocationTargetException, IllegalAccessException {
    ChannelsClient channelsClient = new ChannelsClient(grpcChannelManager.getChannel(), false);
    List<Channels> listChannels = channelsUtils.getFilteredRandomChannelsId(1);
    Channels channel = listChannels.get(new Random().nextInt(listChannels.size()));

    LogUtils.logInfoMessage("GetAllPaged. MongoDB channel id: " + channel.getId());

    List<tv.pluto.ip.dal.channels.Channels.Filter> listFiltersBodyInChannels =
        channelsClient.filtersBodyInChannels(channel);

    List<GetAllPagedSort> listSortObjects = channelsClient.singleListSortObject("name", 1);
    GetAllPagedResponse getAllPagedClientResponse =
        channelsClient.getAllPagedException(1, 0, listSortObjects, listFiltersBodyInChannels, true);
    Channels mongoDBChannel = channelsUtils.getDocumentById(channel.getId());

    Channels clientChannel =
        channelsUtils.mapGrpcObjectToPojo(
            getAllPagedClientResponse.getDocuments(0),
            tv.pluto.mongo.entities.channels.Channels.class);

    Channels mongoDbUpdated =
        channelsWithMainCategory(mongoDBChannel, clientChannel.getMainCategories());
    Assert.assertEquals(mongoDbUpdated, clientChannel);
  }

  @Test
  @Description("GetAllPaged - filter kidsMode/number limit 50")
  @TmsLink("28500501")
  public void C28500501_TEST() {
    ChannelsClient channelsClient = new ChannelsClient(grpcChannelManager.getChannel(), false);
    Channels channel = channelsUtils.getRandomDocument();
    LogUtils.logInfoMessage("Random channelId: " + channel.getId());

    tv.pluto.ip.dal.channels.Channels.Filter kidsFilter =
        channelsClient.channelFilterBody("kidsMode", channel.getKidsMode().toString(), "boolean");
    tv.pluto.ip.dal.channels.Channels.Filter numberFilter =
        channelsClient.channelFilterBody("number", channel.getNumber().toString(), "number");
    List<tv.pluto.ip.dal.channels.Channels.Filter> listFiltersBodyInChannels =
        channelsClient.listFiltersBodyInChannels(kidsFilter, numberFilter);
    List<GetAllPagedSort> listSortObjects = channelsClient.singleListSortObject("name", 1);

    GetAllPagedResponse getAllPagedClientResponse =
        channelsClient.getAllPaged(
            LIMIT_FIFTY, 0, listSortObjects, listFiltersBodyInChannels, true);
    getAllPagedClientResponse
        .getDocumentsList()
        .forEach(chan -> Assert.assertEquals(channel.getNumber().intValue(), chan.getNumber()));
    getAllPagedClientResponse
        .getDocumentsList()
        .forEach(
            chan -> Assert.assertEquals(chan.getKidsMode(), channel.getKidsMode().booleanValue()));

    BasicDBObject basicDBObject = channelsUtils.kidsModeObject(channel);
    basicDBObject.put("number", channel.getNumber());

    int channelSize = channelsUtils.getListChannels(basicDBObject).size();
    int channelsGRPCSize = getAllPagedClientResponse.getDocumentsList().size();

    if (channelSize > LIMIT_FIFTY) Assert.assertEquals(LIMIT_FIFTY, channelsGRPCSize);
    else Assert.assertEquals(channelsGRPCSize, channelSize);
  }

  @Test
  @Description("GetAllPaged - filter kidsMode/plutoOfficeOnly limit 50")
  @TmsLink("28500503")
  public void C28500503_TEST() {
    ChannelsClient channelsClient = new ChannelsClient(grpcChannelManager.getChannel(), false);
    Channels channel = channelsUtils.getRandomDocument();
    LogUtils.logInfoMessage("C8992482_TEST. Random channelId: " + channel.getId());

    tv.pluto.ip.dal.channels.Channels.Filter kidsFilter =
        channelsClient.channelFilterBody("kidsMode", channel.getKidsMode().toString(), "boolean");
    tv.pluto.ip.dal.channels.Channels.Filter numberFilter =
        channelsClient.channelFilterBody(
            "plutoOfficeOnly", channel.getPlutoOfficeOnly().toString(), "boolean");
    List<tv.pluto.ip.dal.channels.Channels.Filter> listFiltersBodyInChannels =
        channelsClient.listFiltersBodyInChannels(kidsFilter, numberFilter);
    List<GetAllPagedSort> listSortObjects = channelsClient.singleListSortObject("name", 1);

    GetAllPagedResponse getAllPagedClientResponse =
        channelsClient.getAllPaged(
            LIMIT_FIFTY, 0, listSortObjects, listFiltersBodyInChannels, true);
    getAllPagedClientResponse
        .getDocumentsList()
        .forEach(
            chan ->
                Assert.assertEquals(
                    chan.getPlutoOfficeOnly(), channel.getPlutoOfficeOnly().booleanValue()));
    getAllPagedClientResponse
        .getDocumentsList()
        .forEach(
            chan -> Assert.assertEquals(chan.getKidsMode(), channel.getKidsMode().booleanValue()));

    BasicDBObject basicDBObject = channelsUtils.kidsModeObject(channel);
    basicDBObject.put("plutoOfficeOnly", channel.getPlutoOfficeOnly());

    int channelsGRPCSize = getAllPagedClientResponse.getDocumentsList().size();
    int channelSize = channelsUtils.getListChannels(basicDBObject).size();

    if (channelSize > LIMIT_FIFTY) Assert.assertEquals(LIMIT_FIFTY, channelsGRPCSize);
    else Assert.assertEquals(channelsGRPCSize, channelSize);
  }

  @Test
  @Description("GetAllPaged - filter kidsMode/activeRegion limit 50")
  @TmsLink("28500504")
  public void C28500504_TEST() {
    ChannelsClient channelsClient = new ChannelsClient(grpcChannelManager.getChannel(), false);
    Channels channel = channelsUtils.getRandomDocument();
    LogUtils.logInfoMessage("C8992483_TEST. Random channelId: " + channel.getId());

    tv.pluto.ip.dal.channels.Channels.Filter kidsFilter =
        channelsClient.channelFilterBody("kidsMode", channel.getKidsMode().toString(), "boolean");
    tv.pluto.ip.dal.channels.Channels.Filter numberFilter =
        channelsClient.channelFilterBody("activeRegion", channel.getActiveRegion(), "string");
    List<tv.pluto.ip.dal.channels.Channels.Filter> listFiltersBodyInChannels =
        channelsClient.listFiltersBodyInChannels(kidsFilter, numberFilter);
    List<GetAllPagedSort> listSortObjects = channelsClient.singleListSortObject("name", 1);

    GetAllPagedResponse getAllPagedClientResponse =
        channelsClient.getAllPaged(
            LIMIT_FIFTY, 0, listSortObjects, listFiltersBodyInChannels, true);
    getAllPagedClientResponse
        .getDocumentsList()
        .forEach(chan -> Assert.assertEquals(chan.getActiveRegion(), channel.getActiveRegion()));
    getAllPagedClientResponse
        .getDocumentsList()
        .forEach(
            chan -> Assert.assertEquals(chan.getKidsMode(), channel.getKidsMode().booleanValue()));

    BasicDBObject basicDBObject = channelsUtils.kidsModeObject(channel);
    basicDBObject.put("activeRegion", channel.getActiveRegion());

    int channelsGRPCSize = getAllPagedClientResponse.getDocumentsList().size();
    int channelSize = channelsUtils.getListChannels(basicDBObject).size();

    if (channelSize > LIMIT_FIFTY) Assert.assertEquals(channelsGRPCSize, LIMIT_FIFTY);
    else Assert.assertEquals(channelsGRPCSize, channelSize);
  }

  @Test(
      expectedExceptions = StatusRuntimeException.class,
      expectedExceptionsMessageRegExp = "NOT_FOUND: Channel documents not found")
  @TmsLink("28500497")
  @Description("GetAllPaged - filter by invalid channel name")
  public void C28500497_TEST()
      throws NoSuchFieldException, InvocationTargetException, IllegalAccessException {
    ChannelsClient channelsClient = new ChannelsClient(grpcChannelManager.getChannel(), false);
    Channels channel = channelsUtils.getRandomDocument();
    channel.setName("invalidTestName");

    List<GetAllPagedSort> listSortObjects = channelsClient.singleListSortObject("name", 1);
    List<tv.pluto.ip.dal.channels.Channels.Filter> listFiltersBodyInChannels =
        channelsClient.filtersBodyInChannels(channel);

    channelsClient.getAllPagedException(1, 0, listSortObjects, listFiltersBodyInChannels, true);
  }

  @Test(
      expectedExceptions = StatusRuntimeException.class,
      expectedExceptionsMessageRegExp = "NOT_FOUND: Channel documents not found")
  @TmsLink("28500498")
  @Description("GetAllPaged - filter by invalid active region")
  public void C28500498_TEST()
      throws NoSuchFieldException, InvocationTargetException, IllegalAccessException {
    ChannelsClient channelsClient = new ChannelsClient(grpcChannelManager.getChannel(), false);
    Channels channel = channelsUtils.getRandomDocument();
    channel.setActiveRegion("invalidRegion");

    List<GetAllPagedSort> listSortObjects = channelsClient.singleListSortObject("author", 1);
    List<tv.pluto.ip.dal.channels.Channels.Filter> listFiltersBodyInChannels =
        channelsClient.filtersBodyInChannels(channel);

    channelsClient.getAllPagedException(1, 0, listSortObjects, listFiltersBodyInChannels, false);
  }

  @Test
  @Description("GetAll Channels - has only active region")
  @TmsLink("28500499")
  public void C28500499_TEST() {
    int limit = 15;
    String activeRegionFromEpisodes = episodeUtils.getSetActiveRegionFromEpisodes().get(0);
    Iterator<tv.pluto.ip.dal.channels.Channels.Channel> getAllResponse =
        new ChannelsClient(grpcChannelManager.getChannel(), false)
            .getAllResponse(activeRegionFromEpisodes);
    List<tv.pluto.ip.dal.channels.Channels.Channel> listChannelsGRPC =
        new ChannelsClient(grpcChannelManager.getChannel(), false)
            .listFromIteratorLimit(getAllResponse, limit);
    Assert.assertEquals(limit, listChannelsGRPC.size());

    List<Channels> listChannels = new ArrayList<>();
    List<Channels> listMongoChannels = new ArrayList<>();

    listChannelsGRPC.forEach(
        episode -> {
          Channels channelGrpc = episodeUtils.mapGrpcObjectToPojo(episode, Channels.class);
          listChannels.add(channelGrpc);

          Channels mongoDBChannel = channelsUtils.getDocumentById(channelGrpc.getId());
          listMongoChannels.add(mongoDBChannel);
          Assert.assertEquals(
              activeRegionFromEpisodes,
              mongoDBChannel.getActiveRegion(),
              "Channel's active region in MongoDB and gRPC are not equal");
        });

    listChannels.sort(Comparator.comparing(Channels::getId));
    listMongoChannels.sort(Comparator.comparing(Channels::getId));

    Assert.assertEquals(
        listChannels, listMongoChannels, "List Channels from gRPC and Mongo DB are not equal");
  }

  @Test(
      expectedExceptions = StatusRuntimeException.class,
      expectedExceptionsMessageRegExp = "NOT_FOUND: Not found")
  @Description("GetAll Channels - for the incorrect active region")
  @TmsLink("28500500")
  public void C28500500_TEST() {
    channelsClient.getAllResponse("randomData").next();
  }

  @Test
  @Description("cFeedsSyncAllIds - returns all ids")
  @TmsLink("28500505")
  public void C28500505_TEST() {
    List<String> channelsIdsFromCFeeds =
        channelsClient.channelsIdsFromCFeeds().stream()
            .map(tv.pluto.ip.dal.channels.Channels.Id::getId)
            .collect(Collectors.toList());

    List<String> mongoIdsFromCFeeds =
        channelsUtils.getDocumentsByIds(channelsIdsFromCFeeds).stream()
            .map(chan -> ((Channels) chan).getId())
            .collect(Collectors.toList());

    Assert.assertTrue(CommonUtils.isTwoListsEqual(channelsIdsFromCFeeds, mongoIdsFromCFeeds));
  }

  @Test
  @Description("cFeedsSyncDocuments - returns all channels")
  @TmsLink("28500675")
  public void C28500675_TEST() {
    Channels channels =
        channelsUtils.getDocuments(1_000).stream()
            .map(chan -> (Channels) chan)
            .filter(Channels::getPublished)
            .findFirst()
            .get();
    LogUtils.logInfoMessage(
        "Test start date:" + channels.getUpdatedAtString() + ", isPublished: " + true);

    List<Channels> mongoCollection =
        channelsUtils.getDocumentsForFeedsSync(channels.getUpdatedAt(), true).stream()
            .filter(Channels::getPublished)
            .collect(Collectors.toList());

    List<tv.pluto.ip.dal.channels.Channels.Channel> grpcList =
        channelsClient.getCFeedsSyncDocumentsList(channels.getUpdatedAtString(), true);
    List<Channels> grpcChannelsList = channelsUtils.mapGrpcObjectsToPojo(grpcList, Channels.class);
    LogUtils.logInfoMessage("grpcChannelsList size: " + grpcChannelsList.size());
    LogUtils.logInfoMessage("mongoCollection size: " + mongoCollection.size());

    mongoCollection.sort(Comparator.comparing(Channels::getId));
    grpcChannelsList.sort(Comparator.comparing(Channels::getId));

    Assert.assertEquals(grpcChannelsList, mongoCollection);
  }

  @Test(
      dataProvider = "is-true-false",
      expectedExceptions = StatusRuntimeException.class,
      expectedExceptionsMessageRegExp = NOT_FOUND_MESSAGE)
  @TmsLink("28500507")
  @Description("cFeedsSyncDocuments - does not return any channels for the future time")
  public void C28500507_TEST(boolean isPublished) {
    String time = CommonUtils.localDateTimeStringPlusDays(1);
    channelsClient.getCFeedsSyncDocumentsList(time, isPublished).get(0);
  }

  @Test
  @Description("UpdateFields - update fields in channels")
  @TmsLink("28500508")
  public void C28500508_TEST() {
    List<String> listChannels =
        List.of(
            "54bdb8678ba729396b1637d2",
            "51c75f7bb6f26ba1cd00000d",
            "51c75f7bb6f26ba1cd000009",
            "51f2f75e16a2a2f72d0003da");
    String testChannel = CommonUtils.getRandomValueFromList(listChannels);
    LogUtils.logInfoMessage("testChannel: " + testChannel);

    Channels channel = channelsUtils.getDocumentById(testChannel);
    String updatedName = CommonUtils.slightlyModifyString(channel.getName()).toLowerCase();
    LogUtils.logInfoMessage("Random channelId: " + channel.getId());

    tv.pluto.ip.dal.channels.Channels.Channel channelsList =
        newBuilder()
            .setId(channel.getId())
            .setName(updatedName)
            .setArchived(!channel.getArchived())
            .build();

    List<String> listFields = List.of("name", "archived");

    UpdateFieldsResponse getUpdateFieldsGrpcResponse =
        channelsClient.getUpdateFieldsResponse(channel.getId(), channelsList, listFields);

    Channels channelsGrpcResponse =
        channelsUtils.mapGrpcObjectToPojo(
            getUpdateFieldsGrpcResponse.getDocument(), Channels.class);
    Channels channelsMangoDB = channelsUtils.getDocumentById(channel.getId());

    SoftAssertions softAssert = new SoftAssertions();
    softAssert.assertThat(updatedName).isEqualTo(channelsGrpcResponse.getName());
    softAssert.assertThat(!channel.getArchived()).isEqualTo(channelsGrpcResponse.getArchived());
    softAssert.assertThat(channelsMangoDB).isEqualTo(channelsGrpcResponse);
    softAssert.assertAll();

    tv.pluto.ip.dal.channels.Channels.Channel revertedChannelsList =
        newBuilder()
            .setId(channel.getId())
            .setName(channel.getName())
            .setArchived(channel.getArchived())
            .build();

    UpdateFieldsResponse revertedUpdateFieldsGrpcResponse =
        channelsClient.getUpdateFieldsResponse(channel.getId(), revertedChannelsList, listFields);
    Assert.assertEquals(
        channel.getArchived().booleanValue(),
        revertedUpdateFieldsGrpcResponse.getDocument().getArchived());
  }

  @Test(
      expectedExceptions = StatusRuntimeException.class,
      expectedExceptionsMessageRegExp = CHANNEL_NOT_FOUND)
  @Description("UpdateFields - error messages")
  @TmsLink("28500509")
  public void C28500509_TEST() {
    String invalidChannelId = "999997df3b19999999999999";
    List<String> listFields = List.of("name");

    tv.pluto.ip.dal.channels.Channels.Channel channelsList =
        newBuilder().setId(invalidChannelId).setName("test").build();

    UpdateFieldsResponse getUpdateFieldsGrpcResponse =
        channelsClient.getUpdateFieldsResponse(invalidChannelId, channelsList, listFields);

    channelsUtils.mapGrpcObjectToPojo(getUpdateFieldsGrpcResponse.getDocument(), Channels.class);
  }

  @Test
  @Description("GeById - verify the channels object has __v field")
  @TmsLink("28500510")
  public void C28500510_TEST() {
    Channels channelsMango = channelsUtils.getRandomDocumentWithTheField("__v", true);
    LogUtils.logInfoMessage("ChannelId: " + channelsMango.getId());
    tv.pluto.ip.dal.channels.Channels.Channel channelsGrpc =
        channelsClient.getChannelById(channelsMango.getId()).getDocument();
    Channels channelGrpc = channelsUtils.mapGrpcObjectToPojo(channelsGrpc, Channels.class);
    Assert.assertNotNull(channelsMango.getV());
    Assert.assertEquals(channelGrpc, channelsMango);
  }

  @Test
  @Description("GeById - verify the channels object has the DASHReadyDRM field")
  @TmsLink("28500511")
  public void C28500511_TEST() {
    boolean isDashDrm = true;
    Channels channelsMango = channelsUtils.getDocumentByKeyValue("_isDASHReadyDRM", true);

    if (channelsMango == null) {
      channelsMango = channelsUtils.getRandomDocument();
      isDashDrm = false;
    }

    LogUtils.logInfoMessage(
        "ChannelId: " + channelsMango.getId() + ", _isDASHReadyDRM: " + isDashDrm);
    tv.pluto.ip.dal.channels.Channels.Channel channelsGrpc =
        channelsClient.getChannelById(channelsMango.getId()).getDocument();

    // To Do - compare 2 objects. Find a solution for _isDASHReadyDRM from grpc
    Assert.assertNotNull(channelsMango.getIsDASHReadyDRM());
    Assert.assertEquals(isDashDrm, channelsGrpc.getIsDASHReadyDRM());
  }

  @Test
  @Description("GeById - verify the channels object has chat_room_id field")
  @TmsLink("28500512")
  public void C28500512_TEST() {
    Channels channelsMango = channelsUtils.getRandomDocumentWithTheField("chatRoomId", true);
    LogUtils.logInfoMessage("ChannelId: " + channelsMango.getId());
    tv.pluto.ip.dal.channels.Channels.Channel channelsGrpc =
        channelsClient.getChannelById(channelsMango.getId()).getDocument();
    Channels channelGrpc = channelsUtils.mapGrpcObjectToPojo(channelsGrpc, Channels.class);
    Assert.assertNotNull(channelsMango.getChatRoomId());
    Assert.assertEquals(channelGrpc, channelsMango);
  }

  @Test
  @Description("GeById - verify the channels object has chatEnabled field")
  @TmsLink("28500513")
  public void C28500513_TEST() {
    Channels channelsMango = channelsUtils.getRandomDocumentWithTheField("chatEnabled", true);
    LogUtils.logInfoMessage("ChannelId: " + channelsMango.getId());
    tv.pluto.ip.dal.channels.Channels.Channel channelsGrpc =
        channelsClient.getChannelById(channelsMango.getId()).getDocument();
    Channels channelGrpc = channelsUtils.mapGrpcObjectToPojo(channelsGrpc, Channels.class);
    Assert.assertNotNull(channelsMango.getChatEnabled());
    Assert.assertEquals(channelGrpc, channelsMango);
  }

  @Test
  @Description("GeById - verify the channels object has gracenoteIntegration object")
  @TmsLink("28500514")
  public void C28500514_TEST() {
    Channels channelsMango =
        channelsUtils.getRandomDocumentWithTheField("gracenoteIntegration", true);
    LogUtils.logInfoMessage("ChannelId: " + channelsMango.getId());
    tv.pluto.ip.dal.channels.Channels.Channel channelsGrpc =
        channelsClient.getChannelById(channelsMango.getId()).getDocument();
    Channels channelGrpc = channelsUtils.mapGrpcObjectToPojo(channelsGrpc, Channels.class);
    Assert.assertNotNull(channelsMango.getGracenoteIntegration());
    Assert.assertEquals(channelGrpc, channelsMango);
  }

  @Test
  @Description("GetAllPagedResponse - has a new object Metadata disable_total_count: false")
  @TmsLink("28501217")
  public void C28501217_TEST() {
    int limit = 10;
    int offset = 1;
    ChannelsClient channelsClient = new ChannelsClient(grpcChannelManager.getChannel(), false);

    tv.pluto.ip.dal.channels.Channels.GetAllPagedResponse response =
        channelsClient.getAllPaged(limit, offset, null, null, false);
    long countTotalEpisodes = channelsUtils.getDocumentsCountsInTheCollection();

    Assert.assertTrue(countTotalEpisodes > 0);
    Assert.assertEquals(response.getMetadata().getTotalItems(), countTotalEpisodes);
    Assert.assertEquals(response.getMetadata().getCurrentOffset(), offset);
    Assert.assertEquals(response.getDocumentsList().size(), limit);
  }

  @Test
  @Description("GetById - verify a googleDai field")
  @TmsLink("28500516")
  public void C28500516_TEST() {
    Channels channelsMango = channelsUtils.getRandomDocumentWithTheField("googleDai", true);
    tv.pluto.ip.dal.channels.Channels.Channel grpcChannel =
        channelsClient.getChannelById(channelsMango.getId()).getDocument();
    Channels grpcChannels = channelsUtils.mapGrpcObjectToPojo(grpcChannel, Channels.class);

    Assert.assertNotNull(grpcChannels.getGoogleDai());
    Assert.assertEquals(channelsMango, grpcChannels);
  }

  @SuppressWarnings("SizeGreaterThanOrEqualsZero")
  @Test
  @Description("GetById - verify a SamsungChannelProperties field")
  @TmsLink("28500517")
  public void C28500517_TEST() {
    Channels channelsMango = channelsUtils.getRandomDocument();
    tv.pluto.ip.dal.channels.Channels.Channel grpcChannel =
        channelsClient.getChannelById(channelsMango.getId()).getDocument();
    Assert.assertTrue(grpcChannel.getSamsungChannelPropertiesCount() >= 0);
  }

  @SuppressWarnings("SizeGreaterThanOrEqualsZero")
  @Test
  @Description("GetByIds - verify a samsung_channel_properties field")
  @TmsLink("28500518")
  public void C28500518_TEST() {
    List<String> randomChannelsIds = channelsUtils.getRandomChannelsIds();
    List<tv.pluto.ip.dal.channels.Channels.Channel> grpcListChannel =
        channelsClient.getChannelsByIds(randomChannelsIds).getDocumentsList();
    grpcListChannel.forEach(
        channel -> Assert.assertTrue(channel.getSamsungChannelPropertiesCount() >= 0));
  }

  @SuppressWarnings("SizeGreaterThanOrEqualsZero")
  @Test
  @Description("GetAllPagedResponse - verify a samsung_channel_properties field")
  @TmsLink("28500519")
  public void C28500519_TEST() {
    ChannelsClient channelsClient = new ChannelsClient(grpcChannelManager.getChannel(), false);
    tv.pluto.ip.dal.channels.Channels.GetAllPagedResponse grpcChannel =
        channelsClient.getAllPaged(10, 1, null, null, false);
    List<tv.pluto.ip.dal.channels.Channels.Channel> grpcListChannel =
        grpcChannel.getDocumentsList();
    grpcListChannel.forEach(
        channel -> Assert.assertTrue(channel.getSamsungChannelPropertiesCount() >= 0));
  }

  @Test
  @Description("GetById - verify a thumbnailAlt field")
  @TmsLink("28500551")
  public void C28500551_TEST() {
    Channels channelsMango = channelsUtils.getRandomDocumentWithTheField("thumbnailAlt", true);
    tv.pluto.ip.dal.channels.Channels.Channel grpcChannel =
        channelsClient.getChannelById(channelsMango.getId()).getDocument();
    Channels grpcChannels = channelsUtils.mapGrpcObjectToPojo(grpcChannel, Channels.class);

    Assert.assertNotNull(grpcChannels.getThumbnailAlt());
    Assert.assertEquals(grpcChannels.getThumbnailAlt(), channelsMango.getThumbnailAlt());
    Assert.assertEquals(channelsMango, grpcChannels);
  }

  @Test
  @Description("GetById - verify a featuredImageAlt field")
  @TmsLink("28500552")
  public void C28500552_TEST() {
    Channels channelsMango = channelsUtils.getRandomDocumentWithTheField("featuredImageAlt", true);
    tv.pluto.ip.dal.channels.Channels.Channel grpcChannel =
        channelsClient.getChannelById(channelsMango.getId()).getDocument();
    Channels grpcChannels = channelsUtils.mapGrpcObjectToPojo(grpcChannel, Channels.class);

    Assert.assertNotNull(grpcChannels.getFeaturedImageAlt());
    Assert.assertEquals(grpcChannels.getFeaturedImageAlt(), channelsMango.getFeaturedImageAlt());
    Assert.assertEquals(channelsMango, grpcChannels);
  }

  @Test
  @Description("GetById - verify a logoAlt field")
  @TmsLink("28500553")
  public void C28500553_TEST() {
    Channels channelsMango = channelsUtils.getRandomDocumentWithTheField("logoAlt", true);
    tv.pluto.ip.dal.channels.Channels.Channel grpcChannel =
        channelsClient.getChannelById(channelsMango.getId()).getDocument();
    Channels grpcChannels = channelsUtils.mapGrpcObjectToPojo(grpcChannel, Channels.class);

    Assert.assertNotNull(grpcChannels.getLogoAlt());
    Assert.assertEquals(grpcChannels.getLogoAlt(), channelsMango.getLogoAlt());
    Assert.assertEquals(channelsMango, grpcChannels);
  }

  @Test
  @Description("UpdateFields - update logoAlt field in channels")
  @TmsLink("28500557")
  public void C28500557_TEST() {
    ChannelsClient channelsClientAuth = new ChannelsClient(grpcChannelManager.getChannel(), true);
    Channels channelsMango = channelsUtils.getRandomDocumentWithTheField("logoAlt", true);
    tv.pluto.ip.dal.channels.Channels.Channel grpcChannel =
        channelsClientAuth.getChannelById(channelsMango.getId()).getDocument();
    Channels grpcChannels = channelsUtils.mapGrpcObjectToPojo(grpcChannel, Channels.class);

    Assert.assertNotNull(grpcChannels.getLogoAlt());
    Assert.assertEquals(grpcChannels.getLogoAlt(), channelsMango.getLogoAlt());
    Assert.assertEquals(channelsMango, grpcChannels);

    String newTitle = CommonUtils.getRandomString();
    List<String> listFields = List.of("name", "logoAlt");

    tv.pluto.ip.dal.channels.Channels.Image updatedLogoAlt =
        tv.pluto.ip.dal.channels.Channels.Image.newBuilder()
            .setTitle(newTitle)
            .setPath(grpcChannel.getLogoAlt().getPath())
            .build();

    tv.pluto.ip.dal.channels.Channels.Channel channelsList =
        newBuilder()
            .setId(channelsMango.getId())
            .setName(channelsMango.getName())
            .setLogoAlt(updatedLogoAlt)
            .build();

    UpdateFieldsResponse getUpdateFieldsGrpcResponse =
        channelsClient.getUpdateFieldsResponse(channelsMango.getId(), channelsList, listFields);

    Channels channelsGrpcResponse =
        channelsUtils.mapGrpcObjectToPojo(
            getUpdateFieldsGrpcResponse.getDocument(), Channels.class);
    Channels channelsMangoDB = channelsUtils.getDocumentById(channelsMango.getId());

    Assert.assertEquals(channelsMango.getName(), channelsGrpcResponse.getName());
    Assert.assertEquals(updatedLogoAlt.getPath(), channelsGrpcResponse.getLogoAlt().getPath());
    Assert.assertEquals(updatedLogoAlt.getTitle(), channelsGrpcResponse.getLogoAlt().getTitle());
    Assert.assertEquals(channelsMangoDB, channelsGrpcResponse);
  }

  @Test
  @Description("UpdateFields - update solidLogoPNGAlt field in channels")
  @TmsLink("28500558")
  public void C28500558_TEST() {
    ChannelsClient channelsClientAuth = new ChannelsClient(grpcChannelManager.getChannel(), true);
    Channels channelsMango = channelsUtils.getRandomDocumentWithTheField("solidLogoPNGAlt", true);
    tv.pluto.ip.dal.channels.Channels.Channel grpcChannel =
        channelsClientAuth.getChannelById(channelsMango.getId()).getDocument();
    Channels grpcChannels = channelsUtils.mapGrpcObjectToPojo(grpcChannel, Channels.class);

    Assert.assertNotNull(grpcChannels.getSolidLogoPNG());
    Assert.assertEquals(grpcChannels.getSolidLogoPNG(), channelsMango.getSolidLogoPNG());
    Assert.assertEquals(channelsMango, grpcChannels);

    String newTitle = CommonUtils.getRandomString();
    List<String> listFields = List.of("name", "solidLogoPNGAlt");

    tv.pluto.ip.dal.channels.Channels.Image image =
        tv.pluto.ip.dal.channels.Channels.Image.newBuilder()
            .setTitle(newTitle)
            .setPath(grpcChannel.getLogoAlt().getPath())
            .build();

    tv.pluto.ip.dal.channels.Channels.Channel channelsList =
        newBuilder()
            .setId(channelsMango.getId())
            .setName(channelsMango.getName())
            .setSolidLogoPNGAlt(image)
            .build();

    UpdateFieldsResponse getUpdateFieldsGrpcResponse =
        channelsClient.getUpdateFieldsResponse(channelsMango.getId(), channelsList, listFields);

    Channels channelsGrpcResponse =
        channelsUtils.mapGrpcObjectToPojo(
            getUpdateFieldsGrpcResponse.getDocument(), Channels.class);
    Channels channelsMangoDB = channelsUtils.getDocumentById(channelsMango.getId());

    Assert.assertEquals(channelsMango.getName(), channelsGrpcResponse.getName());
    Assert.assertEquals(image.getPath(), channelsGrpcResponse.getSolidLogoPNGAlt().getPath());
    Assert.assertEquals(image.getTitle(), channelsGrpcResponse.getSolidLogoPNGAlt().getTitle());
    Assert.assertEquals(channelsMangoDB, channelsGrpcResponse);
  }

  @Test
  @Description("UpdateFields - update colorLogoPNGAlt field in channels")
  @TmsLink("28500559")
  public void C28500559_TEST() {
    ChannelsClient channelsClientAuth = new ChannelsClient(grpcChannelManager.getChannel(), true);
    Channels channelsMango = channelsUtils.getRandomDocumentWithTheField("colorLogoPNGAlt", true);
    tv.pluto.ip.dal.channels.Channels.Channel grpcChannel =
        channelsClientAuth.getChannelById(channelsMango.getId()).getDocument();
    Channels grpcChannels = channelsUtils.mapGrpcObjectToPojo(grpcChannel, Channels.class);

    Assert.assertNotNull(grpcChannels.getColorLogoPNGAlt());
    Assert.assertEquals(grpcChannels.getColorLogoPNGAlt(), channelsMango.getColorLogoPNGAlt());
    Assert.assertEquals(channelsMango, grpcChannels);

    String newTitle = CommonUtils.getRandomString();
    List<String> listFields = List.of("name", "colorLogoPNGAlt");

    tv.pluto.ip.dal.channels.Channels.Image image =
        tv.pluto.ip.dal.channels.Channels.Image.newBuilder()
            .setTitle(newTitle)
            .setPath(grpcChannel.getLogoAlt().getPath())
            .build();

    tv.pluto.ip.dal.channels.Channels.Channel channelsList =
        newBuilder()
            .setId(channelsMango.getId())
            .setName(channelsMango.getName())
            .setColorLogoPNGAlt(image)
            .build();

    UpdateFieldsResponse getUpdateFieldsGrpcResponse =
        channelsClient.getUpdateFieldsResponse(channelsMango.getId(), channelsList, listFields);

    Channels channelsGrpcResponse =
        channelsUtils.mapGrpcObjectToPojo(
            getUpdateFieldsGrpcResponse.getDocument(), Channels.class);
    Channels channelsMangoDB = channelsUtils.getDocumentById(channelsMango.getId());

    Assert.assertEquals(channelsMango.getName(), channelsGrpcResponse.getName());
    Assert.assertEquals(image.getPath(), channelsGrpcResponse.getColorLogoPNGAlt().getPath());
    Assert.assertEquals(image.getTitle(), channelsGrpcResponse.getColorLogoPNGAlt().getTitle());
    Assert.assertEquals(channelsMangoDB, channelsGrpcResponse);
  }

  @Test
  @Description("UpdateFields - update solidLogoSVGAlt field in channels")
  @TmsLink("28500560")
  public void C28500560_TEST() {
    ChannelsClient channelsClientAuth = new ChannelsClient(grpcChannelManager.getChannel(), true);
    Channels channelsMango = channelsUtils.getRandomDocumentWithTheField("solidLogoSVGAlt", true);
    tv.pluto.ip.dal.channels.Channels.Channel grpcChannel =
        channelsClientAuth.getChannelById(channelsMango.getId()).getDocument();
    Channels grpcChannels = channelsUtils.mapGrpcObjectToPojo(grpcChannel, Channels.class);

    Assert.assertNotNull(grpcChannels.getColorLogoPNGAlt());
    Assert.assertEquals(grpcChannels.getColorLogoPNGAlt(), channelsMango.getColorLogoPNGAlt());
    Assert.assertEquals(channelsMango, grpcChannels);

    String newTitle = CommonUtils.getRandomString();
    List<String> listFields = List.of("name", "solidLogoSVGAlt");

    tv.pluto.ip.dal.channels.Channels.Image image =
        tv.pluto.ip.dal.channels.Channels.Image.newBuilder()
            .setTitle(newTitle)
            .setPath(grpcChannel.getLogoAlt().getPath())
            .build();

    tv.pluto.ip.dal.channels.Channels.Channel channelsList =
        newBuilder()
            .setId(channelsMango.getId())
            .setName(channelsMango.getName())
            .setSolidLogoSVGAlt(image)
            .build();

    UpdateFieldsResponse getUpdateFieldsGrpcResponse =
        channelsClient.getUpdateFieldsResponse(channelsMango.getId(), channelsList, listFields);

    Channels channelsGrpcResponse =
        channelsUtils.mapGrpcObjectToPojo(
            getUpdateFieldsGrpcResponse.getDocument(), Channels.class);
    Channels channelsMangoDB = channelsUtils.getDocumentById(channelsMango.getId());

    Assert.assertEquals(channelsMango.getName(), channelsGrpcResponse.getName());
    Assert.assertEquals(image.getPath(), channelsGrpcResponse.getSolidLogoSVGAlt().getPath());
    Assert.assertEquals(image.getTitle(), channelsGrpcResponse.getSolidLogoSVGAlt().getTitle());
    Assert.assertEquals(channelsMangoDB, channelsGrpcResponse);
  }

  @Test
  @Description("UpdateFields - update colorLogoSVGAlt field in channels")
  @TmsLink("28500553")
  public void C28500553_TEST6() {
    ChannelsClient channelsClientAuth = new ChannelsClient(grpcChannelManager.getChannel(), true);
    Channels channelsMango = channelsUtils.getRandomDocumentWithTheField("colorLogoSVGAlt", true);
    tv.pluto.ip.dal.channels.Channels.Channel grpcChannel =
        channelsClientAuth.getChannelById(channelsMango.getId()).getDocument();
    Channels grpcChannels = channelsUtils.mapGrpcObjectToPojo(grpcChannel, Channels.class);

    Assert.assertNotNull(grpcChannels.getColorLogoSVGAlt());
    Assert.assertEquals(grpcChannels.getColorLogoSVGAlt(), channelsMango.getColorLogoSVGAlt());
    Assert.assertEquals(channelsMango, grpcChannels);

    String newTitle = CommonUtils.getRandomString();
    List<String> listFields = List.of("name", "colorLogoSVGAlt");

    tv.pluto.ip.dal.channels.Channels.Image image =
        tv.pluto.ip.dal.channels.Channels.Image.newBuilder()
            .setTitle(newTitle)
            .setPath(grpcChannel.getLogoAlt().getPath())
            .build();

    tv.pluto.ip.dal.channels.Channels.Channel channelsList =
        newBuilder()
            .setId(channelsMango.getId())
            .setName(channelsMango.getName())
            .setColorLogoSVGAlt(image)
            .build();

    UpdateFieldsResponse getUpdateFieldsGrpcResponse =
        channelsClient.getUpdateFieldsResponse(channelsMango.getId(), channelsList, listFields);

    Channels channelsGrpcResponse =
        channelsUtils.mapGrpcObjectToPojo(
            getUpdateFieldsGrpcResponse.getDocument(), Channels.class);
    Channels channelsMangoDB = channelsUtils.getDocumentById(channelsMango.getId());

    Assert.assertEquals(channelsMango.getName(), channelsGrpcResponse.getName());
    Assert.assertEquals(image.getPath(), channelsGrpcResponse.getColorLogoSVGAlt().getPath());
    Assert.assertEquals(image.getTitle(), channelsGrpcResponse.getColorLogoSVGAlt().getTitle());
    Assert.assertEquals(channelsMangoDB, channelsGrpcResponse);
  }

  @Test
  @Description("GetById - verify a solidLogoPNGAlt field")
  @TmsLink("28500554")
  public void C28500554_TEST() {
    Channels channelsMango = channelsUtils.getRandomDocumentWithTheField("solidLogoPNGAlt", true);
    tv.pluto.ip.dal.channels.Channels.Channel grpcChannel =
        channelsClient.getChannelById(channelsMango.getId()).getDocument();
    Channels grpcChannels = channelsUtils.mapGrpcObjectToPojo(grpcChannel, Channels.class);

    Assert.assertNotNull(grpcChannels.getSolidLogoPNGAlt());
    Assert.assertEquals(grpcChannels.getSolidLogoPNGAlt(), channelsMango.getSolidLogoPNGAlt());
    Assert.assertEquals(channelsMango, grpcChannels);
  }

  @Test
  @Description("GetById - verify a colorLogoPNGAlt field")
  @TmsLink("28500516")
  public void C28500516_TEST6() {
    Channels channelsMango = channelsUtils.getRandomDocumentWithTheField("colorLogoPNGAlt", true);
    tv.pluto.ip.dal.channels.Channels.Channel grpcChannel =
        channelsClient.getChannelById(channelsMango.getId()).getDocument();
    Channels grpcChannels = channelsUtils.mapGrpcObjectToPojo(grpcChannel, Channels.class);

    Assert.assertNotNull(grpcChannels.getColorLogoPNGAlt());
    Assert.assertEquals(grpcChannels.getColorLogoPNGAlt(), channelsMango.getColorLogoPNGAlt());
    Assert.assertEquals(channelsMango, grpcChannels);
  }

  @Test
  @Description("GetById - verify a solidLogoSVGAlt field")
  @TmsLink("28500555")
  public void C28500555_TEST() {
    Channels channelsMango = channelsUtils.getRandomDocumentWithTheField("solidLogoSVGAlt", true);
    tv.pluto.ip.dal.channels.Channels.Channel grpcChannel =
        channelsClient.getChannelById(channelsMango.getId()).getDocument();
    Channels grpcChannels = channelsUtils.mapGrpcObjectToPojo(grpcChannel, Channels.class);

    Assert.assertNotNull(grpcChannels.getSolidLogoSVGAlt());
    Assert.assertEquals(grpcChannels.getSolidLogoSVGAlt(), channelsMango.getSolidLogoSVGAlt());
    Assert.assertEquals(channelsMango, grpcChannels);
  }

  @Test
  @Description("GetById - verify a ColorLogoSVGAlt field")
  @TmsLink("28500556")
  public void C28500556_TEST() {
    Channels channelsMango = channelsUtils.getRandomDocumentWithTheField("colorLogoSVGAlt", true);
    tv.pluto.ip.dal.channels.Channels.Channel grpcChannel =
        channelsClient.getChannelById(channelsMango.getId()).getDocument();
    Channels grpcChannels = channelsUtils.mapGrpcObjectToPojo(grpcChannel, Channels.class);

    Assert.assertNotNull(grpcChannels.getColorLogoSVGAlt());
    Assert.assertEquals(grpcChannels.getColorLogoSVGAlt(), channelsMango.getColorLogoSVGAlt());
    Assert.assertEquals(channelsMango, grpcChannels);
  }

  @Test
  @Description("GetAllPaged - filter by samsungChannelProperties.id no sort")
  @TmsLink("28500535")
  public void C28500535_TEST() {
    ChannelsClient channelsClient = new ChannelsClient(grpcChannelManager.getChannel(), false);
    SamsungChannelProperties samsungChannelProperties =
        samsungChannelPropertiesUtils.getRandomDocumentWithTheField("channel", true);

    List<Filter> listFilter =
        Collections.singletonList(
            Filter.newBuilder()
                .setField("samsungChannelProperties.id")
                .setValue(samsungChannelProperties.getId())
                .setType("string")
                .build());

    GetAllPagedResponse response = channelsClient.getAllPaged(1, 0, null, listFilter, null);

    Assert.assertEquals(1, response.getDocumentsList().size());
    Assert.assertEquals(
        samsungChannelProperties.getId(),
        response.getDocumentsList().get(0).getSamsungChannelProperties(0).getId());
    Assert.assertEquals(
        samsungChannelProperties.getChannel(),
        response.getDocumentsList().get(0).getSamsungChannelProperties(0).getChannel());
    Assert.assertEquals(
        samsungChannelProperties.getServiceId(),
        response.getDocumentsList().get(0).getSamsungChannelProperties(0).getServiceId());
    Assert.assertEquals(
        samsungChannelProperties.getIntilesEnabled().booleanValue(),
        response.getDocumentsList().get(0).getSamsungChannelProperties(0).getIntilesEnabled());
    Assert.assertEquals(
        samsungChannelProperties.getRegion(),
        response.getDocumentsList().get(0).getSamsungChannelProperties(0).getRegion());
  }

  @Test
  @Description("GetAllPaged - filter by samsungChannelProperties.id with sort")
  @TmsLink("28500536")
  public void C28500536_TEST() {
    ChannelsClient channelsClient = new ChannelsClient(grpcChannelManager.getChannel(), false);
    SamsungChannelProperties samsungChannelProperties =
        samsungChannelPropertiesUtils.getRandomDocumentWithTheField("channel", true);

    List<Filter> listFilter =
        Collections.singletonList(
            Filter.newBuilder()
                .setField("samsungChannelProperties.id")
                .setValue(samsungChannelProperties.getId())
                .setType("string")
                .build());

    List<GetAllPagedSort> grpcSort = channelsClient.singleListSortObject("_id", 1);

    GetAllPagedResponse response = channelsClient.getAllPaged(1, 0, grpcSort, listFilter, true);

    Assert.assertEquals(1, response.getDocumentsList().size());
    Assert.assertEquals(1, response.getDocumentsCount());
    Assert.assertEquals(
        samsungChannelProperties.getId(),
        response.getDocumentsList().get(0).getSamsungChannelProperties(0).getId());
    Assert.assertEquals(
        samsungChannelProperties.getChannel(),
        response.getDocumentsList().get(0).getSamsungChannelProperties(0).getChannel());
    Assert.assertEquals(
        samsungChannelProperties.getServiceId(),
        response.getDocumentsList().get(0).getSamsungChannelProperties(0).getServiceId());
    Assert.assertEquals(
        samsungChannelProperties.getIntilesEnabled().booleanValue(),
        response.getDocumentsList().get(0).getSamsungChannelProperties(0).getIntilesEnabled());
    Assert.assertEquals(
        samsungChannelProperties.getRegion(),
        response.getDocumentsList().get(0).getSamsungChannelProperties(0).getRegion());
  }

  @Test
  @Description("GetAllPaged - AND operator with valid fields")
  @TmsLink("28500546")
  public void C28500546_TEST() {
    ChannelsClient channelsClient = new ChannelsClient(grpcChannelManager.getChannel(), false);
    Channels channels = channelsUtils.getRandomDocument();

    List<Filter> listFilter =
        List.of(
            channelsClient.getFilter("category", channels.getCategory(), "", "AND"),
            channelsClient.getFilter("name", channels.getName(), "", "AND"));

    GetAllPagedResponse response = channelsClient.getAllPaged(10, 0, null, listFilter, true);

    BasicDBObject query =
        new BasicDBObject("category", channels.getCategory()).append("name", channels.getName());
    List<Channels> listChannels = channelsUtils.getListChannels(query);
    List<Channels> listChannelsGrpc =
        channelsUtils.mapGrpcObjectsToPojo(response.getDocumentsList(), Channels.class);

    listChannels.forEach(chan -> chan.setMainCategories(null));
    listChannelsGrpc.forEach(chan -> chan.setMainCategories(null));

    listChannels.sort(Comparator.comparing(Channels::getName));
    listChannelsGrpc.sort(Comparator.comparing(Channels::getName));

    Assert.assertEquals(listChannels, listChannelsGrpc);
  }

  @Test(expectedExceptions = RuntimeException.class, expectedExceptionsMessageRegExp = NOT_FOUND)
  @TmsLink("28500547")
  @Description("GetAllPaged - AND operator with valid/invalid fields")
  public void C28500547_TEST()
      throws NoSuchFieldException, InvocationTargetException, IllegalAccessException {
    ChannelsClient channelsClient = new ChannelsClient(grpcChannelManager.getChannel(), false);
    Channels channels = channelsUtils.getRandomDocument();

    List<Filter> listFilter =
        List.of(
            channelsClient.getFilter("category", channels.getCategory(), "", "AND"),
            channelsClient.getFilter("name", "testDAl98799999", "", "AND"));

    channelsClient.getAllPagedException(10, 0, null, listFilter, true);
  }

  @Test
  @Description("GetAllPaged - OR operator with valid fields")
  @TmsLink("28500548")
  public void C28500548_TEST() {
    List<Channels> channels = channelsUtils.getDocuments(2);

    List<Filter> listFilter =
        List.of(
            channelsClient.getFilter("name", channels.get(0).getName(), "", "OR"),
            channelsClient.getFilter("_id", channels.get(1).getId(), "", "OR"));

    GetAllPagedResponse response =
        new ChannelsClient(grpcChannelManager.getChannel(), false)
            .getAllPagedRegex(500, 0, null, listFilter, true);
    LogUtils.logInfoMessage(listFilter + "");
    LogUtils.logInfoMessage(response.getMetadata().getTotalItems() + "");

    // partial search
    List<BasicDBObject> mongoOrList =
        Arrays.asList(
            new BasicDBObject(
                "name", Pattern.compile(channels.get(0).getName(), Pattern.CASE_INSENSITIVE)),
            new BasicDBObject("_id", new ObjectId(channels.get(1).getId())));

    BasicDBObject query = new BasicDBObject("$or", mongoOrList);
    List<Channels> listChannels = channelsUtils.getListChannels(query);
    List<Channels> listChannelsGrpc =
        channelsUtils.mapGrpcObjectsToPojo(response.getDocumentsList(), Channels.class);

    listChannels.sort(Comparator.comparing(Channels::getName));
    listChannelsGrpc.sort(Comparator.comparing(Channels::getName));
    listChannelsGrpc.forEach(c -> c.setMainCategories(null));

    Assert.assertTrue(listChannels.size() > 0);
    Assert.assertEquals(listChannels, listChannelsGrpc);
  }

  private List<Channels> setUpMainCategoriesForChannels(List<Channels> listChannels) {
    listChannels.forEach(
        c -> {
          List<MainCategories> listMainCategories =
              c.getCategories().stream()
                  .map(cat -> cat.getCatId())
                  .filter(catId -> !catId.isEmpty())
                  .map(catId -> (MainCategories) mainCategoriesUtils.getDocumentById(catId))
                  .collect(Collectors.toList());

          c.setMainCategories(listMainCategories);
        });
    return listChannels;
  }

  @Test
  @Description("GetAllPaged - Filter only by Id")
  @TmsLink("28500549")
  public void C28500549_TEST() {
    ChannelsClient channelsClient = new ChannelsClient(grpcChannelManager.getChannel(), false);
    Channels channels = channelsUtils.getRandomDocument();

    List<Filter> listFilter = List.of(channelsClient.getFilter("_id", channels.getId(), "", null));

    GetAllPagedResponse response = channelsClient.getAllPaged(500, 0, null, listFilter, true);
    Assert.assertEquals(1, response.getDocumentsCount());
    Assert.assertEquals(1, response.getDocumentsList().size());

    Channels channelsGrpc =
        channelsUtils.mapGrpcObjectToPojo(response.getDocumentsList().get(0), Channels.class);

    channelsWithMainCategory(channels, channelsGrpc.getMainCategories());
    Assert.assertEquals(channelsGrpc, channels);
  }

  private Channels channelsWithMainCategory(Channels channels, List<MainCategories> grpcMainIds) {
    List<String> listMainIds =
        grpcMainIds.stream().map(MainCategories::getId).collect(Collectors.toList());
    List<MainCategories> listDbMainCategories = mainCategoriesUtils.getDocumentsByIds(listMainIds);
    channels.setMainCategories(listDbMainCategories);
    return channels;
  }

  @Test(dataProvider = "is-true-false")
  @TmsLink("28500550")
  @Description("GetAllPaged - OR and AND operators with valid fields")
  public void C28500550_TEST(boolean isTrue) {
    int limit = 5;
    ChannelsClient channelsClient = new ChannelsClient(grpcChannelManager.getChannel(), false);
    Channels firstChannel;

    if (isTrue) {
      List<Channels> listChannels = channelsUtils.getDocuments(2000);
      firstChannel =
          listChannels.stream()
              .filter(channel -> channel.getName().contains("/"))
              .findAny()
              .orElseThrow();
    } else firstChannel = channelsUtils.getRandomDocument();

    Channels secondChannel = channelsUtils.getRandomDocument();

    List<Filter> listFilter =
        List.of(
            channelsClient.getFilter("name", firstChannel.getName(), "", "OR"),
            channelsClient.getFilter("_id", secondChannel.getId(), "", "OR"),
            channelsClient.getFilter(
                "kidsMode", String.valueOf(secondChannel.getKidsMode()), "boolean", "AND"));

    GetAllPagedResponse response =
        channelsClient.getAllPagedRegex(isTrue ? limit : 0, 0, null, listFilter, isTrue);

    Pattern regexPattern = Pattern.compile(firstChannel.getName(), Pattern.CASE_INSENSITIVE);

    List<BasicDBObject> mongoOrList =
        Arrays.asList(
            new BasicDBObject("name", regexPattern),
            new BasicDBObject("_id", new ObjectId(secondChannel.getId())));

    BasicDBObject query =
        new BasicDBObject("$or", mongoOrList).append("kidsMode", secondChannel.getKidsMode());
    List<Channels> listChannels = channelsUtils.getListChannels(query);
    List<Channels> listChannelsGrpc =
        channelsUtils.mapGrpcObjectsToPojo(response.getDocumentsList(), Channels.class);

    listChannels.forEach(chan -> chan.setMainCategories(null));
    listChannelsGrpc.forEach(chan -> chan.setMainCategories(null));
    listChannels.sort(Comparator.comparing(Channels::getName));
    listChannelsGrpc.sort(Comparator.comparing(Channels::getName));

    Assert.assertTrue(listChannels.size() > 0);
    Assert.assertEquals(listChannels, listChannelsGrpc);

    if (isTrue) Assert.assertTrue(response.getMetadata().getTotalItems() <= limit);
    else Assert.assertEquals(listChannels.size(), response.getMetadata().getTotalItems());
  }

  @Test
  @Description(
      "GetAllPaged - samsungChannelProperties.serviceId crash when used with AND OR operators")
  @TmsLink("28500561")
  public void C28500561_TEST() {
    ChannelsClient channelsClient = new ChannelsClient(grpcChannelManager.getChannel(), false);
    SamsungChannelProperties samsungChannelProperties =
        samsungChannelPropertiesUtils.getRandomDocumentWithTheField("channel", true);
    String samsungChannelId = samsungChannelProperties.getChannel();
    String channelCategory =
        channelsClient.getChannelById(samsungChannelId).getDocument().getCategory();

    List<Filter> listFilter = new ArrayList<>();
    Filter samsungChannelBuild =
        Filter.newBuilder()
            .setField("samsungChannelProperties.id")
            .setValue(samsungChannelProperties.getId())
            .setType("string")
            .setOperator("AND")
            .build();

    Filter categoryBuild =
        Filter.newBuilder()
            .setField("category")
            .setValue(channelCategory)
            .setType("string")
            .setOperator("AND")
            .build();

    listFilter.add(samsungChannelBuild);
    listFilter.add(categoryBuild);

    GetAllPagedResponse response = channelsClient.getAllPaged(1, 0, null, listFilter, true);

    int docSize = response.getDocumentsList().size();
    Assert.assertEquals(1, docSize);
    Assert.assertEquals(samsungChannelId, response.getDocumentsList().get(0).getId());
    Assert.assertEquals(channelCategory, response.getDocumentsList().get(0).getCategory());
    Assert.assertEquals(docSize, response.getMetadata().getTotalItems());
  }

  @Test
  @Description("UpdateFields - SamsungProperty service_id object")
  @TmsLink("28500537")
  public void C28500537_TEST() {
    String testVar = "A";
    List<String> listFields = List.of("samsungChannelProperties");

    SamsungChannelProperties samsungChannelProperties =
        samsungChannelPropertiesUtils.getRandomDocumentWithTheField("channel", true);
    LogUtils.logInfoMessage("Channel id: " + samsungChannelProperties.getChannel());
    tv.pluto.ip.dal.channels.Channels.Channel channelGrpc =
        channelsClient.getChannelById(samsungChannelProperties.getChannel()).getDocument();

    SamsungChannelProperty samsungChannelProperty =
        channelGrpc.getSamsungChannelPropertiesList().get(0);
    LogUtils.logInfoMessage(
        "Samsung id: "
            + samsungChannelProperty.getId()
            + ", serviceId: "
            + samsungChannelProperty.getServiceId());

    SamsungChannelProperty propertyBuild =
        SamsungChannelProperty.newBuilder()
            .setId(samsungChannelProperty.getId())
            .setChannel(samsungChannelProperty.getChannel())
            .setServiceId(samsungChannelProperty.getServiceId() + testVar)
            .build();

    tv.pluto.ip.dal.channels.Channels.Channel channelsList =
        newBuilder().setId(channelGrpc.getId()).addSamsungChannelProperties(propertyBuild).build();

    UpdateFieldsResponse grpcResponse =
        channelsClient.getUpdateFieldsResponse(channelGrpc.getId(), channelsList, listFields);
    SamsungChannelProperty grpcSamsungChannelProp =
        grpcResponse.getDocument().getSamsungChannelProperties(0);

    Assert.assertEquals(grpcSamsungChannelProp.getId(), samsungChannelProperty.getId());
    Assert.assertEquals(grpcSamsungChannelProp.getChannel(), samsungChannelProperty.getChannel());
    Assert.assertEquals(
        grpcSamsungChannelProp.getServiceId(), samsungChannelProperty.getServiceId() + testVar);
    Assert.assertEquals(grpcSamsungChannelProp.getRegion(), samsungChannelProperty.getRegion());

    SamsungChannelProperty propertyBuildRevert =
        SamsungChannelProperty.newBuilder()
            .setId(samsungChannelProperty.getId())
            .setChannel(samsungChannelProperty.getChannel())
            .setServiceId(samsungChannelProperty.getServiceId())
            .build();

    tv.pluto.ip.dal.channels.Channels.Channel channelsListRevert =
        newBuilder()
            .setId(channelGrpc.getId())
            .addSamsungChannelProperties(propertyBuildRevert)
            .build();

    UpdateFieldsResponse grpcRevertResponse =
        channelsClient.getUpdateFieldsResponse(channelGrpc.getId(), channelsListRevert, listFields);

    Assert.assertEquals(grpcRevertResponse.getDocument().getId(), channelGrpc.getId());
    Assert.assertEquals(
        grpcRevertResponse.getDocument().getSamsungChannelProperties(0).getServiceId(),
        channelGrpc.getSamsungChannelPropertiesList().get(0).getServiceId());
  }

  @Test(expectedExceptions = RuntimeException.class)
  @Description("UpdateFields - SamsungProperty service_id object without the channel field")
  @TmsLink("28500538")
  public void C28500538_TEST() {
    List<String> listFields = List.of("samsungChannelProperties");
    SamsungChannelProperties samsungChannelProperties =
        samsungChannelPropertiesUtils.getRandomDocumentWithTheField("channel", true);
    LogUtils.logInfoMessage("Channel id: " + samsungChannelProperties.getChannel());
    tv.pluto.ip.dal.channels.Channels.Channel channelGrpc =
        channelsClient.getChannelById(samsungChannelProperties.getChannel()).getDocument();
    SamsungChannelProperty samsungChannelProperty =
        channelGrpc.getSamsungChannelPropertiesList().get(0);

    SamsungChannelProperty propertyBuild =
        SamsungChannelProperty.newBuilder()
            .setId(samsungChannelProperty.getId())
            .setServiceId(samsungChannelProperty.getServiceId())
            .build();

    tv.pluto.ip.dal.channels.Channels.Channel channelsList =
        newBuilder().setId(channelGrpc.getId()).addSamsungChannelProperties(propertyBuild).build();

    channelsClient.getUpdateFieldsResponse(channelGrpc.getId(), channelsList, listFields);
  }

  @SuppressWarnings("SizeGreaterThanOrEqualsZero")
  @Test
  @Description("UpdateFields - verify a samsung_channel_properties field")
  @TmsLink("28500520")
  public void C28500520_TEST() {
    Channels channel = channelsUtils.getRandomDocumentWithTheFieldSize("categories", 1, 0);
    LogUtils.logInfoMessage("Random channelId: " + channel.getId());
    List<String> listFields = List.of("name");

    tv.pluto.ip.dal.channels.Channels.Channel channelsList =
        newBuilder().setId(channel.getId()).setName(channel.getName()).build();

    UpdateFieldsResponse grpcResponse =
        channelsClient.getUpdateFieldsResponse(channel.getId(), channelsList, listFields);
    Assert.assertTrue(grpcResponse.getDocument().getSamsungChannelPropertiesCount() >= 0);
  }

  @Test
  @Description("UpdateFields - zipCodeDistribution field")
  @TmsLink("28500521")
  public void C28500521_TEST() {
    Channels channel = channelsUtils.getRandomDocumentWithTheFieldSize("categories", 1, 0);
    LogUtils.logInfoMessage("C34823497_TEST. Random channelId: " + channel.getId());
    List<String> listFields = List.of("zipCodeDistribution");
    String randomZip = new Faker().address().zipCode();
    String randomZipTwo = new Faker().address().zipCode();
    String randomZipThree = new Faker().address().zipCode();
    List<String> randomZipList = List.of(randomZip, randomZipTwo, randomZipThree);

    tv.pluto.ip.dal.channels.Channels.Channel channelsList =
        newBuilder().setId(channel.getId()).addAllZipCodeDistribution(randomZipList).build();

    UpdateFieldsResponse grpcResponse =
        channelsClient.getUpdateFieldsResponse(channel.getId(), channelsList, listFields);

    Assert.assertEquals(grpcResponse.getDocument().getZipCodeDistributionList(), randomZipList);
  }

  @Test(
      expectedExceptions = RuntimeException.class,
      expectedExceptionsMessageRegExp =
          "INTERNAL: ValidationError: zipCodeDistribution: Invalid Zip Codes:.*")
  @Description("UpdateFields - invalid zipCodeDistribution field")
  @TmsLink("28500522")
  public void C28500522_TEST() {
    Channels channel = channelsUtils.getRandomDocumentWithTheFieldSize("categories", 1, 0);
    LogUtils.logInfoMessage("C34824027. Random channelId: " + channel.getId());
    List<String> listFields = List.of("zipCodeDistribution");
    String randomZip = "notZipCoe";
    String randomZipTwo = "1234567890123456789012345678901234567890";

    List<String> randomZipList = List.of(randomZip, randomZipTwo);

    tv.pluto.ip.dal.channels.Channels.Channel channelsList =
        newBuilder().setId(channel.getId()).addAllZipCodeDistribution(randomZipList).build();

    channelsClient.getUpdateFieldsResponse(channel.getId(), channelsList, listFields);
  }

  @Test
  @Description("GetAll - verify a samsung_channel_properties field")
  @TmsLink("28500523")
  public void C28500523_TEST() {
    Iterator<tv.pluto.ip.dal.channels.Channels.Channel> getAllResponse =
        channelsClient.getAllResponse("us");
    Assert.assertNotNull(getAllResponse.next().getSamsungChannelPropertiesList());
  }

  @Test
  @Description("Create - creating new channel")
  @TmsLink("28500524")
  public void C28500524_TEST() {
    Channels channels = channelsUtils.getRandomDocumentWithTheFieldSize("categories", 1, 1);
    tv.pluto.ip.dal.channels.Channels.Channel initChannel =
        new ChannelsClient(grpcChannelManager.getChannel(), true)
            .getChannelById(channels.getId())
            .getDocument();
    Channels grpcChannel = channelsUtils.mapGrpcObjectToPojo(initChannel, Channels.class);
    String replacedName = "DAL Create test channel";
    String json;
    tv.pluto.ip.dal.channels.Channels.Channel channelCreateObj;

    try {
      grpcChannel.setId("");
      grpcChannel.setName(replacedName);

      // Workaround to prevent duplicate error
      grpcChannel.setAccessCode((int) System.currentTimeMillis());

      // Workaround in case of bad test data
      if (initChannel.getNumber() == 0) {
        grpcChannel.setNumber(1);
      }

      // Workaround in case of bad test data
      if (initChannel.getAutoScheduleDays() < 1 || initChannel.getAutoScheduleDays() > 30) {
        grpcChannel.setAutoScheduleDays(1);
      }

      if (initChannel.getSummary().isEmpty()) grpcChannel.setSummary("new summary");

      if (initChannel.getTagsList().isEmpty()) grpcChannel.setTags(List.of("testTag"));

      json = new Gson().toJson(grpcChannel);

      channelCreateObj =
          ProtoJsonUtil.fromJson(json, tv.pluto.ip.dal.channels.Channels.Channel.class);
    } catch (IOException e) {
      throw new RuntimeException(e);
    }

    tv.pluto.ip.dal.channels.Channels.CreateResponse createResponse =
        channelsClientAuth.create(channelCreateObj);
    String createdChannelId = createResponse.getDocument().getId();
    LogUtils.logInfoMessage("C21906894_TEST Created channel ID = " + createdChannelId);
    Channels mongoChannel = channelsUtils.getDocumentById(createdChannelId);

    SoftAssert softAssert = new SoftAssert();

    softAssert.assertEquals(replacedName, mongoChannel.getName());
    softAssert.assertEquals(
        initChannel.getIsStitched(), mongoChannel.getIsStitched().booleanValue());
    softAssert.assertEquals(initChannel.getActiveRegion(), mongoChannel.getActiveRegion());
    softAssert.assertEquals(initChannel.getPublished(), mongoChannel.getPublished().booleanValue());
    softAssert.assertNotEquals(0, mongoChannel.getAccessCode().intValue());
    softAssert.assertAll();

    channelsUtils.deleteDocumentById(createdChannelId);
  }

  @Test
  @Description("Create - creating new channel with zipCodeDistribution array")
  @TmsLink("28500525")
  public void C28500525_TEST() {
    Channels channels = channelsUtils.getRandomDocumentWithTheFieldSize("categories", 1, 1);
    tv.pluto.ip.dal.channels.Channels.Channel initChannel =
        new ChannelsClient(grpcChannelManager.getChannel(), true)
            .getChannelById(channels.getId())
            .getDocument();
    Channels grpcChannel = channelsUtils.mapGrpcObjectToPojo(initChannel, Channels.class);
    String replacedName = "DAL Create test channel with zipCodeDistribution";
    String json;
    tv.pluto.ip.dal.channels.Channels.Channel channelCreateObj;
    List<String> listZipCodeDistribution = List.of("90018", "90019", "90020");

    try {
      grpcChannel.setId("");
      grpcChannel.setName(replacedName);

      grpcChannel.setAccessCode((int) System.currentTimeMillis());

      if (initChannel.getNumber() == 0) {
        grpcChannel.setNumber(1);
      }

      if (initChannel.getAutoScheduleDays() < 1 || initChannel.getAutoScheduleDays() > 30) {
        grpcChannel.setAutoScheduleDays(1);
      }

      if (initChannel.getSummary().isEmpty()) grpcChannel.setSummary("new summary");

      if (initChannel.getTagsList().isEmpty()) grpcChannel.setTags(List.of("testTag"));

      grpcChannel.setZipCodeDistribution(listZipCodeDistribution);

      json = new Gson().toJson(grpcChannel);

      channelCreateObj =
          ProtoJsonUtil.fromJson(json, tv.pluto.ip.dal.channels.Channels.Channel.class);
    } catch (IOException e) {
      throw new RuntimeException(e);
    }

    tv.pluto.ip.dal.channels.Channels.CreateResponse createResponse =
        channelsClientAuth.create(channelCreateObj);
    String createdChannelId = createResponse.getDocument().getId();
    LogUtils.logInfoMessage("C34819425_TEST Created channel ID = " + createdChannelId);
    Channels mongoChannel = channelsUtils.getDocumentById(createdChannelId);

    SoftAssert softAssert = new SoftAssert();

    softAssert.assertEquals(replacedName, mongoChannel.getName());
    softAssert.assertEquals(
        initChannel.getIsStitched(), mongoChannel.getIsStitched().booleanValue());
    softAssert.assertEquals(initChannel.getActiveRegion(), mongoChannel.getActiveRegion());
    softAssert.assertEquals(initChannel.getPublished(), mongoChannel.getPublished().booleanValue());
    softAssert.assertNotEquals(0, mongoChannel.getAccessCode().intValue());
    softAssert.assertEquals(listZipCodeDistribution, mongoChannel.getZipCodeDistribution());
    softAssert.assertAll();

    channelsUtils.deleteDocumentById(createdChannelId);
  }

  @Test(
      expectedExceptions = RuntimeException.class,
      expectedExceptionsMessageRegExp = "INTERNAL: Invalid Zip Codes:.*")
  @Description("Create - creating new channel with invalid zipCodeDistribution array")
  @TmsLink("28500526")
  public void C28500526_TEST() {
    Channels channels = channelsUtils.getRandomDocumentWithTheFieldSize("categories", 1, 1);
    tv.pluto.ip.dal.channels.Channels.Channel initChannel =
        new ChannelsClient(grpcChannelManager.getChannel(), true)
            .getChannelById(channels.getId())
            .getDocument();
    Channels grpcChannel = channelsUtils.mapGrpcObjectToPojo(initChannel, Channels.class);
    String replacedName = "DAL Create test channel with zipCodeDistribution";
    String json;
    tv.pluto.ip.dal.channels.Channels.Channel channelCreateObj;
    List<String> listZipCodeDistribution =
        List.of("invalidZip", "90019", "1234567890123456789012345678901234567890");

    try {
      grpcChannel.setId("");
      grpcChannel.setName(replacedName);

      grpcChannel.setAccessCode((int) System.currentTimeMillis());

      if (initChannel.getNumber() == 0) {
        grpcChannel.setNumber(1);
      }

      if (initChannel.getAutoScheduleDays() < 1 || initChannel.getAutoScheduleDays() > 30) {
        grpcChannel.setAutoScheduleDays(1);
      }

      if (initChannel.getSummary().isEmpty()) grpcChannel.setSummary("new summary");

      if (initChannel.getTagsList().isEmpty()) grpcChannel.setTags(List.of("testTag"));

      grpcChannel.setZipCodeDistribution(listZipCodeDistribution);

      json = new Gson().toJson(grpcChannel);

      channelCreateObj =
          ProtoJsonUtil.fromJson(json, tv.pluto.ip.dal.channels.Channels.Channel.class);
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
    channelsClientAuth.create(channelCreateObj);
  }

  @Test
  @Description("Create - creating channel without authentication")
  @TmsLink("28500527")
  public void C28500527_TEST() {
    try {
      channelsClient.create(tv.pluto.ip.dal.channels.Channels.Channel.newBuilder().build());
    } catch (StatusRuntimeException e) {
      Assert.assertEquals(e.getStatus().getCode().value(), 16);
      Assert.assertEquals(
          e.getMessage(), "UNAUTHENTICATED: DB writes not allowed without authentication");
    }
  }

  @Test
  @Description("BulkDeviceUpdate - update channels with existing devices, include group")
  @TmsLink("28500528")
  public void C28500528_TEST() {
    List<Devices> devices = devicesUtils.getDocuments(3);
    List<Channels> channels = channelsUtils.getDocuments(3);

    List<String> devicesIds = devicesUtils.getListDeviceIds(devices);
    List<String> platforms = devicesUtils.getListPlatforms(devices);
    List<String> channelsIds = channelsUtils.getListIds(channels);

    LogUtils.logInfoMessage("C22150154_TEST data");
    LogUtils.logInfoMessage("ChannelsIds list " + channelsIds);
    LogUtils.logInfoMessage("DevicesIds list " + devicesIds);
    LogUtils.logInfoMessage("Platforms list " + platforms);

    channelsClient.bulkDeviceUpdate(devicesIds, channelsIds, null, null);

    List<Channels> channelsAfterUpdate = channelsUtils.getDocumentsByIds(channelsIds);

    channelsAfterUpdate.forEach(
        channel -> {
          Assert.assertTrue(
              channel.getDistribution().getInclude().containsAll(platforms),
              "Channels platforms "
                  + channel.getDistribution().getInclude()
                  + "\n "
                  + "platforms for include "
                  + platforms);

          Assert.assertFalse(channel.getDistribution().getExclude().containsAll(platforms));
        });
  }

  @Test
  @Description("BulkDeviceUpdate - delete channels with existing devices, include group")
  @TmsLink("28500539")
  public void C28500539_TEST() {
    List<Devices> devices = devicesUtils.getDocuments(3);
    List<Channels> channels = channelsUtils.getDocuments(3);

    List<String> devicesIds = devicesUtils.getListDeviceIds(devices);
    List<String> platforms = devicesUtils.getListPlatforms(devices);
    List<String> channelsIds = channelsUtils.getListIds(channels);
    Assert.assertEquals(3, channelsIds.size());

    List<String> includeIds = List.of(channelsIds.get(0));
    List<String> removeIds = channelsIds.subList(1, channelsIds.size() - 1);

    new ChannelsClient(grpcChannelManager.getChannel(), false)
        .bulkDeviceUpdate(devicesIds, includeIds, null, removeIds);

    List<Channels> channelsAfterUpdate = channelsUtils.getDocumentsByIds(removeIds);

    channelsAfterUpdate.forEach(
        channel -> {
          boolean isEqual = channel.getDistribution().getInclude().containsAll(platforms);

          Assert.assertFalse(
              isEqual,
              "Channels platforms "
                  + channel.getDistribution().getInclude()
                  + "\n "
                  + "platforms for include "
                  + platforms);
        });
  }

  @Test
  @Description("BulkDeviceUpdate - delete channels with existing devices, exclude group")
  @TmsLink("28500542")
  public void C28500542_TEST() {
    List<Devices> devices = devicesUtils.getDocuments(2);
    List<Channels> channels = channelsUtils.getDocuments(2);

    List<String> devicesIds = devicesUtils.getListDeviceIds(devices);
    List<String> platforms = devicesUtils.getListPlatforms(devices);
    List<String> channelsIds = channelsUtils.getListIds(channels);

    channelsClient.bulkDeviceUpdate(devicesIds, null, channelsIds, null);
    List<Channels> channelsAfterUpdate = channelsUtils.getDocumentsByIds(channelsIds);

    channelsAfterUpdate.forEach(
        channel ->
            Assert.assertTrue(
                channel.getDistribution().getExclude().containsAll(platforms),
                "Channels platforms "
                    + channel.getDistribution().getExclude()
                    + "\n "
                    + "platforms for exclude "
                    + platforms));
  }

  @Test
  @Description("BulkDeviceUpdate - delete channels with existing devices")
  @TmsLink("28500543")
  public void C28500543_TEST() {
    List<Devices> devices = devicesUtils.getRandomDocuments(2);
    List<Channels> channels = channelsUtils.getRandomDocuments(2);

    List<String> devicesIds = devicesUtils.getListDeviceIds(devices);
    List<String> platforms = devicesUtils.getListPlatforms(devices);
    List<String> channelsIds = channelsUtils.getListIds(channels);

    channelsClient.bulkDeviceUpdate(devicesIds, null, null, channelsIds);

    List<Channels> channelsAfterUpdate = channelsUtils.getDocumentsByIds(channelsIds);

    channelsAfterUpdate.forEach(
        channel -> {
          Assert.assertFalse(
              channel.getDistribution().getInclude().containsAll(platforms),
              "Channels platforms "
                  + channel.getDistribution().getInclude()
                  + "\n "
                  + "platforms for include "
                  + platforms);

          Assert.assertFalse(
              channel.getDistribution().getExclude().containsAll(platforms),
              "Channels platforms "
                  + channel.getDistribution().getExclude()
                  + "\n "
                  + "platforms for exclude "
                  + platforms);
        });
  }

  @Test(expectedExceptions = RuntimeException.class)
  @Description("BulkDeviceUpdate - delete invalid removeGroup channels")
  @TmsLink("28500544")
  public void C28500544_TEST() {
    List<Devices> devices = devicesUtils.getRandomDocuments(2);
    List<String> devicesIds = devicesUtils.getListDeviceIds(devices);

    channelsClient.bulkDeviceUpdate(devicesIds, null, null, List.of("DAL_Test"));
  }

  @Test
  @Description(
      "BulkDeviceUpdate - delete channels with existing devices, include and exclude group")
  @TmsLink("28500540")
  public void C28500540_TEST() {
    List<Devices> devices = devicesUtils.getRandomDocuments(3);
    List<Channels> channels = channelsUtils.getRandomDocuments(3);

    List<String> devicesIds = devicesUtils.getListDeviceIds(devices);
    List<String> platforms = devicesUtils.getListPlatforms(devices);
    List<String> channelsIds = channelsUtils.getListIds(channels);
    Assert.assertEquals(3, channelsIds.size());

    List<String> includeIds = List.of(channelsIds.get(0));
    List<String> removeIds = List.of(channelsIds.get(1));
    List<String> excludeIds = List.of(channelsIds.get(2));
    LogUtils.logInfoMessage(
        "devicesIds: "
            + devicesIds
            + ", include_group: "
            + includeIds
            + ", exclude: "
            + excludeIds
            + ", remove_group: "
            + removeIds);

    new ChannelsClient(grpcChannelManager.getChannel(), false)
        .bulkDeviceUpdate(devicesIds, includeIds, excludeIds, removeIds);

    List<Channels> channelsAfterUpdate = channelsUtils.getDocumentsByIds(channelsIds);

    channelsAfterUpdate.forEach(
        channel -> {
          Assert.assertFalse(
              channel.getDistribution().getInclude().containsAll(platforms),
              "Channels platforms "
                  + channel.getDistribution().getInclude()
                  + "\n "
                  + "platforms for include "
                  + platforms);

          Assert.assertFalse(
              channel.getDistribution().getExclude().containsAll(platforms),
              "Channels platforms "
                  + channel.getDistribution().getExclude()
                  + "\n "
                  + "platforms for exclude "
                  + platforms);
        });
  }

  @Test
  @Description("BulkDeviceUpdate - update channels with existing devices, exclude group")
  @TmsLink("28500529")
  public void C28500529_TEST() {
    List<Devices> devices = devicesUtils.getDocuments(3);
    List<Channels> channels = channelsUtils.getDocuments(3);

    List<String> devicesIds = devicesUtils.getListDeviceIds(devices);
    List<String> platforms = devicesUtils.getListPlatforms(devices);
    List<String> channelsIds = channelsUtils.getListIds(channels);

    LogUtils.logInfoMessage("C22150155_TEST data");
    LogUtils.logInfoMessage("ChannelsIds list " + channelsIds);
    LogUtils.logInfoMessage("DevicesIds list " + devicesIds);
    LogUtils.logInfoMessage("Platforms list " + platforms);

    channelsClient.bulkDeviceUpdate(devicesIds, null, channelsIds, null);

    List<Channels> channelsAfterUpdate = channelsUtils.getDocumentsByIds(channelsIds);

    channelsAfterUpdate.forEach(
        channel ->
            Assert.assertTrue(
                channel.getDistribution().getExclude().containsAll(platforms),
                "Channels platforms "
                    + channel.getDistribution().getInclude()
                    + "\n "
                    + "platforms for exclude "
                    + platforms));
  }

  @Test
  @Description("BulkDeviceUpdate - empty device list")
  @TmsLink("28500530")
  public void C28500530_TEST() {
    try {
      channelsClient.bulkDeviceUpdate(Collections.emptyList(), null, null, null);
    } catch (StatusRuntimeException e) {
      Assert.assertEquals(e.getStatus().getCode().value(), 3);
      Assert.assertEquals(e.getMessage(), "INVALID_ARGUMENT: Devices cannot be empty.");
    }
  }

  @Test
  @Description("BulkDeviceUpdate - non existing id in device list")
  @TmsLink("28500531")
  public void C28500531_TEST() {
    try {
      channelsClient.bulkDeviceUpdate(
          Collections.singletonList(INVALID_ID_VALUE),
          Collections.singletonList(INVALID_ID_VALUE),
          Collections.singletonList(INVALID_ID_VALUE),
          null);
    } catch (StatusRuntimeException e) {
      Assert.assertEquals(e.getStatus().getCode().value(), 5);
      Assert.assertEquals(
          e.getMessage(),
          "NOT_FOUND: Channel ID is repeated in includeGroup, excludeGroup and removeGroup");
    }
  }

  @Test
  @Description("BulkDeviceUpdate - empty include list and exclude list")
  @TmsLink("28500532")
  public void C28500532_TEST() {
    Devices device = devicesUtils.getRandomDocument();

    try {
      channelsClient.bulkDeviceUpdate(Collections.singletonList(device.getId()), null, null, null);
    } catch (StatusRuntimeException e) {
      Assert.assertEquals(e.getStatus().getCode().value(), 3);
      Assert.assertEquals(
          e.getMessage(), "INVALID_ARGUMENT: includeGroup and excludeGroup cannot be empty.");
    }
  }

  @Test(
      expectedExceptions = RuntimeException.class,
      expectedExceptionsMessageRegExp =
          "NOT_FOUND: Channel ID is repeated in includeGroup, excludeGroup and removeGroup")
  @Description("BulkDeviceUpdate - include exclude and remove group with the same channelIds")
  @TmsLink("28500541")
  public void C28500541_TEST() {
    List<Devices> devices = devicesUtils.getDocuments(3);
    List<Channels> channels = channelsUtils.getDocuments(3);

    List<String> devicesIds = devicesUtils.getListDeviceIds(devices);
    List<String> channelsIds = channelsUtils.getListIds(channels);

    channelsClient.bulkDeviceUpdate(devicesIds, channelsIds, channelsIds, channelsIds);
  }

  @Test
  @Description("Bug verification - DAL Update ChannelManager to include customReference")
  @TmsLink("28500534")
  public void C28500534_TEST() {
    BasicDBObject query =
        new BasicDBObject(
            "customReferences",
            new BasicDBObject("$exists", true).append("$not", new BasicDBObject("$size", 0)));

    Channels channelWithReference = channelsUtils.getListChannels(query).get(0);

    tv.pluto.mongo.entities.channels.Channels mappedChannel =
        channelsUtils.mapGrpcObjectToPojo(
            channelsClient.getChannelById(channelWithReference.getId()).getDocument(),
            tv.pluto.mongo.entities.channels.Channels.class);

    Assert.assertEquals(channelWithReference, mappedChannel);
  }

  @Test
  @Description("GetAllPagedChannelLite - valid request with AND")
  @TmsLink("28500440")
  public void C28500440_TEST() {
    Channels channels = channelsUtils.getRandomDocument();
    int total = 0;

    while (channels.getCategory().endsWith(" ") && total < 10) {
      LogUtils.logInfoMessage(
          "Data issue in category: " + channels.getCategory() + ", ChannelId: " + channels.getId());
      channels = channelsUtils.getRandomDocument();
      total++;
    }

    LogUtils.logInfoMessage("Channel id: " + channels.getId());
    Integer limit = 10;
    Integer offset = 0;
    List<GetAllPagedSort> grpcSort = channelsClient.singleListSortObject("_id", 1);

    List<Filter> listFilter =
        List.of(
            channelsClient.getFilter("_id", channels.getId(), "", "AND"),
            channelsClient.getFilter("activeRegion", channels.getActiveRegion(), "", "AND"),
            channelsClient.getFilter("category", channels.getCategory(), "", "AND"),
            channelsClient.getFilter("name", channels.getName(), "", "AND"));

    GetAllPagedChannelLiteResponse allPagedChannelLite =
        channelsClient.getAllPagedChannelLite(limit, offset, grpcSort, listFilter, true);

    List<ChannelLite> documentsList = allPagedChannelLite.getDocumentsList();

    Assert.assertEquals(1, documentsList.size());

    ChannelLite lite = documentsList.get(0);
    Assert.assertEquals(lite.getId(), channels.getId());
    Assert.assertEquals(lite.getActiveRegion(), channels.getActiveRegion());
    Assert.assertEquals(lite.getArchived(), channels.getArchived());
    Assert.assertEquals(lite.getPublished(), channels.getPublished());
    Assert.assertEquals(lite.getCategory(), channels.getCategory());
    Assert.assertEquals(1, allPagedChannelLite.getMetadata().getTotalItems());
    Assert.assertEquals(offset, allPagedChannelLite.getMetadata().getCurrentOffset());
  }

  @Test(dataProvider = "is-true-false")
  @TmsLink("28500441")
  @Description("GetAllPagedChannelLite - valid request with AND for category and activeRegion")
  public void C28500441_TEST(boolean isTrue) {
    Channels channels = channelsUtils.getRandomDocument();
    Integer limit = 10;
    Integer offset = 0;
    List<GetAllPagedSort> grpcSort = channelsClient.singleListSortObject("_id", 1);

    List<Filter> listFilter =
        List.of(
            channelsClient.getFilter("activeRegion", channels.getActiveRegion(), "", "AND"),
            channelsClient.getFilter("category", channels.getCategory(), "", "AND"));

    GetAllPagedChannelLiteResponse allPagedChannelLite =
        channelsClient.getAllPagedChannelLite(limit, offset, grpcSort, listFilter, isTrue);

    List<ChannelLite> documentsList = allPagedChannelLite.getDocumentsList();

    Assert.assertTrue(documentsList.size() > 0 && documentsList.size() <= 10);

    documentsList.forEach(
        doc -> {
          Assert.assertEquals(doc.getActiveRegion(), channels.getActiveRegion());
          Assert.assertEquals(doc.getCategory(), channels.getCategory().trim());
        });

    BasicDBObject query =
        new BasicDBObject("category", channels.getCategory().trim())
            .append("activeRegion", channels.getActiveRegion());
    int dbChannelsSize = channelsUtils.getListChannels(query).size();

    if (isTrue) {
      Assert.assertTrue(documentsList.size() <= dbChannelsSize);
      Assert.assertTrue(dbChannelsSize >= allPagedChannelLite.getMetadata().getTotalItems());
    } else Assert.assertEquals(dbChannelsSize, allPagedChannelLite.getMetadata().getTotalItems());

    Assert.assertEquals(offset, allPagedChannelLite.getMetadata().getCurrentOffset());
  }

  @Test(dataProvider = "is-true-false")
  @TmsLink("28500442")
  @Description("GetAllPagedChannelLite - valid request with OR for category and activeRegion")
  public void C28500442_TEST(boolean isTrue) {
    Channels channels = channelsUtils.getRandomDocument();
    Integer limit = 10;
    Integer offset = 0;
    List<GetAllPagedSort> grpcSort = channelsClient.singleListSortObject("_id", 1);

    List<Filter> listFilter =
        List.of(
            channelsClient.getFilter("activeRegion", channels.getActiveRegion(), "", "OR"),
            channelsClient.getFilter("category", channels.getCategory(), "", "OR"));

    GetAllPagedChannelLiteResponse allPagedChannelLite =
        channelsClient.getAllPagedChannelLite(limit, offset, grpcSort, listFilter, isTrue);

    List<ChannelLite> documentsList = allPagedChannelLite.getDocumentsList();

    Assert.assertTrue(documentsList.size() > 0 && documentsList.size() <= 10);

    documentsList.forEach(
        doc -> {
          boolean isActive = doc.getActiveRegion().equals(channels.getActiveRegion());
          boolean isCategory = doc.getCategory().equals(channels.getCategory());

          Assert.assertTrue(isActive || isCategory);
        });

    List<BasicDBObject> mongoOrList =
        Arrays.asList(
            new BasicDBObject("category", channels.getCategory()),
            new BasicDBObject("activeRegion", channels.getActiveRegion()));

    BasicDBObject query = new BasicDBObject("$or", mongoOrList);
    int dbChannelsSize = channelsUtils.getListChannels(query).size();

    if (isTrue) {
      Assert.assertTrue(documentsList.size() <= dbChannelsSize);
      Assert.assertTrue(dbChannelsSize >= allPagedChannelLite.getMetadata().getTotalItems());
    } else Assert.assertEquals(dbChannelsSize, allPagedChannelLite.getMetadata().getTotalItems());

    Assert.assertEquals(offset, allPagedChannelLite.getMetadata().getCurrentOffset());
  }

  @Test
  @Description("GetChannelQueue filter with rating +")
  @TmsLink("28500574")
  public void C28500574_TEST() {
    // Any episode with rating +
    String rating = "+12";
    Episodes episode = episodeUtils.getDocumentByFieldAndValue("rating", rating);
    String channelId = episode.getChannels().get(0).toString();

    tv.pluto.ip.dal.channels.Channels.GetChannelQueueRequest request =
        tv.pluto.ip.dal.channels.Channels.GetChannelQueueRequest.newBuilder()
            .setChannelId(channelId)
            .setRating(episode.getRating())
            .build();

    tv.pluto.ip.dal.channels.Channels.GetChannelQueueResponse response =
        channelsClient.getChannelQueueRequest(request);

    Assert.assertFalse(response.getDocumentsList().isEmpty());
    response
        .getDocumentsList()
        .forEach(document -> Assert.assertEquals(rating, document.getRating()));
  }

  @Test
  @Description("GetChannelQueue a series type field exists")
  @TmsLink("28500582")
  public void C28500582_TEST() {
    Channels channels = channelsUtils.getExistsAndSizeNotZero("episodesQueue");

    tv.pluto.ip.dal.channels.Channels.GetChannelQueueRequest request =
        tv.pluto.ip.dal.channels.Channels.GetChannelQueueRequest.newBuilder()
            .setChannelId(channels.getId())
            .build();
    tv.pluto.ip.dal.channels.Channels.GetChannelQueueResponse response;
    try {
      response = channelsClient.getChannelQueueRequest(request);
      response.getDocumentsList().get(0).getSeries().getType();
    } catch (RuntimeException e) {
      boolean isTrue =
          e.getMessage().equals("NOT_FOUND: Channel document for requested ID not found")
              || e.getMessage().equals("No type fields in series");
      Assert.assertTrue(isTrue);
    }
  }

  @Test
  @Description("GetChannelQueue - invalid channel format")
  @TmsLink("28500563")
  public void C28500563_TEST() {
    try {
      channelsClient.getChannelQueue("testDal");
      Assert.fail("No exceptions have been received");
    } catch (RuntimeException e) {
      Assert.assertEquals(
          e.getMessage(),
          "INTERNAL: Cast to ObjectId failed for value \"testDal\" (type string) "
              + "at path \"_id\" for model \"Channel\"");
    }
  }

  @Test
  @Description("GetChannelQueue - invalid channel")
  @TmsLink("28500564")
  public void C28500564_TEST() {
    try {
      channelsClient.getChannelQueue("00000f7bb6f26b0000000000");
      Assert.fail("No exceptions have been received");
    } catch (RuntimeException e) {
      Assert.assertTrue(e.getMessage().contains("INTERNAL: Cannot read properties of undefined"));
    }
  }

  @DataProvider(name = "regexSearch")
  public Object[][] regexDataProvider() {
    String regexName = regexChannel.getName().trim();
    LogUtils.logInfoMessage("Regex data provider: " + regexName);
    return CommonUtils.getRegexpSearch(regexName);
  }

  @Test(dataProvider = "regexSearch")
  @TmsLink("28500502")
  @Description("GetAllPaged - get channels by name regex")
  public void C28500502_TEST(String regexStr) {
    ChannelsClient channelsClient = new ChannelsClient(grpcChannelManager.getChannel(), false);

    LogUtils.logInfoMessage(
        "C23866845_TEST: Document name = "
            + regexChannel.getName()
            + " , Regex string = "
            + regexStr
            + ", id: "
            + regexChannel.getId());

    List<Filter> listFilter = List.of(channelsClient.getFilter("name", regexStr, "string", null));

    GetAllPagedResponse response = channelsClient.getAllPagedRegex(0, 0, null, listFilter, true);
    LogUtils.logInfoMessage("Response: " + response);
    Assert.assertNotNull(response.getDocumentsList());

    List<Channels> mappedChannelsList =
        channelsUtils.mapGrpcObjectsToPojo(response.getDocumentsList(), Channels.class);

    Assert.assertTrue(
        mappedChannelsList.stream()
            .anyMatch(channel -> channel.getId().equals(regexChannel.getId())));

    List<Channels> channelsMongo = channelsUtils.getDocumentsByRegex("name", regexStr);
    channelsMongo.forEach(chan -> chan.setMainCategories(null));
    mappedChannelsList.forEach(chan -> chan.setMainCategories(null));

    channelsMongo.sort(Comparator.comparing(Channels::getId));
    mappedChannelsList.sort(Comparator.comparing(Channels::getId));

    Assert.assertEquals(
        channelsMongo,
        mappedChannelsList,
        "Mongo and gRPC lists are not equal for regex " + regexStr);
  }

  @Test
  @Description("GetById - number 0")
  @TmsLink("28500565")
  public void C28500565_TEST() {
    BasicDBObject query = new BasicDBObject();
    query.put("number", 0);
    List<Channels> channels = channelsUtils.getDocuments(query, 1);
    tv.pluto.ip.dal.channels.Channels.Channel channel =
        channelsClient.getChannelById(channels.get(0).getId()).getDocument();
    Assert.assertEquals(0, channel.getNumber());
  }

  @Test
  @Description("GetAllPaged - filter with number 0 and id")
  @TmsLink("28500566")
  public void C28500566_TEST() {
    ChannelsClient channelsClient = new ChannelsClient(grpcChannelManager.getChannel(), false);
    int testNumber = 0;
    int limit = 10;
    int offset = 0;

    BasicDBObject query = new BasicDBObject();
    query.put("number", 0);
    List<Channels> listChannels = channelsUtils.getDocuments(query, 1);
    Channels channels = listChannels.get(0);
    Assert.assertEquals(testNumber, channels.getNumber());

    Filter buildNumber =
        Filter.newBuilder()
            .setField("number")
            .setValue(channels.getNumber().toString())
            .setType("number")
            .setOperator("AND")
            .build();
    Filter buildId =
        Filter.newBuilder()
            .setField("_id")
            .setValue(channels.getId())
            .setType("string")
            .setOperator("AND")
            .build();
    List<Filter> listFilters = List.of(buildNumber, buildId);

    LogUtils.logInfoMessage("Request: " + listFilters);
    GetAllPagedResponse response =
        channelsClient.getAllPaged(limit, offset, null, listFilters, true, null);
    LogUtils.logInfoMessage("Response: " + response);
    Assert.assertNotNull(response);

    Assert.assertEquals(testNumber, response.getDocumentsList().get(testNumber).getNumber());
    Assert.assertEquals(1, response.getMetadata().getTotalItems());
    Assert.assertEquals(offset, response.getMetadata().getCurrentOffset());
  }

  @Test
  @Description("GetAllPaged - filter with number 0")
  @TmsLink("28500567")
  public void C28500567_TEST() {
    int testNumber = 0;
    int limit = 5;
    int offset = 0;

    BasicDBObject query = new BasicDBObject();
    query.put("number", 0);
    List<Channels> listChannels = channelsUtils.getDocuments(query, 5);

    Filter buildNumber =
        Filter.newBuilder()
            .setField("number")
            .setValue(String.valueOf(testNumber))
            .setType("number")
            .build();
    List<Filter> listFilters = List.of(buildNumber);

    LogUtils.logInfoMessage("ListFilters: " + listFilters);
    GetAllPagedResponse response =
        new ChannelsClient(grpcChannelManager.getChannel(), false)
            .getAllPaged(limit, offset, null, listFilters, true, null);
    Assert.assertNotNull(response);
    response.getDocumentsList().forEach(doc -> Assert.assertEquals(testNumber, doc.getNumber()));

    Assert.assertEquals(listChannels.size(), response.getMetadata().getTotalItems());
    Assert.assertEquals(offset, response.getMetadata().getCurrentOffset());
  }

  @Test
  @Description("GetAllPaged - filter with number 0 OR id")
  @TmsLink("28500568")
  public void C28500568_TEST() {
    ChannelsClient channelsClient = new ChannelsClient(grpcChannelManager.getChannel(), false);
    int testNumber = 0;
    int limit = 10;
    int offset = 0;

    BasicDBObject query = new BasicDBObject();
    query.put("number", 0);
    List<Channels> listChannels = channelsUtils.getDocuments(query, limit);
    Channels channels = listChannels.get(0);
    Assert.assertEquals(testNumber, channels.getNumber());

    Filter buildNumber =
        Filter.newBuilder()
            .setField("number")
            .setValue(channels.getNumber().toString())
            .setType("number")
            .setOperator("OR")
            .build();
    Filter buildId =
        Filter.newBuilder()
            .setField("_id")
            .setValue(channels.getId())
            .setType("string")
            .setOperator("OR")
            .build();
    List<Filter> listFilters = List.of(buildNumber, buildId);

    GetAllPagedResponse response =
        channelsClient.getAllPaged(limit, offset, null, listFilters, true, null);
    Assert.assertNotNull(response);
    response.getDocumentsList().forEach(doc -> Assert.assertEquals(testNumber, doc.getNumber()));

    Assert.assertEquals(listChannels.size(), response.getMetadata().getTotalItems());
    Assert.assertEquals(offset, response.getMetadata().getCurrentOffset());
  }

  @Test
  @Description("GetAllPaged - filter activeRegion with OR")
  @TmsLink("28500569")
  public void C28500569_TEST() {
    ChannelsClient channelsClient = new ChannelsClient(grpcChannelManager.getChannel(), false);
    int limit = 99_999;
    int offset = 0;
    String frRegion = "fr";
    String esRegion = "es";

    List<BasicDBObject> mongoOrList =
        Arrays.asList(
            new BasicDBObject("activeRegion", frRegion),
            new BasicDBObject("activeRegion", esRegion));

    BasicDBObject query = new BasicDBObject();
    query.put("$or", mongoOrList);

    int dbSize = channelsUtils.getDocuments(query, limit).size();

    Filter buildNumber =
        Filter.newBuilder()
            .setField("activeRegion")
            .setValue(frRegion)
            .setType("string")
            .setOperator("OR")
            .build();

    Filter buildId =
        Filter.newBuilder()
            .setField("activeRegion")
            .setValue(esRegion)
            .setType("string")
            .setOperator("OR")
            .build();

    List<Filter> listFilters = List.of(buildNumber, buildId);

    GetAllPagedResponse response =
        channelsClient.getAllPaged(limit, offset, null, listFilters, true, null);
    response
        .getDocumentsList()
        .forEach(
            doc -> {
              boolean isActive =
                  doc.getActiveRegion().equals(frRegion) || doc.getActiveRegion().equals(esRegion);
              Assert.assertTrue(isActive);
            });

    Assert.assertEquals(dbSize, response.getMetadata().getTotalItems());
    Assert.assertEquals(dbSize, response.getDocumentsList().size());
    Assert.assertEquals(response.getMetadata().getCurrentOffset(), offset);
  }

  @Test
  @Description("GetAllPaged - populated mainCategory")
  @TmsLink("28500570")
  public void C28500570_TEST() {
    ChannelsClient channelsClient = new ChannelsClient(grpcChannelManager.getChannel(), false);
    Channels channels = channelsUtils.getRandomDocumentWithTheFieldSize("categories", 1, 2);
    tv.pluto.mongo.entities.maincategories.MainCategories mainCategories =
        mainCategoriesUtils.getDocumentById(channels.getCategories().get(0).getCatId());

    List<Filter> listFilter = List.of(channelsClient.getFilter("_id", channels.getId(), "", null));

    GetAllPagedResponse response = channelsClient.getAllPaged(5, 0, null, listFilter, true, null);
    Assert.assertNotNull(response);
    Assert.assertEquals(1, response.getDocumentsCount());
    Assert.assertEquals(1, response.getDocumentsList().size());

    tv.pluto.mongo.entities.maincategories.MainCategories mainCategoriesGrpc =
        channelsUtils.mapGrpcObjectToPojo(
            response.getDocumentsList().get(0).getMainCategories(0),
            tv.pluto.mongo.entities.maincategories.MainCategories.class);

    tv.pluto.mongo.entities.maincategories.MainCategories grpcMainCategory =
        channelsUtils.mapGrpcObjectToPojo(
            mainCategoriesGrpc, tv.pluto.mongo.entities.maincategories.MainCategories.class);
    grpcMainCategory.setHideMainCategory(false);
    mainCategories.setHideMainCategory(false);

    Assert.assertEquals(grpcMainCategory, mainCategories);
  }

  @Test(dataProvider = "sort-values")
  @TmsLink("28500571")
  @Description("GetAllPaged - populated mainCategory sort by id")
  public void C28500571_TEST(int sort) {
    ChannelsClient channelsClient = new ChannelsClient(grpcChannelManager.getChannel(), false);
    Boolean isPublished = false;
    String activeRegion = "es";
    BasicDBObject query = new BasicDBObject("categories", new BasicDBObject("$exists", true));
    query.append("published", isPublished).append("activeRegion", activeRegion);

    List<Channels> channels = channelsUtils.getDocuments(query, 1000);
    int dbChannelsSize = channels.size();

    LogUtils.logInfoMessage("DB channels size: " + dbChannelsSize);
    Assert.assertTrue(dbChannelsSize > 0);

    List<GetAllPagedSort> grpcSort = channelsClient.singleListSortObject("_id", sort);

    Filter filterPublished =
        channelsClient.getFilter("published", isPublished.toString(), "boolean", "AND");
    Filter filterActiveRegion = channelsClient.getFilter("activeRegion", activeRegion, "", "AND");
    List<Filter> listFilter = List.of(filterPublished, filterActiveRegion);
    LogUtils.logInfoMessage("List filters: " + listFilter);

    GetAllPagedResponse response =
        channelsClient.getAllPaged(9999, 0, grpcSort, listFilter, true, null);
    Assert.assertEquals(dbChannelsSize, response.getDocumentsCount());
    Assert.assertEquals(dbChannelsSize, response.getDocumentsList().size());

    List<String> dbListIds = channels.stream().map(c -> c.getId()).collect(Collectors.toList());
    if (sort == 1) dbListIds.sort(Comparator.naturalOrder());
    else dbListIds.sort(Comparator.reverseOrder());

    List<String> grpsChannelIds =
        response.getDocumentsList().stream().map(c -> c.getId()).collect(Collectors.toList());

    Assert.assertEquals(grpsChannelIds, dbListIds);

    response
        .getDocumentsList()
        .forEach(
            document -> {
              Assert.assertEquals(document.getPublished(), isPublished);
              Assert.assertEquals(document.getActiveRegion(), activeRegion);
              Assert.assertTrue(document.getMainCategoriesCount() > 0);
            });
  }

  @Test
  @Description("GetAllPagedChannelLite - sort by name numericOrdering: true")
  @TmsLink("28500572")
  public void C28500572_TEST() {
    int limit = 10;
    int sort = 1;
    String activeRegion = "us";
    List<GetAllPagedSort> grpcSort = channelsClient.singleListSortObject("name", sort);
    List<Filter> listFilter =
        List.of(channelsClient.getFilter("activeRegion", activeRegion, "", "AND"));

    GetAllPagedChannelLiteResponse allPagedChannelLite =
        channelsClient.getAllPagedChannelLite(limit, 0, grpcSort, listFilter, true);

    List<String> grpcNameList =
        allPagedChannelLite.getDocumentsList().stream()
            .map(ChannelLite::getName)
            .collect(Collectors.toList());
    Assert.assertTrue(grpcNameList.size() > 0 && grpcNameList.size() <= limit);

    BasicDBObject query = new BasicDBObject("activeRegion", activeRegion);
    Bson sorting = orderBy(ascending("name"));

    List<Channels> mongoChannels =
        channelsUtils.getChannelsQueryWithCollation(limit, 0, sorting, query, sort);
    List<String> listMongoChannels =
        mongoChannels.stream().map(Channels::getName).collect(Collectors.toList());

    Assert.assertEquals(listMongoChannels, grpcNameList);
  }

  @Test
  @Description("GetAllPagedChannelLite - sort by name numericOrdering: false")
  @TmsLink("28500573")
  public void C28500573_TEST() {
    int limit = 100;
    int sort = -1;
    String activeRegion = "us";
    List<GetAllPagedSort> grpcSort = channelsClient.singleListSortObject("name", sort);
    List<Filter> listFilter =
        List.of(channelsClient.getFilter("activeRegion", activeRegion, "", "AND"));

    GetAllPagedChannelLiteResponse allPagedChannelLite =
        channelsClient.getAllPagedChannelLite(limit, 0, grpcSort, listFilter, true);

    List<String> grpcNameList =
        allPagedChannelLite.getDocumentsList().stream()
            .map(ChannelLite::getName)
            .collect(Collectors.toList());
    Assert.assertTrue(grpcNameList.size() > 0 && grpcNameList.size() <= limit);

    BasicDBObject query = new BasicDBObject("activeRegion", activeRegion);
    Bson sorting = orderBy(descending("name"));

    List<Channels> mongoChannels =
        channelsUtils.getChannelsQueryWithCollation(limit, 0, sorting, query, sort);
    List<String> listMongoChannels =
        mongoChannels.stream().map(Channels::getName).collect(Collectors.toList());

    Assert.assertEquals(listMongoChannels, grpcNameList);
  }

  @Test(dataProvider = "is-true-false")
  @TmsLink("28500443")
  @Description("GetCFaasIntegratedChannel - getAll data")
  public void C28500443_TEST(boolean isTrue) {
    BasicDBObject query = new BasicDBObject();
    query.put(
        "cfaasIntegration.sourceId.key", new BasicDBObject("$exists", true).append("$ne", ""));
    query.put("cfaasIntegration.enabled", isTrue);
    query.put("archived", new BasicDBObject("$ne", true));

    List<Channels> listChannels = channelsUtils.getListChannels(query);
    Channels channel = listChannels.get(0);
    String channelId = channel.getId();
    CfaasIntegration cfaasIntegration = channel.getCfaasIntegration();

    tv.pluto.ip.dal.channels.Channels.SourceId.Builder builder =
        tv.pluto.ip.dal.channels.Channels.SourceId.newBuilder()
            .setKey(cfaasIntegration.getSourceId().getKey())
            .setValue(cfaasIntegration.getSourceId().getValue());

    tv.pluto.ip.dal.channels.Channels.CfaasIntegrationParams.Builder cfaasIntegrationBuilder =
        tv.pluto.ip.dal.channels.Channels.CfaasIntegrationParams.newBuilder()
            .setClipId(cfaasIntegration.getClipId())
            .setEnabled(cfaasIntegration.getEnabled())
            .setSourceId(builder);

    tv.pluto.ip.dal.channels.Channels.GetCFaasIntegratedChannelRequest request =
        tv.pluto.ip.dal.channels.Channels.GetCFaasIntegratedChannelRequest.newBuilder()
            .setAutoEpgSource(channel.getAutoEpgSource())
            .setCfaasIntegration(cfaasIntegrationBuilder)
            .setProjection(channelsClient.getCFaasProjection(true))
            .build();

    LogUtils.logInfoMessage("Request: " + request);

    GetCFaasIntegratedChannelResponse cFaasIntegratedChannel =
        channelsClient.getCfaasIntegratedChannel(request);

    tv.pluto.ip.dal.channels.Channels.GetCFaasIntegratedChannel document =
        cFaasIntegratedChannel.getDocumentsList().stream()
            .filter(c -> c.getId().equals(channelId))
            .findFirst()
            .orElseThrow(
                () ->
                    new StatusRuntimeException(
                        io.grpc.Status.NOT_FOUND.withDescription(
                            "Channel document for requested ID not found")));

    Assert.assertEquals(channel.getAutoEpgSource(), document.getAutoEpgSource());
    Assert.assertEquals(cfaasIntegration.getEnabled(), document.getCfaasIntegration().getEnabled());
    Assert.assertEquals(cfaasIntegration.getClipId(), document.getCfaasIntegration().getClipId());
    Assert.assertEquals(
        cfaasIntegration.getSourceId().getKey(),
        document.getCfaasIntegration().getSourceId().getKey());
    Assert.assertEquals(
        cfaasIntegration.getSourceId().getValue(),
        document.getCfaasIntegration().getSourceId().getValue());
  }

  @Test(
      expectedExceptions = StatusRuntimeException.class,
      expectedExceptionsMessageRegExp =
          "INVALID_ARGUMENT: CfaasIntegration.source_id.key must be provided.")
  @Description("GetCFaasIntegratedChannel - no CfaasIntegration.source_id.key")
  @TmsLink("28500444")
  public void C28500444_TEST() {
    BasicDBObject query = new BasicDBObject();
    query.put(
        "cfaasIntegration.sourceId.key", new BasicDBObject("$exists", true).append("$ne", ""));
    query.put("archived", new BasicDBObject("$ne", true));

    Channels channel = channelsUtils.getListChannels(query).get(0);
    String channelId = channel.getId();
    String testClipId = channel.getCfaasIntegration().getClipId();

    Assert.assertNotNull(channelsUtils.getDocumentById(channelId));

    String autoEpgSource = "cfaas";
    boolean isEnabled = true;

    // if no data in db run update. To do a logic to check if no data in db then update
    //        channelsUtils.updateOne(filter, update);

    tv.pluto.ip.dal.channels.Channels.CfaasIntegrationParams cfaasIntegration =
        tv.pluto.ip.dal.channels.Channels.CfaasIntegrationParams.newBuilder()
            .setEnabled(isEnabled)
            .setClipId(testClipId)
            .build();

    tv.pluto.ip.dal.channels.Channels.GetCFaasIntegratedChannelRequest request =
        tv.pluto.ip.dal.channels.Channels.GetCFaasIntegratedChannelRequest.newBuilder()
            .setAutoEpgSource(autoEpgSource)
            .setCfaasIntegration(cfaasIntegration)
            .build();

    channelsClient.getCfaasIntegratedChannel(request);
  }

  @Test(
      expectedExceptions = StatusRuntimeException.class,
      expectedExceptionsMessageRegExp = "NOT_FOUND: Channel document for requested ID not found")
  @Description("GetCFaasIntegratedChannel - for channelId without data")
  @TmsLink("28500445")
  public void C28500445_TEST() {
    tv.pluto.ip.dal.channels.Channels.SourceId sourceId =
        tv.pluto.ip.dal.channels.Channels.SourceId.newBuilder()
            .setValue("test")
            .setKey("key")
            .build();
    tv.pluto.ip.dal.channels.Channels.CfaasIntegrationParams cfaasIntegration =
        tv.pluto.ip.dal.channels.Channels.CfaasIntegrationParams.newBuilder()
            .setEnabled(false)
            .setClipId("55b285cd2665de2745510000")
            .setSourceId(sourceId)
            .build();

    tv.pluto.ip.dal.channels.Channels.GetCFaasIntegratedChannelRequest request =
        tv.pluto.ip.dal.channels.Channels.GetCFaasIntegratedChannelRequest.newBuilder()
            .setAutoEpgSource("test")
            .setCfaasIntegration(cfaasIntegration)
            .build();

    channelsClient.getCfaasIntegratedChannel(request);
  }

  @Test
  @Description("GetChannelQueue - valid request")
  @TmsLink("28500562")
  public void C28500562_TEST() {
    Channels channels = channelsUtils.getExistsAndSizeNotZero("episodesQueue");
    LogUtils.logInfoMessage("channelId: " + channels.getId());

    List<String> episodesQueueList =
        channels.getEpisodesQueue().stream()
            .map(EpisodesQueue::getEpisode)
            .collect(Collectors.toList());
    Assert.assertFalse(episodesQueueList.isEmpty());
    LogUtils.logInfoMessage("episodesQueueList: " + episodesQueueList);

    List<Episodes> episodeAllListDb = episodeUtils.getDocumentsByIds(episodesQueueList);
    List<Episodes> episodeListDb =
        episodeAllListDb.stream().filter(e -> e.getPublished()).collect(Collectors.toList());

    if (episodeListDb.isEmpty()) {
      try {
        channelsClient.getChannelQueue(channels.getId()).getDocumentsList();
      } catch (StatusRuntimeException e) {
        Assert.assertEquals(
            e.getMessage(), "NOT_FOUND: Channel document for requested ID not found");
      }
    } else {
      List<tv.pluto.ip.dal.channels.Channels.Episode> episodesList =
          channelsClient.getChannelQueue(channels.getId()).getDocumentsList();
      Assert.assertEquals(episodesList.size(), episodeListDb.size());

      episodeListDb.forEach(
          episode -> {
            tv.pluto.ip.dal.channels.Channels.Episode episodeGrpc =
                episodesList.stream()
                    .filter(e -> e.getName().equals(episode.getName()))
                    .collect(Collectors.toList())
                    .get(0);

            Date dateNow = new Date();
            boolean isAvailabilityWindows =
                episode.getAvailabilityWindows().getLinear().stream()
                    .anyMatch(
                        linear ->
                            linear.getStartDate().before(dateNow)
                                && linear.getEndDate().after(dateNow));

            Assert.assertEquals(
                isAvailabilityWindows, episodeGrpc.getHasLinearAvailabilityWindows());

            List<String> listClips =
                episode.getSources().stream().map(Source::getClip).collect(Collectors.toList());
            List<Clips> listMongoDbClips = clipsUtils.getDocumentsByIds(listClips);
            boolean isContentStatus =
                listMongoDbClips.stream().allMatch(clip -> clip.getContentStatus().equals("ready"));
            Assert.assertEquals(isContentStatus, episodeGrpc.getAllClipsReady());

            boolean hasClipWithEmptySources =
                listMongoDbClips.stream().anyMatch(clip -> clip.getSources().size() == 0);
            Assert.assertEquals(hasClipWithEmptySources, episodeGrpc.getHasClipWithEmptySources());

            long providerSize =
                listMongoDbClips.stream().map(Clips::getProvider).distinct().count();
            long countClipsInSources =
                episode.getSources().stream().filter(s -> !s.getClip().isEmpty()).count();

            if (!episode.getIsFeed() && providerSize <= 1) {
              List<String> listSourceClips =
                  episode.getSources().stream().map(Source::getClip).collect(Collectors.toList());
              List<Clips> listClipsSources = clipsUtils.getDocumentsByIds(listSourceClips);
              if (listSourceClips.isEmpty()
                  || listClipsSources.stream().allMatch(c -> c.getProvider().isEmpty()))
                Assert.assertFalse(episodeGrpc.getHasUniqueProvider());
            } else if (countClipsInSources == 0)
              Assert.assertFalse(episodeGrpc.getHasUniqueProvider());
            else {
              List<String> listSourceClips =
                  episode.getSources().stream()
                      .map(Source::getClip)
                      .distinct()
                      .collect(Collectors.toList());
              List<Clips> listObjectClips = clipsUtils.getDocumentsByIds(listSourceClips);
              Set<String> uniqueProviders =
                  listObjectClips.stream().map(Clips::getProvider).collect(Collectors.toSet());

              if (uniqueProviders.size() == 1) {
                boolean allJwPlatform = uniqueProviders.iterator().next().equals("jwplatform");
                Assert.assertEquals(episodeGrpc.getHasUniqueProvider(), allJwPlatform);
              } else {
                Assert.assertFalse(episodeGrpc.getHasUniqueProvider());
              }
            }

            if (episode.getIsFeed() && countClipsInSources == 0)
              Assert.assertFalse(episodeGrpc.getHasMixedProviderWith());

            // availabilityWindows.linear
            List<Window> linearWindow = episode.getAvailabilityWindows().getLinear();

            if (linearWindow.isEmpty()) Assert.assertFalse(episodeGrpc.getIsAvailableNow());
            else {
              boolean isAvailable =
                  linearWindow.stream()
                      .anyMatch(
                          linear ->
                              linear.getStartDate().before(dateNow)
                                  && linear.getEndDate().after(dateNow));
              Assert.assertTrue(isAvailable);
            }

            Assert.assertEquals(episodeGrpc.getName(), episode.getName());
            Assert.assertEquals(episodeGrpc.getRating(), episode.getRating());
            Assert.assertEquals(episodeGrpc.getSeason(), episode.getSeason());
            Assert.assertEquals(episodeGrpc.getNumber(), episode.getNumber());
            Assert.assertEquals(episodeGrpc.getTmsid(), episode.getTmsid());
            Assert.assertEquals(episodeGrpc.getDuration(), episode.getDuration());
            Assert.assertEquals(episodeGrpc.getAllotment(), episode.getAllotment());
            Assert.assertEquals(episodeGrpc.getFlagged(), episode.getFlagged());
            Assert.assertEquals(episodeGrpc.getFeatured(), episode.getFeatured());
            Assert.assertEquals(episodeGrpc.getSourcesCount(), episode.getSources().size());

            Set<String> ageRangeIds =
                episodeGrpc.getAgeRangeList().stream()
                    .map(doc -> doc.getId())
                    .collect(Collectors.toSet());
            Set<String> ageRangeIdsEpisode =
                episode.getAgeRange().stream().map(ObjectId::toString).collect(Collectors.toSet());

            Assert.assertEquals(ageRangeIds, ageRangeIdsEpisode);
            Assert.assertNotNull(episodeGrpc.getLastAired());
            Assert.assertNotNull(episodeGrpc.getSeries());
            Assert.assertNotNull(episodeGrpc.getAvailabilityWindows());
            Assert.assertNotNull(episodeGrpc.getUpdatedAt());
            Assert.assertNotNull(episodeGrpc.getSources(0).getClip().getContentStatus());
            Assert.assertNotNull(episodeGrpc.getSources(0).getClip().getAuthor());
          });
    }
  }

  @Test(dataProvider = "sort-values")
  @TmsLink("28500576")
  @Description("GetChannelQueue - sort by updatedAt")
  public void C28500576_TEST(int sort) {
    Channels channelsDb = channelsUtils.getExistsAndSizeNotZero("episodesQueue");
    List<String> listEpisodes =
        channelsDb.getEpisodesQueue().stream()
            .map(e -> e.getEpisode())
            .collect(Collectors.toList());
    List<Episodes> listAllEpisode = episodeUtils.getDocumentsByIds(listEpisodes);
    List<Episodes> listPublishedEpisode =
        listAllEpisode.stream().filter(Episodes::getPublished).collect(Collectors.toList());

    GetAllPagedSort updatedAt =
        GetAllPagedSort.newBuilder().setField("updatedAt").setValue(sort).build();

    tv.pluto.ip.dal.channels.Channels.GetChannelQueueRequest request =
        tv.pluto.ip.dal.channels.Channels.GetChannelQueueRequest.newBuilder()
            .setChannelId(channelsDb.getId())
            .addSort(updatedAt)
            .build();

    if (listPublishedEpisode.isEmpty()) {
      try {
        channelsClient.getChannelQueueRequest(request);
      } catch (StatusRuntimeException e) {
        Assert.assertEquals(
            e.getMessage(), "NOT_FOUND: Channel document for requested ID not found");
      }
    } else {
      tv.pluto.ip.dal.channels.Channels.GetChannelQueueResponse channelQueue =
          channelsClient.getChannelQueueRequest(request);
      Assert.assertTrue(channelQueue.getMetadata().getTotalItems() > 0);
      Assert.assertEquals(channelQueue.getMetadata().getTotalItems(), listPublishedEpisode.size());

      List<tv.pluto.ip.dal.channels.Channels.Episode> grpcListEpisodes =
          channelQueue.getDocumentsList();
      List<tv.pluto.ip.dal.channels.Channels.Episode> sortedList =
          new ArrayList<>(grpcListEpisodes);

      if (sort == 1)
        sortedList.sort(
            Comparator.comparing(
                tv.pluto.ip.dal.channels.Channels.Episode::getUpdatedAt,
                Comparator.naturalOrder()));
      else
        sortedList.sort(
            Comparator.comparing(
                tv.pluto.ip.dal.channels.Channels.Episode::getUpdatedAt,
                Comparator.reverseOrder()));

      Assert.assertEquals(sortedList, grpcListEpisodes);
    }
  }

  @Test(expectedExceptions = StatusRuntimeException.class)
  @Description("GetChannelQueue - error when no channel found")
  @TmsLink("28500578")
  public void C28500578_TEST() {
    tv.pluto.ip.dal.channels.Channels.GetChannelQueueRequest request =
        tv.pluto.ip.dal.channels.Channels.GetChannelQueueRequest.newBuilder()
            .setChannelId("00000f7bb6f26ba1cd000000")
            .build();

    channelsClient.getChannelQueueRequest(request);
  }

  @Test
  @Description("GetChannelQueue - return a tags array")
  @TmsLink("28500577")
  public void C28500577_TEST() {
    Channels channelsDb = channelsUtils.getChannelsEpisodesQueueInEpisodes();

    if (channelsDb == null) channelsDb = channelsUtils.getRandomDocument();

    LogUtils.logInfoMessage("channelsDb: " + channelsDb.getId());
    GetAllPagedSort updatedAt =
        GetAllPagedSort.newBuilder().setField("updatedAt").setValue(1).build();

    tv.pluto.ip.dal.channels.Channels.GetChannelQueueRequest request =
        tv.pluto.ip.dal.channels.Channels.GetChannelQueueRequest.newBuilder()
            .setChannelId(channelsDb.getId())
            .addSort(updatedAt)
            .build();

    tv.pluto.ip.dal.channels.Channels.GetChannelQueueResponse channelQueue =
        channelsClient.getChannelQueueRequest(request);
    channelQueue.getDocumentsList().forEach(e -> Assert.assertNotNull(e.getTagsList()));
  }

  @Test
  @Description("UpdateFields - episodesQueue. Happy path")
  @TmsLink("28500579")
  public void C28500579_TEST() {
    /* In case if update any random channel with a category */
    Channels channel = channelsUtils.getExistsAndSizeNotZero("episodesQueue");
    String testEpisodeId = CommonUtils.getRandomValueFromList(LIST_RANDOM_INVALID_EPISODES);
    String testChannelId = channel.getId();
    LogUtils.logInfoMessage("Channel id: " + testChannelId);

    tv.pluto.ip.dal.channels.Channels.Channel grpcChannel =
        channelsClient.getChannelById(testChannelId).getDocument();
    List<tv.pluto.ip.dal.channels.Channels.EpisodesQueue> episodesQueueList =
        grpcChannel.getEpisodesQueueList();
    tv.pluto.ip.dal.channels.Channels.EpisodesQueue updatedEpisode =
        episodesQueueList.get(0).toBuilder().setEpisode(testEpisodeId).setOrder(1).build();

    List<tv.pluto.ip.dal.channels.Channels.EpisodesQueue> listUpdatedEpisodes =
        List.of(updatedEpisode);

    String catId;

    if (channel.getCategories().isEmpty()) {
      VodCategories cat = vodCategoryUtils.getRandomDocument();
      catId = cat.getId();
    } else catId = channel.getCategories().get(0).getCatId();

    Assert.assertNotNull(catId);

    tv.pluto.ip.dal.channels.Channels.Category category =
        tv.pluto.ip.dal.channels.Channels.Category.newBuilder().setCatId(catId).setOrder(1).build();

    tv.pluto.ip.dal.channels.Channels.Channel channelsList =
        newBuilder()
            .setId(channel.getId())
            .addAllCategories(List.of(category))
            .addAllEpisodesQueue(listUpdatedEpisodes)
            .build();

    List<String> listFields = List.of("episodesQueue", "categories");

    tv.pluto.ip.dal.channels.Channels.Channel updatedChannel =
        channelsClient
            .getUpdateFieldsResponse(testChannelId, channelsList, listFields)
            .getDocument();
    Assert.assertEquals(updatedChannel.getEpisodesQueueList().size(), listUpdatedEpisodes.size());
    Assert.assertEquals(updatedChannel.getEpisodesQueueList(), listUpdatedEpisodes);

    Channels grpcConvertedChannel =
        channelsUtils.mapGrpcObjectToPojo(updatedChannel, Channels.class);
    Channels channelDbUpdated = channelsUtils.getDocumentById(testChannelId);

    Assert.assertEquals(grpcConvertedChannel, channelDbUpdated);
    Assert.assertEquals(testEpisodeId, grpcConvertedChannel.getEpisodesQueue().get(0).getEpisode());
  }

  @Test(
      expectedExceptions = StatusRuntimeException.class,
      expectedExceptionsMessageRegExp = "NOT_FOUND: Channel document for requested ID not found")
  @Description("UpdateFields - episodesQueue invalid channelId")
  @TmsLink("28500580")
  public void C28500580_TEST() {
    /* In case if update any random channel. Use Channels channel = channelsUtils.getExistsAndSizeNotZero("episodesQueue"); with a category */
    Channels channel = channelsUtils.getDocumentById("51c75f7bb6f26ba1cd000019");

    String testEpisodeId = CommonUtils.getRandomValueFromList(LIST_RANDOM_INVALID_EPISODES);

    tv.pluto.ip.dal.channels.Channels.Channel grpcChannel =
        channelsClient.getChannelById(testEpisodeId).getDocument();
    List<tv.pluto.ip.dal.channels.Channels.EpisodesQueue> episodesQueueList =
        grpcChannel.getEpisodesQueueList();
    tv.pluto.ip.dal.channels.Channels.EpisodesQueue updatedEpisode =
        episodesQueueList.get(0).toBuilder().setEpisode(testEpisodeId).setOrder(1).build();

    List<tv.pluto.ip.dal.channels.Channels.EpisodesQueue> listUpdatedEpisodes =
        List.of(updatedEpisode);
    String catId = channel.getCategories().get(0).getCatId();
    Assert.assertNotNull(catId);

    tv.pluto.ip.dal.channels.Channels.Category category =
        tv.pluto.ip.dal.channels.Channels.Category.newBuilder().setCatId(catId).setOrder(1).build();

    tv.pluto.ip.dal.channels.Channels.Channel channelsList =
        newBuilder()
            .setId(channel.getId())
            .addAllCategories(List.of(category))
            .addAllEpisodesQueue(listUpdatedEpisodes)
            .build();

    List<String> listFields = List.of("episodesQueue", "categories");
    channelsClient.getUpdateFieldsResponse(testEpisodeId, channelsList, listFields).getDocument();
  }

  @Test(
      expectedExceptions = RuntimeException.class,
      expectedExceptionsMessageRegExp =
          "INTERNAL: ValidationError: categories.0.catId: catId requires a valid Category ID")
  @Description("UpdateFields - episodesQueue invalid catId")
  @TmsLink("28500581")
  public void C28500581_TEST() {
    /* In case if update any random channel. Use Channels channel = channelsUtils.getExistsAndSizeNotZero("episodesQueue"); with a category */
    Channels channel = channelsUtils.getDocumentById("51c75f7bb6f26ba1cd000019");

    // invalid id
    String testId = CommonUtils.getRandomValueFromList(LIST_RANDOM_INVALID_EPISODES);
    String testChannelId = channel.getId();

    tv.pluto.ip.dal.channels.Channels.Channel grpcChannel =
        channelsClient.getChannelById(testChannelId).getDocument();

    tv.pluto.ip.dal.channels.Channels.Category category =
        tv.pluto.ip.dal.channels.Channels.Category.newBuilder()
            .setCatId(testId)
            .setOrder(1)
            .build();

    tv.pluto.ip.dal.channels.Channels.Channel channelsList =
        newBuilder().setId(channel.getId()).addAllCategories(List.of(category)).build();

    List<String> listFields = List.of("categories");
    channelsClient.getUpdateFieldsResponse(testChannelId, channelsList, listFields);
  }

  @Test(dataProvider = "is-true-false")
  @TmsLink("28500583")
  @Description("GetById - logo_overlay_enable field exist")
  public void C28500583_TEST(boolean isTrue) {
    Channels channel = channelsUtils.getDocumentByKeyValue("logoOverlayEnable", isTrue);

    if (channel == null) LogUtils.logWarningMessage("No data for logoOverlayEnable: " + isTrue);
    else {
      tv.pluto.ip.dal.channels.Channels.Channel grpcChannel =
          channelsClient.getChannelById(channel.getId()).getDocument();
      Assert.assertEquals(channel.getLogoOverlayEnable(), grpcChannel.getLogoOverlayEnable());
      Assert.assertEquals(channel, channelsUtils.mapGrpcObjectToPojo(grpcChannel, Channels.class));
    }
  }

  @Test
  @Description("UpdateFields - logo_overlay_enable field update")
  @TmsLink("28500584")
  public void C28500584_TEST() {
    String logoOverlayEnable = "logoOverlayEnable";
    List<Channels> candidates = channelsUtils.getDocumentsByKeyValue(logoOverlayEnable, false, 20);
    Channels channel = null;
    for (Channels candidate : candidates) {
      boolean allCatIdsValid =
          candidate.getCategories().stream()
              .allMatch(
                  cat ->
                      !cat.getCatId().isEmpty()
                          && mainCategoriesUtils.getDocumentById(cat.getCatId()) != null);
      if (allCatIdsValid) {
        channel = candidate;
        break;
      }
    }
    LogUtils.logInfoMessage("Channel for updateFields test: 28500584" + channel);
    if (channel == null)
      Assert.fail("No channel with logoOverlayEnable=false and valid categories found");

    tv.pluto.ip.dal.channels.Channels.Channel channelsList =
        newBuilder()
            .setId(channel.getId())
            .setLogoOverlayEnable(!channel.getLogoOverlayEnable())
            .build();

    tv.pluto.ip.dal.channels.Channels.Channel response =
        channelsClient
            .getUpdateFieldsResponse(channel.getId(), channelsList, List.of(logoOverlayEnable))
            .getDocument();

    Assert.assertEquals(response.getLogoOverlayEnable(), !channel.getLogoOverlayEnable());
  }

  @Test
  @Description("UpdateFields - logo_overlay_enable field update without id in the document")
  @TmsLink("28500585")
  public void C28500585_TEST() {
    String logoOverlayEnable = "logoOverlayEnable";

    List<Channels> candidates = channelsUtils.getDocumentsByKeyValue(logoOverlayEnable, false, 20);
    Channels channel = null;
    for (Channels candidate : candidates) {
      boolean allCatIdsValid =
          candidate.getCategories().stream()
              .allMatch(
                  cat ->
                      !cat.getCatId().isEmpty()
                          && mainCategoriesUtils.getDocumentById(cat.getCatId()) != null);
      if (allCatIdsValid) {
        channel = candidate;
        break;
      }
    }
    LogUtils.logInfoMessage("Channel for updateFields test: 28500585" + channel);
    if (channel == null)
      Assert.fail("No channel with logoOverlayEnable=false and valid categories found");

    tv.pluto.ip.dal.channels.Channels.Channel channelsList =
        newBuilder().setLogoOverlayEnable(!channel.getLogoOverlayEnable()).build();

    tv.pluto.ip.dal.channels.Channels.Channel response =
        channelsClient
            .getUpdateFieldsResponse(channel.getId(), channelsList, List.of(logoOverlayEnable))
            .getDocument();

    Assert.assertEquals(response.getLogoOverlayEnable(), !channel.getLogoOverlayEnable());
  }

  @Test(groups = {"ttfb"})
  @Description("Check TTFB 90 percentile for the ChannelManager GetById operation.")
  @TmsLink("28500586")
  public void C28500586_TEST() {
    tv.pluto.mongo.entities.channels.Channels randomMongoChannel =
        channelsUtils.getRandomDocument();
    String randomChannelId = randomMongoChannel.getId();

    GrpcCall grpcCall =
        new GrpcCall(
            "ChannelManager.GetById", () -> channelsClient.getChannelById(randomChannelId));

    TTFBGrpcValidator ttfbGrpcValidator = TTFBGrpcValidator.builder().build();

    ttfbGrpcValidator.validateTTFBForGrpcCalls(List.of(grpcCall));
  }

  @Test(groups = {"ttfb"})
  @Description(
      "Check TTFB 90 percentile for the ChannelManager GetTimelinesForActiveContent operation.")
  @TmsLink("28500587")
  public void C28500587_TEST() {
    ActiveContent activeContent = new ActiveContent();
    Timelines randomTimeline = timelinesUtils.getRandomDocument();
    activeContent.setChannelId(randomTimeline.getChannel());
    // Updating dates to increase range of search
    activeContent.setFrom(addYearsToDate(randomTimeline.getStop(), -10));
    activeContent.setTo(addYearsToDate(randomTimeline.getStart(), 10));
    // Sort by start field
    activeContent.setSort("start");
    activeContent.setLimit(MongoUtils.LIMIT);

    GrpcCall grpcCall =
        new GrpcCall(
            "ChannelManager.GetTimelinesForActiveContent",
            () -> channelsClient.getTimelinesForActiveContent(activeContent));

    TTFBGrpcValidator ttfbGrpcValidator = TTFBGrpcValidator.builder().build();

    ttfbGrpcValidator.validateTTFBForGrpcCalls(List.of(grpcCall));
  }

  @Test
  @Description("GetAllPaged using projection")
  @TmsLink("28500588")
  public void C28500588_TEST() {
    DocumentQuery documentQuery =
        DocumentQuery.builder()
            .limit(20)
            .offset(10)
            .projections(include("_id", "name"))
            .sort(orderBy(ascending("_id")))
            .build();

    List<Channels> mongoChannels = channelsUtils.getDocumentsWithCollation(documentQuery);

    List<String> projections = new ArrayList<>();
    projections.add("id");
    projections.add("name");

    List<GetAllPagedSort> grpcSort = Collections.singletonList(channelsClient.sortObject("_id", 1));

    GetAllPagedResponse response =
        new ChannelsClient(grpcChannelManager.getChannel(), false)
            .getAllPaged(20, 10, grpcSort, null, null, projections);

    List<Channels> grpcChannels =
        channelsUtils.mapGrpcObjectsToPojo(response.getDocumentsList(), Channels.class);

    Assert.assertEquals(mongoChannels, grpcChannels);
  }

  @Test
  @Description("BulkRemoveEpisodesFromQueue - Valid Episode ID.")
  @TmsLink("28500589")
  public void C28500589_TEST() {

    List<String> randomEpisodesIds = episodeUtils.getRandomEpisodesIds();

    String episodeId = randomEpisodesIds.get(new Random().nextInt(randomEpisodesIds.size()));

    long channelsCount = channelsUtils.getCountOfChannels();

    tv.pluto.ip.dal.channels.Channels.BulkRemoveEpisodesFromQueueResponse response =
        channelsClient.bulkRemoveEpisodesFromQueue(Collections.singletonList(episodeId));

    Assert.assertTrue(
        response.toString().contains(String.format("Updated %d channel documents", channelsCount)),
        "The response obtained was: "
            + response
            + "but the expected amount of channels was: "
            + channelsCount);
  }

  @Test(
      expectedExceptions = StatusRuntimeException.class,
      expectedExceptionsMessageRegExp =
          "FAILED_PRECONDITION: Request param ids must contain valid ids")
  @Description("BulkRemoveEpisodesFromQueue - Invalid Episode ID.")
  @TmsLink("28500590")
  public void C28500590_TEST() {
    String invalidEpisodeId = "Peñarol & Shakhtar Donetsk";

    channelsClient.bulkRemoveEpisodesFromQueue(Collections.singletonList(invalidEpisodeId));
  }

  @Test(
      expectedExceptions = StatusRuntimeException.class,
      expectedExceptionsMessageRegExp = "FAILED_PRECONDITION: EpisodeID must exist in database")
  @Description("BulkRemoveEpisodesFromQueue - Non-existent Episode ID.")
  @Issue("IP-5764")
  @TmsLink("28500591")
  public void C28500591_TEST() {
    String nonExistentEpisodeId = "1a2b3c4d5e6f7a8b9c10d11e";

    channelsClient.bulkRemoveEpisodesFromQueue(Collections.singletonList(nonExistentEpisodeId));
  }

  @Test
  @Description("GetAllPagedChannelLite - Add number field")
  @TmsLink("28500592")
  public void C28500592_TEST() {
    Channels channels = channelsUtils.getRandomDocument();
    LogUtils.logInfoMessage("Channel id: " + channels.getId());

    List<Filter> listFilter = List.of(channelsClient.getFilter("_id", channels.getId(), "", "AND"));
    List<GetAllPagedSort> grpcSort = Collections.emptyList();

    GetAllPagedChannelLiteResponse allPagedChannelLite =
        channelsClient.getAllPagedChannelLite(1, 0, grpcSort, listFilter, true);

    List<ChannelLite> documentsList = allPagedChannelLite.getDocumentsList();

    ChannelLite lite = documentsList.get(0);

    Assert.assertEquals(lite.getNumber(), channels.getNumber());
  }

  @Test
  @Description("GetAllPagedChannelLite - Number field does not exist")
  @TmsLink("28500593")
  public void C28500593_TEST() {

    Iterator<Channels> channelIterator = channelsUtils.getDocumentsWithTheField("number", false);

    Channels channels = channelIterator.next();

    LogUtils.logInfoMessage("Channel id: " + channels.getId());

    List<Filter> listFilter = List.of(channelsClient.getFilter("_id", channels.getId(), "", "AND"));
    List<GetAllPagedSort> grpcSort = Collections.emptyList();

    GetAllPagedChannelLiteResponse allPagedChannelLite =
        channelsClient.getAllPagedChannelLite(1, 0, grpcSort, listFilter, true);

    List<ChannelLite> documentsList = allPagedChannelLite.getDocumentsList();

    Assert.assertEquals(1, documentsList.size());

    ChannelLite lite = documentsList.get(0);
    Assert.assertEquals(lite.getNumber(), 0);
    Assert.assertFalse(channels.getNumber() > 0, "Channel number should not exist in the document");
  }

  @Test(
      expectedExceptions = StatusRuntimeException.class,
      expectedExceptionsMessageRegExp = "NOT_FOUND: Channel documents not found")
  @Description("GetAllPagedChannelLite  - filter by invalid channel name")
  @TmsLink("28500594")
  public void C28500594_TEST() {
    ChannelsClient channelsClient = new ChannelsClient(grpcChannelManager.getChannel(), false);
    Channels channel = channelsUtils.getRandomDocument();
    channel.setName("invalidChannelName");

    List<GetAllPagedSort> listSortObjects = channelsClient.singleListSortObject("name", 1);
    List<tv.pluto.ip.dal.channels.Channels.Filter> listFiltersBodyInChannels =
        channelsClient.filtersBodyInChannels(channel);

    channelsClient.getAllPagedChannelLite(1, 0, listSortObjects, listFiltersBodyInChannels, true);
  }

  @Test(expectedExceptions = RuntimeException.class, expectedExceptionsMessageRegExp = NOT_FOUND)
  @Description("GetAllPagedChannelLite - AND operator with valid/invalid fields")
  @TmsLink("28500595")
  public void C28500595_TEST() {
    ChannelsClient channelsClient = new ChannelsClient(grpcChannelManager.getChannel(), false);
    Channels channels = channelsUtils.getRandomDocument();
    List<GetAllPagedSort> grpcSort = Collections.emptyList();

    List<Filter> listFilter =
        List.of(
            channelsClient.getFilter("category", channels.getCategory(), "", "AND"),
            channelsClient.getFilter("name", "invalidChannel111", "", "AND"));

    channelsClient.getAllPagedChannelLite(10, 0, grpcSort, listFilter, true);
  }

  @Test(
      expectedExceptions = RuntimeException.class,
      expectedExceptionsMessageRegExp = "INVALID_ARGUMENT.*")
  @Description("GetAllPagedChannelLite - INVALID_ARGUMENT for invalid sort value.")
  @TmsLink("28500596")
  public void C28500596_TEST() {
    List<GetAllPagedSort> grpcSort =
        Collections.singletonList(
            GetAllPagedSort.newBuilder().setField("name").setValue(2).build());
    Channels channels = channelsUtils.getRandomDocument();
    List<Filter> listFilter = List.of(channelsClient.getFilter("_id", channels.getId(), "", "AND"));
    channelsClient.getAllPagedChannelLite(20, 10, grpcSort, listFilter, true);
  }

  @Test(
      expectedExceptions = RuntimeException.class,
      expectedExceptionsMessageRegExp =
          "INVALID_ARGUMENT: Operator property should be only AND, OR, or NOR.")
  @Description("GetAllPagedChannelLite - invalid operator")
  @TmsLink("28500597")
  public void C28500597_TEST() {
    Channels channels = channelsUtils.getRandomDocument();

    List<Filter> listFilter =
        List.of(channelsClient.getFilter("_id", channels.getId(), "", "InvalidOperator"));
    List<GetAllPagedSort> grpcSort = Collections.emptyList();
    channelsClient.getAllPagedChannelLite(1, 0, grpcSort, listFilter, true);
  }

  @Test
  @Description("GetLibrarySumDuration - Request with valid data.")
  @TmsLink("28500598")
  public void C28500598_TEST() {

    Channels channels = channelsUtils.getRandomDocumentWithTheFieldSize("episodesQueue", 20);

    List<String> episodesIds = new ArrayList<>();

    for (EpisodesQueue episodesQueue : channels.getEpisodesQueue()) {
      episodesIds.add(episodesQueue.getEpisode());
    }

    List<Series> series = seriesUtils.getSeriesByChannelId(new ObjectId(channels.getId()));
    List<String> seriesIds = seriesUtils.extractIdsFromSeries(series);

    List<Episodes> episodes =
        episodeUtils.getEpisodesExcludingIdsAndMatchingSeries(episodesIds, seriesIds);

    Episodes filterEpisode = episodes.get(0);

    int sumDuration = 0;

    for (Episodes episode : episodes) {
      if (episode.getStatus().equals(filterEpisode.getStatus())
          && episode.getName().equals(filterEpisode.getName())) {
        sumDuration += episode.getDuration();
      }
    }

    GetLibrarySumDurationRequest request =
        GetLibrarySumDurationRequest.newBuilder()
            .setChannelId(channels.getId())
            .setName(filterEpisode.getName())
            .addAllStatus(List.of(filterEpisode.getStatus()))
            .build();

    GetLibrarySumDurationResponse response = channelsClient.getLibrarySumDuration(request);

    Assert.assertEquals(
        response.getSumDuration(),
        sumDuration,
        "The expected sumDuration: "
            + sumDuration
            + " is not equal to the response sumDuration: "
            + response.getSumDuration());
  }

  @Test
  @Issue("IP-5795")
  @Description("GetLibrarySumDuration - Request with channel without episodesQueue.")
  @TmsLink("28500599")
  public void C28500599_TEST() {

    Channels channels = channelsUtils.getRandomDocumentWithTheFieldSize("episodesQueue", 0);

    List<Series> series = seriesUtils.getSeriesByChannelId(new ObjectId(channels.getId()));
    List<String> seriesIds = seriesUtils.extractIdsFromSeries(series);

    List<Episodes> episodes =
        episodeUtils.getEpisodesExcludingIdsAndMatchingSeries(new ArrayList<>(), seriesIds);

    int sumDuration = 0;

    if (episodes != null) {
      for (Episodes episode : episodes) {
        sumDuration += episode.getDuration();
      }
    }

    GetLibrarySumDurationRequest request =
        GetLibrarySumDurationRequest.newBuilder().setChannelId(channels.getId()).build();

    GetLibrarySumDurationResponse response = channelsClient.getLibrarySumDuration(request);

    Assert.assertEquals(
        response.getSumDuration(),
        sumDuration,
        "The expected sumDuration: "
            + sumDuration
            + " is not equal to the response sumDuration: "
            + response.getSumDuration());
  }

  @Test(
      expectedExceptions = StatusRuntimeException.class,
      expectedExceptionsMessageRegExp = "INVALID_ARGUMENT: Channel ID cannot be undefined or empty")
  @Description("GetLibrarySumDuration - Request without channelId.")
  @TmsLink("28500600")
  public void C28500600_TEST() {
    GetLibrarySumDurationRequest request = GetLibrarySumDurationRequest.newBuilder().build();

    channelsClient.getLibrarySumDuration(request);
  }

  @Test(
      expectedExceptions = StatusRuntimeException.class,
      expectedExceptionsMessageRegExp = "INVALID_ARGUMENT: Provided status is not valid")
  @Description("GetLibrarySumDuration - Request with an invalid status.")
  @TmsLink("28500601")
  public void C28500601_TEST() {
    GetLibrarySumDurationRequest request =
        GetLibrarySumDurationRequest.newBuilder()
            .setChannelId(new ObjectId().toString())
            .addAllStatus(List.of("Peñarol", "Shakhtar Donetsk"))
            .build();

    channelsClient.getLibrarySumDuration(request);
  }

  @Test(
      expectedExceptions = StatusRuntimeException.class,
      expectedExceptionsMessageRegExp = INTERNAL_MESSAGE)
  @Description("GetLibrarySumDuration - Request with an invalid channelId.")
  @TmsLink("28500602")
  public void C28500602_TEST() {
    GetLibrarySumDurationRequest request =
        GetLibrarySumDurationRequest.newBuilder()
            .setChannelId("Peñarol & Shakhtar Donetsk")
            .addAllStatus(List.of("completed", "on air"))
            .build();

    channelsClient.getLibrarySumDuration(request);
  }

  @Test
  @Description("GetQueueSumDuration - Request with valid data.")
  @TmsLink("28500603")
  public void C28500603_TEST() {

    Channels channels = channelsUtils.getRandomDocumentWithTheFieldSize("episodesQueue", 20);

    List<String> episodesIds = new ArrayList<>();

    for (EpisodesQueue episodesQueue : channels.getEpisodesQueue()) {
      episodesIds.add(episodesQueue.getEpisode());
    }

    List<Episodes> episodes = episodeUtils.getPublishedEpisodesByIds(episodesIds);

    Episodes filterEpisode = episodes.get(0);

    int sumDuration = 0;

    for (Episodes episode : episodes) {
      if (episode.getStatus().equals(filterEpisode.getStatus())
          && episode.getName().equals(filterEpisode.getName())) {
        sumDuration += episode.getDuration();
      }
    }

    GetQueueSumDurationRequest request =
        GetQueueSumDurationRequest.newBuilder()
            .setChannelId(channels.getId())
            .setName(filterEpisode.getName())
            .addAllStatus(List.of(filterEpisode.getStatus()))
            .build();

    GetQueueSumDurationResponse response = channelsClient.getQueueSumDuration(request);

    Assert.assertEquals(
        response.getSumDuration(),
        sumDuration,
        "The expected sumDuration: "
            + sumDuration
            + " is not equal to the response sumDuration: "
            + response.getSumDuration());
  }

  @Test
  @Description("GetQueueSumDuration - Request with channel without episodesQueue.")
  @TmsLink("28500604")
  public void C28500604_TEST() {

    Channels channels = channelsUtils.getRandomDocumentWithTheFieldSize("episodesQueue", 0);

    int expectedSumDuration = 0;

    GetQueueSumDurationRequest request =
        GetQueueSumDurationRequest.newBuilder()
            .setChannelId(channels.getId())
            .addAllStatus(List.of("completed", "on air"))
            .build();

    GetQueueSumDurationResponse response = channelsClient.getQueueSumDuration(request);

    Assert.assertEquals(
        response.getSumDuration(),
        expectedSumDuration,
        "The expected sumDuration: "
            + expectedSumDuration
            + " is not equal to the response sumDuration: "
            + response.getSumDuration());
  }

  @Test(
      expectedExceptions = StatusRuntimeException.class,
      expectedExceptionsMessageRegExp = "INVALID_ARGUMENT: Channel ID cannot be undefined or empty")
  @Description("GetQueueSumDuration - Request without channelId.")
  @TmsLink("28500605")
  public void C28500605_TEST() {
    GetQueueSumDurationRequest request = GetQueueSumDurationRequest.newBuilder().build();

    channelsClient.getQueueSumDuration(request);
  }

  @Test(
      expectedExceptions = StatusRuntimeException.class,
      expectedExceptionsMessageRegExp = "INVALID_ARGUMENT: Provided status is not valid")
  @Description("GetQueueSumDuration - Request with an invalid status.")
  @TmsLink("28500606")
  public void C28500606_TEST() {
    GetQueueSumDurationRequest request =
        GetQueueSumDurationRequest.newBuilder()
            .setChannelId(new ObjectId().toString())
            .addAllStatus(List.of("Peñarol", "Shakhtar Donetsk"))
            .build();

    channelsClient.getQueueSumDuration(request);
  }

  @Test(
      expectedExceptions = StatusRuntimeException.class,
      expectedExceptionsMessageRegExp = INTERNAL_MESSAGE)
  @Description("GetQueueSumDuration - Request with an invalid channelId.")
  @TmsLink("28500607")
  public void C28500607_TEST() {
    GetQueueSumDurationRequest request =
        GetQueueSumDurationRequest.newBuilder()
            .setChannelId("Peñarol & Shakhtar Donetsk")
            .addAllStatus(List.of("completed", "on air"))
            .build();

    channelsClient.getQueueSumDuration(request);
  }

  @Test
  @Description("GetAllPaged - NOR Operator with Valid Values")
  @TmsLink("28500608")
  public void C28500608_TEST() {

    ChannelsClient channelsClient = new ChannelsClient(grpcChannelManager.getChannel(), false);

    List<Filter> listFilter =
        List.of(channelsClient.getFilter("distribution.include", "web", "string", "NOR"));

    GetAllPagedResponse response = channelsClient.getAllPagedRegex(1000, 0, null, listFilter, true);

    BasicDBObject query =
        new BasicDBObject("$nor", List.of(new BasicDBObject("distribution.include", "web")));

    List<Channels> listChannels = channelsUtils.getListChannels(query);
    List<Channels> listChannelsGrpc =
        channelsUtils.mapGrpcObjectsToPojo(response.getDocumentsList(), Channels.class);

    listChannels.sort(Comparator.comparing(Channels::getId));
    listChannelsGrpc.sort(Comparator.comparing(Channels::getId));
    listChannelsGrpc.forEach(c -> c.setMainCategories(null));

    Assert.assertFalse(listChannels.isEmpty(), "Mongo result is empty.");
    Assert.assertFalse(listChannelsGrpc.isEmpty(), "gRPC result is empty.");
    Assert.assertEquals(listChannels, listChannelsGrpc, "Mongo and gRPC results do not match.");
  }

  @Test(
      expectedExceptions = StatusRuntimeException.class,
      expectedExceptionsMessageRegExp = "NOT_FOUND: Channel documents not found")
  @TmsLink("28500609")
  @Description("GetAllPaged - NOR and OR filters with valid values resulting in NOT_FOUND")
  public void C28500609_TEST()
      throws NoSuchFieldException, IllegalAccessException, InvocationTargetException {

    ChannelsClient channelsClient = new ChannelsClient(grpcChannelManager.getChannel(), false);
    List<GetAllPagedSort> grpcSort = Collections.emptyList();

    List<Filter> listFilters =
        List.of(
            channelsClient.getFilter("distribution.include", "validValue", "string", "NOR"),
            channelsClient.getFilter("distribution.include", "validValue", "string", "OR"));

    channelsClient.getAllPagedException(10, 0, grpcSort, listFilters, true);
  }

  @Test(
      expectedExceptions = RuntimeException.class,
      expectedExceptionsMessageRegExp = "NOT_FOUND: Channel documents not found")
  @TmsLink("28500610")
  @Description("GetAllPaged - Non-existent field in filter resulting in error")
  public void C28500610_TEST()
      throws NoSuchFieldException, IllegalAccessException, InvocationTargetException {

    ChannelsClient channelsClient = new ChannelsClient(grpcChannelManager.getChannel(), false);
    List<GetAllPagedSort> grpcSort = Collections.emptyList();
    List<Filter> listFilters =
        List.of(channelsClient.getFilter("nonExistentField", "value", "string", "AND"));

    channelsClient.getAllPagedException(10, 0, grpcSort, listFilters, true);
  }

  @Test
  @Description("GetChannelQueue - Validate has_live_broadcast field in gRPC output")
  @TmsLink("28500611")
  public void C28500611_TEST() {
    // Any episode with rating +
    String rating = "+12";
    Episodes episode = episodeUtils.getDocumentByFieldAndValue("rating", rating);
    String channelId = episode.getChannels().get(0).toString();

    tv.pluto.ip.dal.channels.Channels.GetChannelQueueRequest request =
        tv.pluto.ip.dal.channels.Channels.GetChannelQueueRequest.newBuilder()
            .setChannelId(channelId)
            .setRating(episode.getRating())
            .build();

    tv.pluto.ip.dal.channels.Channels.GetChannelQueueResponse response =
        channelsClient.getChannelQueueRequest(request);

    Assert.assertFalse(
        response.getDocumentsList().isEmpty(), "No documents found in gRPC response");

    response
        .getDocumentsList()
        .forEach(
            document -> {
              Assert.assertNotNull(document, "ChannelQueue document is null");

              Assert.assertNotNull(
                  document.getHasLiveBroadcast(),
                  "has_live_broadcast field is not present for timeline draft ID: "
                      + document.getId());
            });
  }

  @Test
  @Description("GetChannelByFilter - Get valid data for a Channel by slug and published flag")
  @TmsLink("28500612")
  public void C28500612_Test() {

    Channels mongoDocument = channelsUtils.getExistsAndNotEmpty("slug");
    LogUtils.logInfoMessage("mongoDocument: " + mongoDocument);
    String slug = mongoDocument.getSlug();
    boolean published = mongoDocument.getPublished();
    GetChannelByFilterRequest request =
        GetChannelByFilterRequest.newBuilder().setSlug(slug).setPublished(published).build();

    GetChannelByFilterResponse apiResponse = channelsClient.channelsByFilter(request);

    Assert.assertEquals(
        apiResponse.getDocument().getSlug(), mongoDocument.getSlug(), "Slug value  mismatch");
    Assert.assertEquals(
        apiResponse.getDocument().getPublished(),
        mongoDocument.getPublished(),
        "Published status mismatch");
  }

  @Test(expectedExceptions = RuntimeException.class, expectedExceptionsMessageRegExp = NOT_FOUND)
  @Description("GetChannelByFilter - Non-existent slug with 'published' status shows error.")
  @TmsLink("28500613")
  public void C28500613_Test() {

    String invalidSlug = "invalid";
    boolean published = true;
    GetChannelByFilterRequest request =
        GetChannelByFilterRequest.newBuilder().setSlug(invalidSlug).setPublished(published).build();

    channelsClient.channelsByFilter(request);
  }

  @Test(
      expectedExceptions = RuntimeException.class,
      expectedExceptionsMessageRegExp = "INVALID_ARGUMENT: Slug should be provided")
  @Description("GetChannelByFilter - Missing slug causes error.")
  @TmsLink("28500614")
  public void C28500614_Test() {

    boolean published = true;

    GetChannelByFilterRequest request =
        GetChannelByFilterRequest.newBuilder().setPublished(published).build();

    channelsClient.channelsByFilter(request);
  }

  @Test(expectedExceptions = RuntimeException.class, expectedExceptionsMessageRegExp = NOT_FOUND)
  @Description("GetChannelByFilter  - Valid slug with default 'published: false' causes error.")
  @TmsLink("28500615")
  public void C28500615_Test() {
    String slug = channelsUtils.getSlug();
    GetChannelByFilterRequest request =
        GetChannelByFilterRequest.newBuilder().setSlug(slug).build();
    channelsClient.channelsByFilter(request);
  }

  @Test
  @Description("UpdateFields - _isDASHReadyDRM field update")
  @TmsLink("28500616")
  public void C28500616_TEST() {
    String isDASHReadyDRMField = "_isDASHReadyDRM";
    Channels channel = channelsUtils.getDocumentByKeyValue(isDASHReadyDRMField, true);

    if (channel == null) Assert.fail("No data for isDASHReadyDRM");

    tv.pluto.ip.dal.channels.Channels.Channel updatedChannel =
        newBuilder().setId(channel.getId()).setIsDASHReadyDRM(!channel.getIsDASHReadyDRM()).build();

    tv.pluto.ip.dal.channels.Channels.Channel response =
        channelsClient
            .getUpdateFieldsResponse(channel.getId(), updatedChannel, List.of(isDASHReadyDRMField))
            .getDocument();

    Assert.assertEquals(response.getIsDASHReadyDRM(), !channel.getIsDASHReadyDRM());
  }

  @Test
  @Description("UpdateFields - _isDASHReadyDRM field update without id in the document")
  @TmsLink("28500617")
  public void C28500617_TEST() {
    String isDASHReadyDRMField = "_isDASHReadyDRM";
    Channels channel = channelsUtils.getDocumentByKeyValue(isDASHReadyDRMField, true);

    if (channel == null) Assert.fail("No data for isDASHReadyDRM");

    tv.pluto.ip.dal.channels.Channels.Channel updatedChannel =
        newBuilder().setIsDASHReadyDRM(!channel.getIsDASHReadyDRM()).build();

    tv.pluto.ip.dal.channels.Channels.Channel response =
        channelsClient
            .getUpdateFieldsResponse(channel.getId(), updatedChannel, List.of(isDASHReadyDRMField))
            .getDocument();

    Assert.assertEquals(response.getIsDASHReadyDRM(), !channel.getIsDASHReadyDRM());
  }
}
