import { UniDriver } from '@wix/wix-ui-test-utils/unidriver';
import { baseUniDriverFactory } from '../../unidriver';
import {
  CardHeaderUniDriver,
  MultiSelectUniDriver,
  ButtonUniDriver,
  TextButtonUniDriver,
  TextUniDriver,
  TagUniDriver,
} from '@wix/design-system/dist/testkit/unidriver';
import { ManageTagsModalUniDriver } from '../Tags/ManageTags/ManageTagsModal/ManageTagsModal.uni.driver';
import CardContainerUniDriver from '../CardContainer/CardContainer.uni.driver';

export default (base: UniDriver, body: UniDriver) => {
  const cardHeader = () =>
    CardHeaderUniDriver(base.$(`[data-hook="tags-widget-card-header"]`), base);
  const multiSelect = () =>
    MultiSelectUniDriver(
      base.$(`[data-hook="tags-widget-multi-select"]`),
      body,
    );

  const manageTagsButton = () => {
    return ButtonUniDriver(base.$(`[data-hook="manage-tags-cta"]`), body);
  };

  const assignTagsButton = () => {
    return TextButtonUniDriver(base.$(`[data-hook="assign-tags-cta"]`), body);
  };

  const manageTagsModal = () => ManageTagsModalUniDriver(base, body);
  const cardContainer = () => CardContainerUniDriver(base, body);

  const getTagById = (tagId: string) =>
    multiSelect().driver.getTagDriverByTagId(tagId);
  const selectOptionById = (tagId: string) =>
    multiSelect().driver.selectOptionById(tagId);

  const readOnlyEmptyStateText = () =>
    TextUniDriver(
      base.$(`[data-hook="tags-widget-readonly-empty-state"]`),
      body,
    );

  const getReadOnlyTagAt = (index: number) =>
    TagUniDriver(base.$$(`[data-hook="tags-widget-tag"]`).at(index), body);

  const numberOfReadOnlyTags = () =>
    base.$$(`[data-hook="tags-widget-tag"]`).count();

  const inlineErrorText = () => {
    return TextUniDriver(base.$(`[data-hook="tags-widget-error-text"]`), body);
  };

  const inlineRetryButton = () => {
    return TextButtonUniDriver(
      base.$(`[data-hook="tags-widget-retry-button"]`),
      body,
    );
  };

  return {
    manageTagsModal,
    modalExists: () => manageTagsModal().exists(),
    cardHeader: () => cardHeader(),
    title: () => cardHeader().title(),
    subtitle: () => cardHeader().subtitle(),
    inputPlaceholder: () => multiSelect().inputDriver.getPlaceholder(),
    numberOfTags: () => multiSelect().driver.numberOfTags(),
    optionsLength: () => multiSelect().dropdownLayoutDriver.optionsLength(),
    removeTag: async (tagId: string) => {
      const tag = await getTagById(tagId);
      await tag.removeTag();
    },
    optionContentAt: (index: number) =>
      multiSelect().dropdownLayoutDriver.optionContentAt(index),
    clickAtOption: (index: number) =>
      multiSelect().dropdownLayoutDriver.clickAtOption(index),
    enterText: (text: string) => multiSelect().inputDriver.enterText(text),
    getTagLabelAt: (index: number) => multiSelect().driver.getTagLabelAt(index),
    customSuffixExists: () => multiSelect().driver.customSuffixExists(),
    selectOptionById,
    selectAddTagOption: () => selectOptionById('add-item-option'),
    dropdownLayout: () => multiSelect().dropdownLayoutDriver,
    manageTagsButtonExists: () => manageTagsButton().exists(),
    clickManageTagsButton: () => manageTagsButton().click(),
    clickAssignTagsButton: () => assignTagsButton().click(),
    focus: () => multiSelect().inputDriver.focus(),
    blur: () => multiSelect().inputDriver.blur(),
    /** Returns the error state subtitle */
    getErrorSubtitle: () => cardContainer().getErrorState().getSubtitleText(),
    /** Clicks on try again button when error state visible */
    clickTryAgain: () =>
      cardContainer().getErrorState().getRetryButton().click(),
    /** Gets try again button text */
    getTryAgainContent: () =>
      cardContainer().getErrorState().getRetryButton().getButtonTextContent(),
    showsSkeletonHeader: () => cardContainer().showsSkeletonHeader(),
    getReadOnlyEmptyStateContent: () => readOnlyEmptyStateText().getText(),
    getReadOnlyTagAt,
    numberOfReadOnlyTags,
    /** Returns the error text */
    getInlineErrorText: () => inlineErrorText().getText(),
    /** Clicks on try again button when error state visible */
    clickInlineTryAgain: () => inlineRetryButton().click(),
    /** Gets try again button text */
    getInlineTryAgainText: () => inlineRetryButton().getButtonTextContent(),
    /** Return true id skeleton os shown */
    showsInlineSkeleton: () =>
      base.$('[data-hook="tags-widget-skeleton"]').exists(),
    ...baseUniDriverFactory(base),
  };
};
