import { UniDriver } from '@wix/wix-ui-test-utils/unidriver';
import { baseUniDriverFactory } from '../../../unidriver';
import {
  ButtonUniDriver,
  EmptyStateUniDriver,
  LoaderUniDriver,
  PopoverUniDriver,
  SearchUniDriver,
  SelectorListUniDriver,
  TagUniDriver,
  TextButtonUniDriver,
} from '@wix/design-system/dist/testkit/unidriver';
import { ManageTagsModalUniDriver } from '../ManageTags/ManageTagsModal/ManageTagsModal.uni.driver';
import { AsyncJobProgressModalUniDriver } from './AsyncJobProgressModal.uni.driver';

export function BulkAssignTagsPopoverUniDriver(
  base: UniDriver,
  body: UniDriver,
) {
  const popoverBase = () =>
    PopoverUniDriver(base.$('[data-hook="bulk-assign-tags-popover"]'), body);

  const getContentElement = async () =>
    popoverBase().getContentElementUniDriver();

  const getInnerPopoverDriver = async <T>(
    dataHook: string,
    driverConstructor: (base: UniDriver, body: UniDriver) => T,
  ): Promise<T> => {
    const contentElement = await getContentElement();
    return driverConstructor(contentElement.$(`[data-hook=${dataHook}]`), body);
  };

  const getTagsListDriver = async () =>
    getInnerPopoverDriver(
      'bulk-assign-tags-selector-list',
      SelectorListUniDriver,
    );

  const getCloseButtonDriver = async () =>
    getInnerPopoverDriver('bulk-assign-tags-close-button', ButtonUniDriver);

  const getApplyButtonDriver = async () =>
    getInnerPopoverDriver('bulk-assign-tags-apply-button', ButtonUniDriver);

  const getCreateTagButtonDriver = async () =>
    getInnerPopoverDriver(
      'bulk-assign-tags-create-tag-button',
      ButtonUniDriver,
    );

  const getManageTagsButtonDriver = async () =>
    getInnerPopoverDriver(
      'bulk-assign-tags-manage-tags-button',
      TextButtonUniDriver,
    );

  const getEmptyStateDriver = async () =>
    getInnerPopoverDriver('bulk-assign-tags-empty-state', EmptyStateUniDriver);

  const getErrorStateDriver = async () =>
    getInnerPopoverDriver('bulk-assign-tags-error-state', EmptyStateUniDriver);

  const getErrorStateRetryButtonDriver = async () =>
    getInnerPopoverDriver(
      'bulk-assign-tags-error-state-retry-button',
      ButtonUniDriver,
    );

  const getLoaderDriver = async () =>
    getInnerPopoverDriver('bulk-assign-tags-loading-state', LoaderUniDriver);

  const enterSearchValue = async (value: string) => {
    const contentElement = await getContentElement();
    const tagsListDriver = await getTagsListDriver();
    const isEmptyState = await tagsListDriver.showsEmptyState();
    if (isEmptyState) {
      await SearchUniDriver(
        contentElement.$('[data-hook="bulk-assign-tags-empty-state-search"]'),
        body,
      ).inputDriver.enterText(value);
    } else {
      await tagsListDriver.enterSearchValue(value);
    }
  };

  const getTagDriverAt = async (idx: number) =>
    getInnerPopoverDriver(`bulk-assign-tags-tag-${idx}`, TagUniDriver);

  return {
    ...baseUniDriverFactory(base),
    asyncJobProgressModal: () => AsyncJobProgressModalUniDriver(base, body),
    popoverExists: () => popoverBase().exists(),
    clickOutside: () => popoverBase().clickOutside(),
    tagsSelectorlistExist: async () => (await getTagsListDriver()).exists(),
    enterSearchValue,
    clickSearchInputClear: async () =>
      (await getTagsListDriver()).clickSearchInputClear(),
    isSelectorCheckedAt: async (idx: number) =>
      (await getTagsListDriver()).isSelectorCheckedAt(idx),
    isSelectorIsIndeterminateAt: async (idx: number) =>
      (await getTagsListDriver()).isSelectorIsIndeterminateAt(idx),
    tagsListExists: async () => (await getTagsListDriver()).listExists(),
    numberOfItemsInList: async () =>
      (await getTagsListDriver()).numberOfItemsInList(),
    getTagLabelAt: async (idx: number) =>
      (await getTagDriverAt(idx)).getLabel(),
    toggleSelectorAt: async (idx: number) =>
      (await getTagsListDriver()).toggleSelectorAt(idx),
    closeButtonExists: async () => (await getCloseButtonDriver()).exists(),
    clickCloseButton: async () => (await getCloseButtonDriver()).click(),
    applyButtonExists: async () => (await getApplyButtonDriver()).exists(),
    clickApplyButton: async () => (await getApplyButtonDriver()).click(),
    createTagButtonExists: async () =>
      (await getCreateTagButtonDriver()).exists(),
    clickCreateTagButton: async () =>
      (await getCreateTagButtonDriver()).click(),
    manageTagsButtonExists: async () =>
      (await getManageTagsButtonDriver()).exists(),
    clickManageTagsButton: async () =>
      (await getManageTagsButtonDriver()).click(),
    manageTagsModal: () => ManageTagsModalUniDriver(base, body),
    emptyStateExists: async () => (await getEmptyStateDriver()).exists(),
    errorStateExists: async () => (await getErrorStateDriver()).exists(),
    errorStateRetryButtonExists: async () =>
      (await getErrorStateRetryButtonDriver()).exists(),
    clickErrorStateRetryButton: async () =>
      (await getErrorStateRetryButtonDriver()).click(),
    isLoading: async () => (await getLoaderDriver()).exists(),
    isContentElementExists: () => popoverBase().isContentElementExists(),
    getContentElement: () => popoverBase().getContentElement(),
  };
}
