package old;

import com.google.common.collect.Comparators;
import old.core.Browser;
import old.core.BrowserArgumentProvider;
import org.apache.commons.lang.RandomStringUtils;
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 old.page.AdminUserPage;

import java.util.Arrays;
import java.util.List;

import static org.apache.commons.lang.StringUtils.containsIgnoreCase;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

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

  private AdminUserPage adminUserPage;
  private String oldName;
  private String email;

  private static final String USER_PASSWORD = "test";
  private static final String USER_PASSWORD_2 = "test2";
  private static final String ORGANIZATION = "Default";
  private static final String FULL_ORGANIZATION_NAME = "Default Organization";
  private static final String BPMN_ADMIN_GROUP = "BPMN Admin";
  private static final String BPMN_USER_GROUP = "BPMN User";
  private static final String BPMN_SUPERUSER_GROUP = "BPMN Superuser";

  private static final String SECURITY_GROUP = "Security Admin";

  public AdminUserIT() {
    super();
  }

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

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

    if (containsIgnoreCase(testName, "sorting")) {
      String userAccId = EXECUTION_MANAGER.getUserAccountIdByName(name);
      EXECUTION_MANAGER.deleteUserLinkedGroups(userAccId);
    }

    if (containsIgnoreCase(testName, "visibility")) {
      String userAccountId = EXECUTION_MANAGER.getUserAccountIdByName(name);
      EXECUTION_MANAGER.deleteUserLinkedGroups(userAccountId);
    }

    EXECUTION_MANAGER.deleteTestUser(name);
  }

  @ParameterizedTest
  @ArgumentsSource(BrowserArgumentProvider.class)
  public void createUser(Browser browser) {
    openBrowserAndAdminPage(browser);
    adminUserPage.clickCreateButton();
    adminUserPage.waitForVisibilityOf(adminUserPage.lastNameField);
    adminUserPage.fillUserFullName(name);
    email = randomEmail();
    adminUserPage.fillUserCredentials(name, USER_PASSWORD, email, ORGANIZATION, FULL_ORGANIZATION_NAME);
    adminUserPage.addGroup(BPMN_ADMIN_GROUP);
    adminUserPage.clickSaveButton();
    assertTrue(EXECUTION_MANAGER.hasUserByData(name, email));

    adminUserPage.searchUser(name);
    adminUserPage.clickOnUserInTable(name);
    assertEquals(1, adminUserPage.getListOfGroupsFromTable().size());
    assertEquals(BPMN_ADMIN_GROUP, adminUserPage.getListOfGroupsFromTable().get(0).getText());
  }

  @ParameterizedTest
  @ArgumentsSource(BrowserArgumentProvider.class)
  public void searchUser(Browser browser) {
    openBrowserAndAdminPage(browser);
    EXECUTION_MANAGER.createUser(name, ORGANIZATION_ID);

    adminUserPage.searchUser(name);
    assertEquals(1, adminUserPage.getListOfLastNamesFromTable().size());
    assertEquals(1, adminUserPage.getListOfFirstNamesFromTable().size());
    assertEquals(1, adminUserPage.getListOfMiddleNamesFromTable().size());

    assertEquals(name, adminUserPage.getListOfLastNamesFromTable().get(0).getText());
    assertEquals(name, adminUserPage.getListOfFirstNamesFromTable().get(0).getText());
    assertEquals(name, adminUserPage.getListOfMiddleNamesFromTable().get(0).getText());
  }

  @ParameterizedTest
  @ArgumentsSource(BrowserArgumentProvider.class)
  public void editUser(Browser browser) {
    openBrowserAndAdminPage(browser);
    EXECUTION_MANAGER.createUser(name, ORGANIZATION_ID);

    adminUserPage.searchUser(name);
    adminUserPage.clickOnUserInTable(name);
    adminUserPage.clickEditButton();
    adminUserPage.waitForVisibilityOf(adminUserPage.lastNameField);
    oldName = name;
    name = name + "_edited";
    adminUserPage.fillUserFullName(name);
    email = randomEmail();
    adminUserPage.fillPassAndEmail(USER_PASSWORD_2, email);
    adminUserPage.addGroup(BPMN_USER_GROUP);
    adminUserPage.clickSaveButton();
    adminUserPage.waitForVisibilityOf(adminUserPage.filterPanel);
    adminUserPage.searchUser(name);
    assertEquals(1, adminUserPage.getListOfLastNamesFromTable().size());
    assertEquals(1, adminUserPage.getListOfFirstNamesFromTable().size());
    assertEquals(1, adminUserPage.getListOfMiddleNamesFromTable().size());

    assertNotEquals(oldName, adminUserPage.getListOfLastNamesFromTable().get(0).getText());
    assertNotEquals(oldName, adminUserPage.getListOfFirstNamesFromTable().get(0).getText());
    assertNotEquals(oldName, adminUserPage.getListOfMiddleNamesFromTable().get(0).getText());

    assertTrue(EXECUTION_MANAGER.hasUserByData(name, email));

    adminUserPage.clickOnUserInTable(name);
    assertEquals(1, adminUserPage.getListOfGroupsFromTable().size());
    assertEquals(BPMN_USER_GROUP, adminUserPage.getListOfGroupsFromTable().get(0).getText());
  }

  @ParameterizedTest
  @ArgumentsSource(BrowserArgumentProvider.class)
  public void deleteUser(Browser browser) {
    openBrowserAndAdminPage(browser);
    EXECUTION_MANAGER.createUser(name, ORGANIZATION_ID);

    adminUserPage.searchUser(name);
    adminUserPage.clickOnUserInTable(name);
    adminUserPage.deleteUser();

    assertTrue(adminUserPage.getListOfLastNamesFromTable().isEmpty());
    assertTrue(adminUserPage.getListOfFirstNamesFromTable().isEmpty());
    assertTrue(adminUserPage.getListOfMiddleNamesFromTable().isEmpty());
  }


  @ParameterizedTest
  @ArgumentsSource(BrowserArgumentProvider.class)
  public void attachRemoveGroup(Browser browser) {
    openBrowserAndAdminPage(browser);
    EXECUTION_MANAGER.createUser(name, ORGANIZATION_ID);

    adminUserPage.searchUser(name);
    adminUserPage.clickOnUserInTable(name);
    assertTrue(adminUserPage.getListOfGroupsFromTable().isEmpty());

    adminUserPage.clickEditButton();
    assertFalse(adminUserPage.getListOfAvailableGroupsToAdd().isEmpty());
    assertTrue(adminUserPage.getListOfAddedGroups().isEmpty());

    adminUserPage.addGroup(BPMN_ADMIN_GROUP);
    assertFalse(adminUserPage.getWebElementTexts(adminUserPage.getListOfAvailableGroupsToAdd()).contains(BPMN_ADMIN_GROUP));
    assertEquals(BPMN_ADMIN_GROUP, adminUserPage.getListOfAddedGroups().get(0).getText());
    assertEquals(1, adminUserPage.getListOfAddedGroups().size());

    adminUserPage.clickSaveButton();
    adminUserPage.searchUser(name);
    adminUserPage.clickOnUserInTable(name);
    assertEquals(1, adminUserPage.getListOfGroupsFromTable().size());
    assertEquals(BPMN_ADMIN_GROUP, adminUserPage.getListOfGroupsFromTable().get(0).getText());

    adminUserPage.clickEditButton();
    adminUserPage.removeGroup(BPMN_ADMIN_GROUP);
    assertTrue(adminUserPage.getWebElementTexts(adminUserPage.getListOfAvailableGroupsToAdd()).contains(BPMN_ADMIN_GROUP));
    assertTrue(adminUserPage.getListOfAddedGroups().isEmpty());

    adminUserPage.clickSaveButton();
    adminUserPage.searchUser(name);
    adminUserPage.clickOnUserInTable(name);
    assertTrue(adminUserPage.getListOfGroupsFromTable().isEmpty());
  }

  @ParameterizedTest
  @ArgumentsSource(BrowserArgumentProvider.class)
  public void attachRemoveAllGroups(Browser browser) {
    openBrowserAndAdminPage(browser);
    EXECUTION_MANAGER.createUser(name, ORGANIZATION_ID);
    List<String> groupNamesFromTable = EXECUTION_MANAGER.getGroupNamesFromUserGroup();
    List<String> expectedGroups = Arrays.asList(BPMN_ADMIN_GROUP, BPMN_USER_GROUP,
        BPMN_SUPERUSER_GROUP);

    adminUserPage.searchUser(name);
    adminUserPage.clickOnUserInTable(name);
    assertTrue(adminUserPage.getListOfGroupsFromTable().isEmpty());

    adminUserPage.clickEditButton();
    assertFalse(adminUserPage.getListOfAvailableGroupsToAdd().isEmpty());
    assertTrue(adminUserPage.getListOfAddedGroups().isEmpty());

    adminUserPage.addAllGroups();
    assertTrue(adminUserPage.isAvailableGridEmpty(groupNamesFromTable));
    assertFalse(adminUserPage.getListOfAddedGroups().isEmpty());

    adminUserPage.removeAllGroups();
    assertFalse(adminUserPage.getListOfAvailableGroupsToAdd().isEmpty());
    assertTrue(adminUserPage.getListOfAddedGroups().isEmpty());

    adminUserPage.addGroup(BPMN_ADMIN_GROUP);
    adminUserPage.addGroup(BPMN_USER_GROUP);
    adminUserPage.addGroup(BPMN_SUPERUSER_GROUP);
    adminUserPage.clickSaveButton();
    adminUserPage.searchUser(name);
    adminUserPage.clickOnUserInTable(name);
    assertEquals(3, adminUserPage.getListOfGroupsFromTable().size());
    assertTrue(adminUserPage.getWebElementTexts(adminUserPage.getListOfGroupsFromTable()).containsAll(expectedGroups));

    adminUserPage.clickEditButton();
    adminUserPage.removeAllGroups();
    adminUserPage.clickSaveButton();
    adminUserPage.searchUser(name);
    adminUserPage.clickOnUserInTable(name);
    assertTrue(adminUserPage.getListOfGroupsFromTable().isEmpty());
  }

  @ParameterizedTest
  @ArgumentsSource(BrowserArgumentProvider.class)
  public void accessLevelGroupVisibility(Browser browser) {
    openBrowserAndAdminPage(browser);
    EXECUTION_MANAGER.createUserBindGroups(name, ORGANIZATION_ID, SECURITY_ADMIN_GROUP_ID);

    adminUserPage.searchUser(name);
    adminUserPage.clickOnUserInTable(name);
    assertTrue(adminUserPage.getWebElementTexts(adminUserPage.getListOfGroupsFromTable()).contains(SECURITY_GROUP));

    adminUserPage.clickEditButton();
    assertFalse(adminUserPage.getWebElementTexts(adminUserPage.getListOfAvailableGroupsToAdd()).contains(SECURITY_GROUP));
    assertTrue(adminUserPage.getWebElementTexts(adminUserPage.getListOfAddedGroups()).contains(SECURITY_GROUP));

    adminUserPage.logout();
    initQaAdminCredentials();
    login(login, password);
    adminUserPage = inboxPage.startAdminUser();
    adminUserPage.searchUser(name);
    adminUserPage.clickOnUserInTable(name);
    assertFalse(adminUserPage.getWebElementTexts(adminUserPage.getListOfGroupsFromTable()).contains(SECURITY_GROUP));

    adminUserPage.clickEditButton();
    assertFalse(adminUserPage.getWebElementTexts(adminUserPage.getListOfAvailableGroupsToAdd()).contains(SECURITY_GROUP));
    assertFalse(adminUserPage.getWebElementTexts(adminUserPage.getListOfAddedGroups()).contains(SECURITY_GROUP));
  }

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

    //User page sorting
    List<String> lastNamesNatural = adminUserPage.getWebElementTexts(adminUserPage.getListOfLastNamesFromTable());
    assertTrue(Comparators.isInOrder(lastNamesNatural, String.CASE_INSENSITIVE_ORDER),
        "Grid wasn't sorted");

    adminUserPage.changeUserPageGridsSort(AdminUserPage.UsersPageGrids.USERS_GRID);
    List<String> lastNamesReverse = adminUserPage.getWebElementTexts(adminUserPage.getListOfLastNamesFromTable());
    assertTrue(Comparators.isInOrder(lastNamesReverse, String.CASE_INSENSITIVE_ORDER.reversed()),
        "Grid wasn't sorted");

    adminUserPage.searchUser(name);
    adminUserPage.clickOnUserInTable(name);
    List<String> userLinkedGroupsNatural = adminUserPage.getWebElementTexts(adminUserPage.getListOfGroupsFromTable());
    assertTrue(Comparators.isInOrder(userLinkedGroupsNatural, String.CASE_INSENSITIVE_ORDER),
        "Grid wasn't sorted");

    adminUserPage.changeUserPageGridsSort(AdminUserPage.UsersPageGrids.LINKED_GROUPS_GRID);
    List<String> userLinkedGroupsReverse = adminUserPage.getWebElementTexts(adminUserPage.getListOfGroupsFromTable());
    assertTrue(Comparators.isInOrder(userLinkedGroupsReverse, String.CASE_INSENSITIVE_ORDER.reversed()),
        "Grid wasn't sorted");

    //Edit user page sorting
    adminUserPage.clickEditButton();
    List<String> availableToAddGroupsNatural = adminUserPage.getWebElementTexts(adminUserPage.getListOfAvailableGroupsToAdd());
    assertTrue(Comparators.isInOrder(availableToAddGroupsNatural, String.CASE_INSENSITIVE_ORDER),
        "Grid wasn't sorted");

    adminUserPage.changeUserPageGridsSort(AdminUserPage.UsersPageGrids.GROUPS_TO_ADD_GRID);
    List<String> availableGroupsToAddReverse = adminUserPage.getWebElementTexts(adminUserPage.getListOfAvailableGroupsToAdd());
    assertTrue(Comparators.isInOrder(availableGroupsToAddReverse, String.CASE_INSENSITIVE_ORDER.reversed()),
        "Grid wasn't sorted");

    List<String> addedGroupsNatural = adminUserPage.getWebElementTexts(adminUserPage.getListOfAddedGroups());
    assertTrue(Comparators.isInOrder(addedGroupsNatural, String.CASE_INSENSITIVE_ORDER),
        "Grid wasn't sorted");

    adminUserPage.changeUserPageGridsSort(AdminUserPage.UsersPageGrids.ADDED_GROUPS_GRID);
    List<String> addedGroupsReverse = adminUserPage.getWebElementTexts(adminUserPage.getListOfAddedGroups());
    assertTrue(Comparators.isInOrder(addedGroupsReverse, String.CASE_INSENSITIVE_ORDER.reversed()),
        "Grid wasn't sorted");

    //Create user page sorting
    adminUserPage.cancelAction();
    adminUserPage.clickCreateButton();
    List<String> groupsToAddNatural = adminUserPage.getWebElementTexts(adminUserPage.getListOfAvailableGroupsToAdd());
    assertTrue(Comparators.isInOrder(groupsToAddNatural, String.CASE_INSENSITIVE_ORDER),
        "Grid wasn't sorted");

    adminUserPage.changeUserPageGridsSort(AdminUserPage.UsersPageGrids.GROUPS_TO_ADD_GRID);
    List<String> groupsToAddReverse = adminUserPage.getWebElementTexts(adminUserPage.getListOfAvailableGroupsToAdd());
    assertTrue(Comparators.isInOrder(groupsToAddReverse, String.CASE_INSENSITIVE_ORDER.reversed()),
        "Grid wasn't sorted");

    adminUserPage.addAllGroups();
    List<String> addedGroupsInCreateFormNatural = adminUserPage.getWebElementTexts(adminUserPage.getListOfAddedGroups());
    assertTrue(Comparators.isInOrder(addedGroupsInCreateFormNatural, String.CASE_INSENSITIVE_ORDER),
        "Grid wasn't sorted");

    adminUserPage.changeUserPageGridsSort(AdminUserPage.UsersPageGrids.ADDED_GROUPS_GRID);
    List<String> addedGroupsInCreatedFormReverse = adminUserPage.getWebElementTexts(adminUserPage.getListOfAddedGroups());
    assertTrue(Comparators.isInOrder(addedGroupsInCreatedFormReverse, String.CASE_INSENSITIVE_ORDER.reversed()),
        "Grid wasn't sorted");
  }

  private void openBrowserAndAdminPage(Browser browser) {
    openBrowserAndLoginForAdmin(browser);
    initAdminName();
    adminUserPage = inboxPage.startAdminUser();
  }

  private String randomEmail() {
    String random1 = String.valueOf(20000 + (int) (Math.random() * 20000));
    String random2 = String.valueOf(20000 + (int) (Math.random() * 20000));
    return random1 + "@" + random2 + ".ru";
  }

  /*@ParameterizedTest
  @ArgumentsSource(BrowserArgumentProvider.class)
  public void addNewOrgToUser(Browser browser) {
    openBrowserAndAdminPage(browser);
    EXECUTION_MANAGER.createTestOrg(name);
    EXECUTION_MANAGER.createUser(name, ORGANIZATION_ID);

    organizationPage.clickCreateButton();
    organizationPage.waitOrgEditingPageLoading();
    organizationPage.fillOrgNameAndCode(name2);
    organizationPage.chooseParentOrg(DEFAULT_ORG);
    organizationPage.clickSaveButton();
    AdminUserPage adminUserPage = inboxPage.startAdminUser();
    adminUserPage.searchUser(name);
    adminUserPage.clickOnUserInTable(name);
    adminUserPage.clickEditButton();
    adminUserPage.chooseUserOrganization(name2);
    adminUserPage.fillPass(name);
    adminUserPage.clickSaveButton();
  }

  private void openBrowserAndAdminPage(Browser browser) {
    openBrowserAndLoginForAdmin(browser);
    initAdminName();
    name2 = name.substring(0, 3) + "2" + name.substring(3);
    name3 = name.substring(0, 3) + "3" + name.substring(3);
    organizationPage = inboxPage.startAdminOrganization();
    assertFalse(isElementEnabled(DELETE_BUTTON));
  }*/
}