package tv.pluto;

import io.grpc.StatusRuntimeException;
import io.qameta.allure.Description;
import io.qameta.allure.TmsLink;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import net.datafaker.Faker;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import tv.pluto.core.BaseTest;
import tv.pluto.grpc.publishing_users.PublishingUsersClient;
import tv.pluto.ip.dal.publishinguser.PublishingUsers.PublishingUser;
import tv.pluto.mongo.entities.publishingusers.PublishingUsers;
import tv.pluto.mongo.utils.MongoUtils;
import tv.pluto.mongo.utils.PublishingUsersUtils;

// import publishinguserpackage.PublishingUsers.CreateResponse;

public class PublishingUsersTestSuite extends BaseTest {
  private PublishingUsersClient publishingUsersClient;
  private PublishingUsersClient publishingUsersClientAuth;
  private PublishingUsersUtils publishingUsersUtils;

  private static final String USER_ID = "5d9cc977c509420009516297";
  private static final String USER_ID2 = "5d96ed8ac509420009512e97";

  @BeforeClass(alwaysRun = true)
  private void setUp() {
    publishingUsersClient = new PublishingUsersClient(grpcChannelManager.getChannel(), false);
    publishingUsersClientAuth = new PublishingUsersClient(grpcChannelManager.getChannel(), true);
    publishingUsersUtils = new PublishingUsersUtils();
  }

  @Test
  @Description("GetById - existing id")
  @TmsLink("28501206")
  public void C28501206_TEST() {
    PublishingUsers mongoUser = publishingUsersUtils.getRandomDocument();

    String randomUserId = mongoUser.getId();

    PublishingUsers mappedUser =
        publishingUsersUtils.mapGrpcObjectToPojo(
            publishingUsersClient.getById(randomUserId).getDocument(), PublishingUsers.class);

    Assert.assertEquals(mongoUser, mappedUser);
  }

  @Test
  @Description("GetAllPagedResponse - has a new object Metadata")
  @TmsLink("28501216")
  public void C28501216_TEST() {
    int offset = 2;
    int limit = 3;

    tv.pluto.ip.dal.publishinguser.PublishingUsers.GetAllPagedResponse response =
        publishingUsersClient.getAllPaged(limit, offset, null, null, true);
    Assert.assertEquals(response.getMetadata().getCurrentOffset(), offset);
    Assert.assertEquals(limit, response.getMetadata().getTotalItems());
    Assert.assertEquals(limit, response.getDocumentsList().size());
  }

  @Test
  @Description("GetAllPagedResponse - has a new object Metadata disable_total_count: false")
  @TmsLink("28501217")
  public void C28501217_TEST() {
    int limit = 10;
    int offset = 1;
    tv.pluto.ip.dal.publishinguser.PublishingUsers.GetAllPagedResponse response =
        publishingUsersClient.getAllPaged(limit, offset, null, null, false);
    long countTotalEpisodes = publishingUsersUtils.getDocumentsCountsInTheCollection();

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

  @Test(
      expectedExceptions = StatusRuntimeException.class,
      expectedExceptionsMessageRegExp =
          "NOT_FOUND: PublishingUser document for requested ID not found")
  @Description("GetById - non existing id")
  @TmsLink("28501207")
  public void C28501207_TEST() {
    publishingUsersClient.getById(MongoUtils.INVALID_ID_VALUE);
  }

  @Test
  @Description("GetByIds - single existing ID")
  @TmsLink("28501208")
  public void C28501208_TEST() {
    PublishingUsers randomUser = publishingUsersUtils.getRandomDocument();
    List<String> randomUsersIds = Collections.singletonList(randomUser.getId());

    List<PublishingUsers> mongoUsersList = publishingUsersUtils.getDocumentsByIds(randomUsersIds);
    List<PublishingUsers> mappedUsersList =
        publishingUsersUtils.mapGrpcObjectsToPojo(
            publishingUsersClient.getByIds(randomUsersIds).getDocumentsList(),
            PublishingUsers.class);

    Assert.assertEquals(mongoUsersList, mappedUsersList);
  }

  @Test
  @Description("GetByIds - multiple existing IDs")
  @TmsLink("28501209")
  public void C28501209_TEST() {
    List<String> randomUsersIds = publishingUsersUtils.getRandomIds();

    List<PublishingUsers> mongoUsersList = publishingUsersUtils.getDocumentsByIds(randomUsersIds);
    List<PublishingUsers> mappedUsersList =
        publishingUsersUtils.mapGrpcObjectsToPojo(
            publishingUsersClient.getByIds(randomUsersIds).getDocumentsList(),
            PublishingUsers.class);

    Assert.assertEquals(mongoUsersList, mappedUsersList);
  }

  @Test(
      expectedExceptions = StatusRuntimeException.class,
      expectedExceptionsMessageRegExp =
          "NOT_FOUND: PublishingUser documents for requested IDs not found")
  @Description("GetByIds - single non existing ID")
  @TmsLink("28501210")
  public void C28501210_TEST() {
    List<String> randomUsersIds = Collections.singletonList(MongoUtils.INVALID_ID_VALUE);
    publishingUsersClient.getByIds(randomUsersIds);
  }

  @Test
  @Description("GetByIds - multiple existing IDs and one non existing")
  @TmsLink("28501211")
  public void C28501211_TEST() {
    List<String> randomUsersIds = publishingUsersUtils.getRandomIds();
    randomUsersIds.add(MongoUtils.INVALID_ID_VALUE);

    List<PublishingUsers> mongoUsersList = publishingUsersUtils.getDocumentsByIds(randomUsersIds);
    List<PublishingUsers> mappedUsersList =
        publishingUsersUtils.mapGrpcObjectsToPojo(
            publishingUsersClient.getByIds(randomUsersIds).getDocumentsList(),
            PublishingUsers.class);

    Assert.assertEquals(mongoUsersList, mappedUsersList);
  }

  @Test
  @Description("UpdateFields - update displayName")
  @TmsLink("28501212")
  public void C28501212_TEST() {
    Faker faker = new Faker();
    String displayName = "DAL C7800091_TEST " + faker.funnyName().name();

    PublishingUser publishingUser = PublishingUser.newBuilder().setDisplayName(displayName).build();

    PublishingUsers grpcUser =
        publishingUsersUtils.mapGrpcObjectToPojo(
            publishingUsersClient
                .updateFields(USER_ID, publishingUser, Collections.singletonList("displayName"))
                .getDocument(),
            PublishingUsers.class);

    PublishingUsers mongoUser = publishingUsersUtils.getDocumentById(USER_ID);

    Assert.assertEquals(mongoUser, grpcUser);
    Assert.assertEquals(mongoUser.getDisplayName(), displayName);
  }

  /* Was USER_ID2 which is not in the db. Changed to USER_ID C7800091 and C7800092 can fail when running in parallel need new data*/
  @Test
  @Description("UpdateFields - update multiple fields")
  @TmsLink("28501213")
  public void C28501213_TEST() {
    Faker faker = new Faker();

    String displayName = "DAL C7800092_TEST " + faker.funnyName().name();
    String email = faker.internet().emailAddress();

    PublishingUser publishingUser =
        PublishingUser.newBuilder().setDisplayName(displayName).setEmail(email).build();

    PublishingUsers grpcUser =
        publishingUsersUtils.mapGrpcObjectToPojo(
            publishingUsersClient
                .updateFields(USER_ID2, publishingUser, Arrays.asList("displayName", "email"))
                .getDocument(),
            PublishingUsers.class);

    PublishingUsers mongoUser = publishingUsersUtils.getDocumentById(USER_ID2);

    Assert.assertEquals(mongoUser, grpcUser);
    Assert.assertEquals(mongoUser.getDisplayName(), displayName);
    Assert.assertEquals(mongoUser.getEmail(), email);
  }
}
