import React, { useEffect, useState } from 'react';
import { CollectionFilterState } from '../../state';
import { observer } from 'mobx-react-lite';
import { CollectionState, Filter, FiltersMap, KeyedItem } from '@wix/bex-core';
import {
  AutoComplete,
  AutoCompleteProps,
  DropdownLayoutOption,
} from '@wix/design-system';
import { ListItem, useBuildGroupedOptions, useBuildOption } from '../../hooks';
import { SingleSelectFilterBaseProps } from '../SingleSelectFilterBase';
import { useWixPatternsContainer } from '@wix/bex-core/react';
import {
  useFilterToolbarState,
  useDropdownTranslationContext,
} from '../../providers';
import { FilterProps } from '../../model';
import { useFilterCollectionStates } from '../../hooks/useFilterCollectionStates';
import { AutoCompleteFilterState } from '../AutoCompleteFilter/AutoCompleteFilterState';

export type KeyedItemOption<T> = DropdownLayoutOption & {
  keyedItem: KeyedItem<T>;
};

export interface CollectionAutoCompleteProps<V, F extends FiltersMap>
  extends Omit<AutoCompleteProps, 'options'>,
    FilterProps<V[]> {
  /**
   * [ArrayFilter](./?path=/story/features-filter-factories--arrayfilter) state object
   */
  filter: Filter<V[]>;
  /**
   * Function that returns a [ListItemSelectProps](https://www.docs.wixdesignsystem.com/?path=/story/components-form-dropdownlistitems--listitemselect) extended by `{section?: string}`.
   */
  renderItem?: (item: V, index: number) => ListItem;
  /**
   * A function that returns  [ListItemSectionProps](https://www.docs.wixdesignsystem.com/?path=/story/components-form-dropdownlistitems--listitemsection) <br/>
   * According to make it works you need return `sectionId` in `renderItem` method. <br/>
   * ⚠️ Server should return section items sorted by sections in strict order. Otherwise, when using infinite scrolling the behavior of the sections will be unexpected. <br/>
   * (Optional)
   */
  renderSection?: SingleSelectFilterBaseProps<V>['renderSection'];
  /**
   * A collection state object to fetch the dropdown items.<br>
   * Typically, a collection created using [useFilterCollection](./?path=/story/features-filter-hooks--usefiltercollection) hook.
   */
  collection: CollectionState<V, F>;
}

function _CollectionAutoComplete<V, F extends FiltersMap>(
  props: CollectionAutoCompleteProps<V, F>,
) {
  const {
    filter,
    collection,
    renderItem,
    renderSection,
    onSelect,
    onClear,
    readOnly,
    placeholder,
    ...rest
  } = props;

  const container = useWixPatternsContainer();
  const toolbar = useFilterToolbarState();

  const [collectionFilter] = useState(
    () =>
      new CollectionFilterState({
        collection,
        filter,
      }),
  );

  const [state] = useState(
    () =>
      new AutoCompleteFilterState({
        collectionFilter,
        resetOnClose: false,
        container,
        toolbar,
      }),
  );

  const { translate } = useDropdownTranslationContext();

  useEffect(() => {
    return state.init();
  }, []);

  const {
    result: { keyedItems },
    fetchedLastPage,
  } = collection;

  const buildOption = useBuildOption({
    filter,
    renderItem,
  });

  const builtOptions = keyedItems.map(buildOption);
  const options = useBuildGroupedOptions({
    items: builtOptions,
    renderSection,
  });

  const { fixedFooter, showInitialLoader } = useFilterCollectionStates({
    collection,
    fixedFooter: rest.fixedFooter,
  });

  return (
    <AutoComplete
      dataHook={`collection-filter-${filter.name}`}
      closeOnSelect
      border="round"
      options={options}
      onClose={() => {
        state.dropdown.dropdownSelect.close();
        state.onInputBlur();
      }}
      onBlur={state.onInputBlur}
      readOnly={readOnly}
      clearButton={!readOnly}
      onClear={
        !readOnly
          ? (e) => {
              onClear?.(e);
              state.clearSelectionAndSearch();
            }
          : undefined
      }
      placeholder={placeholder ?? translate('placeholder')}
      onSelect={(option, sameOptionWasPicked) => {
        const { keyedItem } = option as KeyedItemOption<V>;
        state.dropdown.dropdownSelect.setSingle(keyedItem);
        onSelect?.(option, sameOptionWasPicked);
        state.searchInputValue = state.collection.itemName(keyedItem.item);
      }}
      infiniteScroll
      value={state.searchInputValue}
      onChange={(e) => {
        state.searchInputValue = e.target.value;
        collection.search(e.target.value, { clearResult: true });
      }}
      hasMore={!showInitialLoader && !fetchedLastPage}
      loadMore={collection.fetchNextPageIfNeeded}
      {...rest}
      fixedFooter={fixedFooter}
    />
  );
}

export const CollectionAutoComplete = observer(_CollectionAutoComplete);
