import clsx from 'clsx';
import { debounce } from 'lodash';
import React, { ChangeEvent, useCallback, useEffect, useState } from 'react';
import { Option } from '../../Filters.model';
import {
  OptionFilterProps,
  OptionsFilter,
} from '../OptionsFilter/OptionsFilter';
import classes from './SearcheableOptionsFilter.scss';

interface SearcheableOptionFilterProps
  extends Omit<OptionFilterProps, 'options'> {
  optionsProvider: (searchText: string) => Option[];
  searchInputPlaceholder?: string;
  maxItems?: number;
  onSelect: (value: string, stringValue?: string) => void;

  /** Optional id for the input field */
  inputId?: string;
}

export const SearcheableOptionsFilter: React.FC<
  SearcheableOptionFilterProps
> = ({
  optionsProvider,
  searchInputPlaceholder = '',
  maxItems = 10,
  onSelect,
  className,
  inputId,
  ...rest
}) => {
  const [options, setOptions] = useState<Option[]>([]);

  const getOptions = useCallback(
    async (value: string) => {
      setOptions(await optionsProvider(value));
    },
    [optionsProvider],
  );

  useEffect(() => {
    getOptions('');
  }, [getOptions]);

  const onChangeHandler = async (
    e: ChangeEvent<HTMLInputElement>,
  ): Promise<void> => {
    const value = e.target.value;
    getOptions(value);
  };

  return (
    <>
      <div
        className={clsx(
          classes.container,
          'free-text-filter-container',
          className,
        )}
      >
        <input
          id={inputId}
          autoFocus
          onChange={debounce(onChangeHandler, 500)}
          className={classes.inputValue}
          placeholder={searchInputPlaceholder}
        />
      </div>
      <OptionsFilter
        options={options?.slice(0, maxItems)}
        {...rest}
        onSelect={(value) =>
          onSelect(
            value,
            options.find((option) => option.value === value)?.label,
          )
        }
      />
      {options?.length === 0 && (
        <div className={clsx(classes.noDataMessage)}>
          <p>No items found</p>
        </div>
      )}
    </>
  );
};
