import { useCallback, useMemo, useState } from 'react';
import { useFilterOptions } from '../use-filter-options';
import { usePagination, usePaginationState } from '../use-pagination';
export function usePaginatedSearchState(config) {
  const initConfig = config || {};
  const {
    searchQuery: initialQuery,
    ...initialState
  } = initConfig;
  const [searchQuery, setSearchQuery] = useState(initialQuery || '');
  const pagination = usePaginationState(initialState);
  const setSearchQueryAndResetPage = useCallback(query => {
    setSearchQuery(query);
    pagination.setPage(0);
  }, [pagination.setPage, setSearchQuery]);
  return useMemo(() => ({
    ...pagination,
    searchQuery,
    setSearchQuery: setSearchQueryAndResetPage
  }), [pagination, searchQuery, setSearchQueryAndResetPage]);
}

/**
 * @typedef PaginatedSearch
 * @property {array} items
 * @property {array} unpaginatedFilteredItems - all items passed through search filter, unpaginated
 * @property {number} pageSize - items per page
 * @property {number} currentPage - current page number
 * @property {number} total - total items count
 * @property {string} searchValue
 * @property {function} setPage
 * @property {function} setPageSize
 * @property {function} setTotal
 * @property {func} setSearchValue
 * */

const defaultOptions = {
  searchFields: ['name']
};

/**
 * A hook that combines filtering and pagination for an array of items
 *
 * @param {array} [items=[]] Array of items that should be filtered
 * and paginated
 * @param {options} {
 *     searchFields = ['name'],
 *     filterFunction,
 *     paginationDefaults,
 *   } - options to configure search and provide
 * initial state for pagination, can be undefined
 * @returns {PaginatedSearch} - object containing filtered items,
 * pagination hook state and search query
 */

export function usePaginatedSearch(items = [], {
  searchFields = defaultOptions.searchFields,
  filterFunction,
  defaultPageSize
} = defaultOptions) {
  const [searchValue, setSearchValue] = useState('');
  const filteredItems = useFilterOptions(items, searchValue, searchFields, filterFunction);
  const pagination = usePagination(filteredItems, defaultPageSize);
  const setSearchValueAndReset = useCallback(newSearchValue => {
    setSearchValue(newSearchValue);
    pagination.setPage(0);
  }, [pagination.currentPage, pagination.pageSize, pagination.setPage, setSearchValue]);
  return useMemo(() => ({
    ...pagination,
    unpaginatedFilteredItems: filteredItems,
    searchValue,
    setSearchValue: setSearchValueAndReset
  }), [pagination, searchValue, setSearchValueAndReset]);
}

/**
 * Example:
 ```
  const fullListOfItems = getALotOfItemsSomehow();
  const {
    items,
    searchValue,
    total,
    currentPage,
    pageSize,
    setSearchValue,
    setPage,
    setPageSize,
  } = usePaginatedSearch(fullListOfItems);

  return (
    <React.Fragment>
      <Search value={searchValue} onChange={setSearchValue} />
      <PaginationControls
        total={total}
        currentPage={currentPage}
        pageSize={pageSize}
        availableSizes={[20, 50, 100]}
        onPageChange={setPage}
        onPageSizeChange={setPageSize}
      />
      {items.map(item => (
        <div key={item.id}>{item.name}</div>
      ))}
    </React.Fragment>
  );
 ```
 */