package old;

import com.google.common.collect.Comparators;
import old.core.Browser;
import old.core.BrowserArgumentProvider;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.TestInfo;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ArgumentsSource;
import org.openqa.selenium.WebElement;
import old.page.AdminGroupPage;
import old.page.AdminRolePage;

import java.util.List;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

/**
 * @author kote
 */
public class AdminRoleIT extends BaseComponentIT {

  private static final String COL_ID = "role$name";
  private static final String COL_ID_CREATED = "role$created";
  private static final String COL_ID_UPDATED = "role$updated";

  private AdminRolePage adminRolePage;
  private String oldName;

  public AdminRoleIT() {
    super();
  }

  @AfterEach
  public void afterEachTest(TestInfo testInfo) {
    String testName = testInfo.getTestMethod().toString();

    if (testName.contains("Group")) {
      EXECUTION_MANAGER.deleteTestGroup(name);
    }

    if (testName.contains("edit")) {
      EXECUTION_MANAGER.deleteTestRole(oldName);
    }

    if (testName.contains("Sorting")) {
      String roleId = EXECUTION_MANAGER.getRoleIdByName(name);
      EXECUTION_MANAGER.deleteLinkedGroupsFromRole(roleId);
    }

    EXECUTION_MANAGER.deleteTestRole(name);
  }

  @ParameterizedTest
  @ArgumentsSource(BrowserArgumentProvider.class)
  public void createRole(Browser browser) {
    openBrowserAndAdminPage(browser);
    adminRolePage.clickCreateButton();
    adminRolePage.typeText(adminRolePage.nameField, name);
    adminRolePage.clickSaveButton();
    String dateOfCreation = adminRolePage.getLocalDate();
    adminRolePage.searchRole(name);
    assertEquals(1, adminRolePage.getListOfRolesNamesFromTable(name).size());
    assertTrue(adminRolePage.getActionTime(COL_ID, name, COL_ID_CREATED).getText().contains(dateOfCreation));
  }

  @ParameterizedTest
  @ArgumentsSource(BrowserArgumentProvider.class)
  public void searchRole(Browser browser) {
    openBrowserAndAdminPage(browser);
    EXECUTION_MANAGER.createTestRole(name);

    adminRolePage.searchRole(name);
    assertEquals(1, adminRolePage.getListOfRolesNamesFromTable(name).size());
  }

  @ParameterizedTest
  @ArgumentsSource(BrowserArgumentProvider.class)
  public void editRole(Browser browser) {
    openBrowserAndAdminPage(browser);
    oldName = "old" + name;
    EXECUTION_MANAGER.createTestRole(oldName);

    adminRolePage.chooseRole(oldName);
    adminRolePage.clickEditButton();
    adminRolePage.typeText(adminRolePage.nameField, name);
    adminRolePage.clickSaveButton();
    adminRolePage.searchRole(oldName);
    assertEquals(0, adminRolePage.getListOfRolesNamesFromTable(oldName).size());

    adminRolePage.searchRole(name);
    assertEquals(1, adminRolePage.getListOfRolesNamesFromTable(name).size());

    String timeOfCreate = adminRolePage.getActionTime(COL_ID, name, COL_ID_CREATED).getText();
    String timeOfUpdate = adminRolePage.getActionTime(COL_ID, name, COL_ID_UPDATED).getText();
    assertNotEquals(timeOfCreate, timeOfUpdate);
  }

  @ParameterizedTest
  @ArgumentsSource(BrowserArgumentProvider.class)
  public void deleteRole(Browser browser) {
    openBrowserAndAdminPage(browser);
    EXECUTION_MANAGER.createTestRole(name);

    adminRolePage.waitForPageLoad();
    adminRolePage.chooseRole(name);
    adminRolePage.deleteRole();
    assertEquals(0, adminRolePage.getListOfRolesNamesFromTable(name).size());
  }

  @ParameterizedTest
  @ArgumentsSource(BrowserArgumentProvider.class)
  public void roleGroupGridContainsAttachedGroup(Browser browser) {
    openBrowserAndAdminPage(browser);
    String roleId = EXECUTION_MANAGER.generateId();
    String groupId = EXECUTION_MANAGER.generateId();
    EXECUTION_MANAGER.createBindGroupRole(name, groupId, ACCESS_LEVEL_ID, roleId);

    adminRolePage.chooseRole(name);
    WebElement gridLinkedGroup = adminRolePage.getListOfRoleLinkedGroups().get(0);
    adminRolePage.waitForTextToBePresentInElement(gridLinkedGroup, name);
    assertEquals(1, adminRolePage.getListOfRoleLinkedGroups().size());
    assertEquals(adminRolePage.getListOfRoleLinkedGroups().get(0).getText(), name);
  }

  @ParameterizedTest
  @ArgumentsSource(BrowserArgumentProvider.class)
  public void addNewRoleToGroup(Browser browser) {
    openBrowserAndAdminPage(browser);
    String groupName = name;
    EXECUTION_MANAGER.createTestGroup(groupName, ACCESS_LEVEL_ID);

    adminRolePage.clickCreateButton();
    adminRolePage.typeText(adminRolePage.nameField, name);
    adminRolePage.clickSaveButton();

    AdminGroupPage adminGroupPage = inboxPage.startAdminGroup();
    adminGroupPage.chooseGroup(groupName);
    adminGroupPage.clickEditButton();
    adminGroupPage.bindRole(name);
    assertTrue(adminGroupPage.hasRolesInTable(AdminGroupPage.GroupPageGrids.ADDED_ROLES_GRID, name));

    adminGroupPage.clickSaveButton();
    adminGroupPage.chooseGroup(groupName);
    adminGroupPage.clickEditButton();
    assertTrue(adminGroupPage.hasRolesInTable(AdminGroupPage.GroupPageGrids.ADDED_ROLES_GRID, name));
  }

  @Disabled("dev WEBBPMNEXT-7837")
  @ParameterizedTest
  @ArgumentsSource(BrowserArgumentProvider.class)
  public void roleGroupsGridSorting(Browser browser) {
    openBrowserAndAdminPage(browser);
    EXECUTION_MANAGER.createRoleBindGroups(name, BPMN_ADMIN_GROUP_ID, BPMN_USER_GROUP_ID, BPMN_SUPERUSER_GROUP_ID);

    List<String> roleNamesNatural = adminRolePage.getWebElementTexts(adminRolePage.getListOfRoles());
    assertTrue(Comparators.isInOrder(roleNamesNatural, String.CASE_INSENSITIVE_ORDER),
        "Grid wasn't sorted");

    adminRolePage.changeRolePageGridSort(AdminRolePage.RolePageGrids.ROLE_NAMES_GRID);
    List<String> roleNamesReverse = adminRolePage.getWebElementTexts(adminRolePage.getListOfRoles());
    assertTrue(Comparators.isInOrder(roleNamesReverse, String.CASE_INSENSITIVE_ORDER.reversed()),
        "Grid wasn't sorted");

    adminRolePage.chooseRole(name);
    List<String> linkedGroupsNatural = adminRolePage.getWebElementTexts(adminRolePage.getListOfRoleLinkedGroups());
    assertTrue(Comparators.isInOrder(linkedGroupsNatural, String.CASE_INSENSITIVE_ORDER),
        "Grid wasn't sorted");

    adminRolePage.changeRolePageGridSort(AdminRolePage.RolePageGrids.GROUP_NAMES_GRID);
    List<String> linkedGroupsReverse = adminRolePage.getWebElementTexts(adminRolePage.getListOfRoleLinkedGroups());
    assertTrue(Comparators.isInOrder(linkedGroupsReverse, String.CASE_INSENSITIVE_ORDER.reversed()),
        "Grid wasn't sorted");
  }

  private void openBrowserAndAdminPage(Browser browser) {
    openBrowserAndLoginForAdmin(browser);
    initAdminName();
    adminRolePage = inboxPage.startAdminRole();
  }
}