package tv.pluto;

import com.plutotv.test.lib.LogUtils;
import io.grpc.StatusRuntimeException;
import io.qameta.allure.Description;
import io.qameta.allure.TmsLink;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;
import org.assertj.core.util.Streams;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import tv.pluto.core.BaseTest;
import tv.pluto.grpc.age_ranges.AgeRangesClient;
import tv.pluto.mongo.entities.ageranges.AgeRanges;
import tv.pluto.mongo.utils.ageranges.AgeRangesUtils;
import tv.pluto.utils.CommonUtils;

public class AgeRangesTestSuite extends BaseTest {
  private AgeRangesUtils ageRangesUtils;
  private AgeRangesClient ageRangesClient;

  @BeforeClass(alwaysRun = true)
  private void setUp() {
    ageRangesUtils = new AgeRangesUtils();
    ageRangesClient = new AgeRangesClient(grpcChannelManager.getChannel());
  }

  @Test
  @Description("GetDocuments")
  @TmsLink("28500354")
  public void C28500354_TEST() {
    List<AgeRanges> mongoProperties = ageRangesUtils.getDocuments(0);
    List<AgeRanges> grpcProperties = new ArrayList<>();

    Iterator<tv.pluto.ip.dal.agerange.AgeRanges.AgeRange> properties =
        ageRangesClient.getDocuments();

    while (properties.hasNext()) {
      grpcProperties.add(ageRangesUtils.mapGrpcObjectToPojo(properties.next(), AgeRanges.class));
    }

    mongoProperties.sort(Comparator.comparing(AgeRanges::getId));
    grpcProperties.sort(Comparator.comparing(AgeRanges::getId));

    Assert.assertEquals(mongoProperties, grpcProperties);
  }

  @Test
  @Description("CFeedsSyncAllIds - get CFEEDs ids")
  @TmsLink("28500349")
  public void C28500349_TEST() {
    Iterator<tv.pluto.ip.dal.agerange.AgeRanges.Id> idIterator =
        ageRangesClient.cFeedsSyncAllIdsIterator();

    List<String> listGrpcIds =
        Streams.stream(idIterator)
            .limit(10)
            .map(tv.pluto.ip.dal.agerange.AgeRanges.Id::getId)
            .collect(Collectors.toList());

    List<String> mongoIds =
        ageRangesUtils.getDocumentsByIds(listGrpcIds).stream()
            .map(range -> ((AgeRanges) range).getId())
            .collect(Collectors.toList());

    Assert.assertTrue(CommonUtils.isTwoListsEqual(mongoIds, listGrpcIds));
  }

  @Test
  @Description("cFeedsSyncDocuments - last_run_at")
  @TmsLink("28500350")
  public void C28500350_TEST() {
    AgeRanges randomActiveRegions = ageRangesUtils.getRandomDocument();
    List<AgeRanges> mongoAllAgeRangesWithingUpdatedDate =
        ageRangesUtils.getAllAgeRangesWithingUpdatedDate(randomActiveRegions.getUpdatedAt());
    List<tv.pluto.ip.dal.agerange.AgeRanges.AgeRange> getGrpcRange =
        ageRangesClient.getListCFeedsSyncDocsUpdatedAgeRange(
            randomActiveRegions.getUpdatedAtString());
    List<AgeRanges> grpcAgeList =
        ageRangesUtils.mapGrpcObjectsToPojo(getGrpcRange, AgeRanges.class);

    mongoAllAgeRangesWithingUpdatedDate.sort(Comparator.comparing(AgeRanges::getId));
    grpcAgeList.sort(Comparator.comparing(AgeRanges::getId));

    Assert.assertFalse(mongoAllAgeRangesWithingUpdatedDate.isEmpty());
    Assert.assertEquals(mongoAllAgeRangesWithingUpdatedDate, grpcAgeList);
  }

  @Test(
      expectedExceptions = StatusRuntimeException.class,
      expectedExceptionsMessageRegExp = NOT_FOUND_MESSAGE)
  @Description("cFeedsSyncDocuments - last_run_at now time. Negative scenario")
  @TmsLink("28500351")
  public void C28500351_TEST() {
    LocalDateTime nowTime = LocalDateTime.now(ZoneOffset.UTC);
    List<AgeRanges> allAgeRangesWithingUpdatedDate =
        ageRangesUtils.getAllAgeRangesWithingUpdatedDate(nowTime);
    Assert.assertTrue(allAgeRangesWithingUpdatedDate.isEmpty());
    ageRangesClient.getListCFeedsSyncDocsUpdatedAgeRange(nowTime.toString()).get(0);
  }

  @Test
  @Description("getAllPaged - filter by active region")
  @TmsLink("28500352")
  public void C28500352_TEST() {
    String activeRegion = "us";
    AgeRangesClient ageRangesClient = new AgeRangesClient(grpcChannelManager.getChannel());
    List<AgeRanges> allAgeRanges = ageRangesUtils.getAllAgeRangesWithFilter(activeRegion);
    List<tv.pluto.ip.dal.agerange.AgeRanges.GetAllPagedSort> ageRangeSort =
        ageRangesClient.grpcSort("name");
    List<tv.pluto.ip.dal.agerange.AgeRanges.Filter> activeRegionsFilter =
        ageRangesClient.activeRegionsFilter("activeRegion", activeRegion, "string");

    tv.pluto.ip.dal.agerange.AgeRanges.GetAllPagedResponse responseAgeRangesGrpc =
        ageRangesClient.getAllPaged(
            allAgeRanges.size(), 0, ageRangeSort, activeRegionsFilter, null);

    try {
      List listAgeRangesGrpc = responseAgeRangesGrpc.getDocumentsList();
      List<AgeRanges> grpcList =
          ageRangesUtils.mapGrpcObjectsToPojo(listAgeRangesGrpc, AgeRanges.class);
      allAgeRanges.sort(Comparator.comparing(AgeRanges::getId));
      grpcList.sort(Comparator.comparing(AgeRanges::getId));

      Assert.assertEquals(allAgeRanges, grpcList);
    } catch (NullPointerException e) {
      LogUtils.logSevereMessage(e.getMessage());
    }
  }

  @Test(
      expectedExceptions = StatusRuntimeException.class,
      expectedExceptionsMessageRegExp = "NOT_FOUND: AgeRange documents not found")
  @Description("getAllPaged - filter by invalid active region")
  @TmsLink("28500353")
  public void C28500353_TEST() {
    List<tv.pluto.ip.dal.agerange.AgeRanges.GetAllPagedSort> ageRangeSort =
        ageRangesClient.grpcSort("name");
    List<tv.pluto.ip.dal.agerange.AgeRanges.Filter> activeRegionsFilter =
        ageRangesClient.activeRegionsFilter("activeRegion", "bla456", "string");
    ageRangesClient.getAllPagedResponse(5, 0, ageRangeSort, activeRegionsFilter).isInitialized();
  }

  @Test
  @Description("GetAllPagedResponse - has a new object Metadata")
  @TmsLink("28500355")
  public void C28500355_TEST() {
    int offset = 0;
    String activeRegion = "us";
    AgeRangesClient ageRangesClient = new AgeRangesClient(grpcChannelManager.getChannel());
    List<AgeRanges> allAgeRanges = ageRangesUtils.getAllAgeRangesWithFilter(activeRegion);
    List<tv.pluto.ip.dal.agerange.AgeRanges.GetAllPagedSort> ageRangeSort =
        ageRangesClient.grpcSort("name");
    List<tv.pluto.ip.dal.agerange.AgeRanges.Filter> activeRegionsFilter =
        ageRangesClient.activeRegionsFilter("activeRegion", activeRegion, "string");

    for (int i = allAgeRanges.size(); i > 0; i--) {
      tv.pluto.ip.dal.agerange.AgeRanges.GetAllPagedResponse responseAgeRangesGrpc =
          ageRangesClient.getAllPaged(i, offset, ageRangeSort, activeRegionsFilter, true);

      Assert.assertEquals(offset, responseAgeRangesGrpc.getMetadata().getCurrentOffset());
      Assert.assertEquals(i, responseAgeRangesGrpc.getMetadata().getTotalItems());
    }
  }

  @Test
  @Description("GetAllPagedResponse - has a new object Metadata disable_total_count: false")
  @TmsLink("28500356")
  public void C28500356_TEST() {
    int limit = 100;
    int offset = 1;
    String activeRegion = "us";
    AgeRangesClient ageRangesClient = new AgeRangesClient(grpcChannelManager.getChannel());
    List<tv.pluto.ip.dal.agerange.AgeRanges.GetAllPagedSort> ageRangeSort =
        ageRangesClient.grpcSort("name");
    List<tv.pluto.ip.dal.agerange.AgeRanges.Filter> activeRegionsFilter =
        ageRangesClient.activeRegionsFilter("activeRegion", activeRegion, "string");
    tv.pluto.ip.dal.agerange.AgeRanges.GetAllPagedResponse responseAgeRangesGrpc =
        ageRangesClient.getAllPaged(limit, offset, ageRangeSort, null, false);

    long countTotalEpisodes = ageRangesUtils.getDocumentsCountsInTheCollection();
    Assert.assertTrue(countTotalEpisodes > 0);
    Assert.assertEquals(responseAgeRangesGrpc.getMetadata().getTotalItems(), countTotalEpisodes);
    Assert.assertEquals(responseAgeRangesGrpc.getMetadata().getCurrentOffset(), offset);
    Assert.assertEquals(
        responseAgeRangesGrpc.getDocumentsList().size(), countTotalEpisodes - offset);

    tv.pluto.ip.dal.agerange.AgeRanges.GetAllPagedResponse filteredResponseAgeRangesGrpc =
        ageRangesClient.getAllPaged(limit, offset, ageRangeSort, activeRegionsFilter, false);
    List<AgeRanges> listAgeRanges =
        ageRangesUtils.getDocumentsByKeyValue("countryCode", activeRegion);
    listAgeRanges.sort(Comparator.comparing(AgeRanges::getName));
    listAgeRanges.remove(0);
    List<AgeRanges> grpcList =
        ageRangesUtils.mapGrpcObjectsToPojo(
            filteredResponseAgeRangesGrpc.getDocumentsList(), AgeRanges.class);

    Assert.assertTrue(listAgeRanges.size() > 0);
    Assert.assertEquals(grpcList.size(), listAgeRanges.size());
    Assert.assertEquals(filteredResponseAgeRangesGrpc.getMetadata().getCurrentOffset(), offset);
  }
}
