package tv.pluto;

import static io.restassured.RestAssured.given;

import io.grpc.StatusRuntimeException;
import io.qameta.allure.Description;
import io.qameta.allure.TmsLink;
import io.restassured.response.Response;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import tv.pluto.core.BaseTest;
import tv.pluto.grpc.languages.LanguageCode;
import tv.pluto.grpc.languages.LanguagesClient;
import tv.pluto.mongo.utils.MongoUtils;

public class LanguagesTestSuite extends BaseTest {
  private List<LanguageCode> languages;
  private MongoUtils mongoUtils;
  private LanguagesClient languagesClient;

  @BeforeClass(alwaysRun = true)
  public void setUp() {
    languages = new ArrayList<>();
    mongoUtils = new MongoUtils();
    languagesClient = new LanguagesClient(grpcChannelManager.getChannel());

    Response response =
        given()
            .when()
            .get("https://raw.githubusercontent.com/pubcore/iso-language-codes/v2.0.0/src/data.ts")
            .then()
            .extract()
            .response();

    String responseBody =
        response
            .getBody()
            .asPrettyString()
            .replace("export default [\n", "")
            .replace("\t[", "")
            .replace("]", "");

    String[] split = responseBody.split("\n");

    Arrays.stream(split)
        .forEach(
            row -> {
              String[] splitRow = row.split("',");
              if (splitRow.length >= 5) {
                LanguageCode languageCode = new LanguageCode();
                languageCode.setName(splitRow[0].replace("'", ""));
                languageCode.setNativeName(splitRow[1].replace(" '", "").replace("\\", ""));
                languageCode.setIso6391(splitRow[2].replace(" '", ""));
                languageCode.setIso6392T(splitRow[3].replace(" '", ""));
                languageCode.setIso6392B(splitRow[4].replace(" '", ""));
                languages.add(languageCode);
              } else {
                System.out.println("Skipping invalid row: " + row);
              }
            });
  }

  @Test
  @Description("GetLanguages - verify languages")
  @TmsLink("28501033")
  public void C28501033_TEST() {
    List<LanguageCode> grpcLanguages =
        mongoUtils.mapGrpcObjectsToPojo(
            languagesClient.getLanguages().getLanguagesList(), LanguageCode.class);

    Assert.assertEquals(languages, grpcLanguages);
  }

  @Test
  @Description("GetLanguageByAttribute - get language by name")
  @TmsLink("28501034")
  public void C28501034_TEST() {
    LanguageCode languageCode = mongoUtils.getRandomItem(languages);

    LanguageCode grpcLanguage =
        mongoUtils.mapGrpcObjectToPojo(
            languagesClient.getLanguageByAttribute("name", languageCode.getName()).getLanguage(),
            LanguageCode.class);

    Assert.assertEquals(languageCode, grpcLanguage);
  }

  @Test
  @Description("GetLanguageByAttribute - get language by nativeName")
  @TmsLink("28501035")
  public void C28501035_TEST() {
    LanguageCode languageCode = mongoUtils.getRandomItem(languages);

    LanguageCode grpcLanguage =
        mongoUtils.mapGrpcObjectToPojo(
            languagesClient
                .getLanguageByAttribute("nativeName", languageCode.getNativeName())
                .getLanguage(),
            LanguageCode.class);

    Assert.assertEquals(languageCode, grpcLanguage);
  }

  @Test(
      expectedExceptions = StatusRuntimeException.class,
      expectedExceptionsMessageRegExp = "NOT_FOUND: No languages found.")
  @Description("GetLanguageByAttribute - use non existing attribute")
  @TmsLink("28501036")
  public void C28501036_TEST() {
    LanguageCode languageCode = mongoUtils.getRandomItem(languages);

    languagesClient.getLanguageByAttribute("test", languageCode.getNativeName());
  }

  @Test(
      expectedExceptions = StatusRuntimeException.class,
      expectedExceptionsMessageRegExp = "NOT_FOUND: No languages found.")
  @Description("GetLanguageByAttribute - use non existing value")
  @TmsLink("28501037")
  public void C28501037_TEST() {
    languagesClient.getLanguageByAttribute("name", "test");
  }

  @Test(
      expectedExceptions = StatusRuntimeException.class,
      expectedExceptionsMessageRegExp =
          "INVALID_ARGUMENT: Missing required parameter\\(s\\). Attribute options: name,nativeName,iso639_1,iso639_2T,iso639_2B")
  @Description("GetLanguageByAttribute - use empty value")
  @TmsLink("28501038")
  public void C28501038_TEST() {
    languagesClient.getLanguageByAttribute("name", "");
  }

  @Test(
      expectedExceptions = StatusRuntimeException.class,
      expectedExceptionsMessageRegExp =
          "INVALID_ARGUMENT: Missing required parameter\\(s\\). Attribute options: name,nativeName,iso639_1,iso639_2T,iso639_2B")
  @Description("GetLanguageByAttribute - use empty attribute")
  @TmsLink("28501039")
  public void C28501039_TEST() {
    languagesClient.getLanguageByAttribute("", "test");
  }
}
