import React, { useEffect, useState } from 'react';
import {
  CollectionFilterState,
  DropdownCollectionFilterState,
} from '../../state';
import { observer } from 'mobx-react-lite';
import { CollectionState, FiltersMap } from '@wix/bex-core';
import {
  SingleSelectFilterBase,
  SingleSelectFilterBaseProps,
} from '../SingleSelectFilterBase';
import { ListItem, useBuildGroupedOptions, useBuildOption } from '../../hooks';
import { useWixPatternsContainer } from '@wix/bex-core/react';
import {
  useFilterToolbarState,
  FilterTranslationProvider,
} from '../../providers';
import { useFilterCollectionStates } from '../../hooks/useFilterCollectionStates';
import {
  CollectionFilterInitialFetchTimingProps,
  useCollectionFilterInitialFetchTiming,
} from '../../hooks/useCollectionFilterInitialFetchTiming';

export interface SingleSelectFilterProps<V, F extends FiltersMap>
  extends Omit<
      SingleSelectFilterBaseProps<V>,
      'keyedItems' | 'options' | 'dropdownSelect'
    >,
    CollectionFilterInitialFetchTimingProps {
  /**
   * Collection state object to fetch the items for the dropdown list.<br>
   * Create using [useFilterCollection](./?path=/story/features-filter-hooks--usefiltercollection) or [useStaticListFilterCollection](./?path=/story/features-filter-hooks--usestaticlistfiltercollection).
   * @external
   */
  collection: CollectionState<V, F>;

  /**
   * A function that returns a [ListItemSelectProps](https://www.docs.wixdesignsystem.com/?path=/story/components-form-dropdownlistitems--listitemselect) extended by `{sectionId?: string}`<br/>
   * (Optional)
   * @external
   */
  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 (see sections example). <br/>
   * (Optional)
   * @external
   */
  renderSection?: SingleSelectFilterBaseProps<V>['renderSection'];
}

function _SingleSelectFilter<V, F extends FiltersMap>(
  props: SingleSelectFilterProps<V, F>,
) {
  const { filter, collection, renderItem, renderSection, ...rest } = props;

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

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

  const [{ dropdownSelect, init }] = useState(
    () =>
      new DropdownCollectionFilterState({
        collectionFilter,
        resetOnClose: false,
        container,
        toolbar,
      }),
  );

  const {
    query: { search },
  } = collection;

  const { skipInitialFetch, onFocus } =
    useCollectionFilterInitialFetchTiming(props);

  useEffect(() => init({ skipInitialFetch }), []);

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

  const options = useBuildGroupedOptions({
    items: keyedItems.map(
      useBuildOption({
        filter,
        renderItem,
      }),
    ),
    renderSection,
  });

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

  return (
    <SingleSelectFilterBase
      {...rest}
      fixedFooter={fixedFooter}
      infiniteScroll
      value={search.value}
      onChange={(e) => {
        collection.search(e.target.value, { clearResult: true });
      }}
      onFocus={onFocus}
      filter={filter}
      options={options}
      renderItem={renderItem}
      dropdownSelect={dropdownSelect}
      hasMore={!showInitialLoader && !fetchedLastPage}
      loadMore={collection.fetchNextPageIfNeeded}
    />
  );
}

const SingleSelectFilterInternal = observer(_SingleSelectFilter);

export function SingleSelectFilter<V, F extends FiltersMap>(
  props: SingleSelectFilterProps<V, F>,
) {
  return (
    <FilterTranslationProvider>
      <SingleSelectFilterInternal {...props} />
    </FilterTranslationProvider>
  );
}
