import type { ChangeEvent } from 'react';
import { useState } from 'react';
import type { FormContextType, RJSFSchema, StrictRJSFSchema, WidgetProps } from '@rjsf/utils';
import { ariaDescribedByIds, getInputProps } from '@rjsf/utils';
import type { AutoCompleteCompleteEvent } from 'primereact/autocomplete';
import { AutoComplete } from 'primereact/autocomplete';

/** The `AutoCompleteWidget` is a widget for rendering a field with options.
 *  This is used instead of the base input template if the schema has examples.
 *
 * @param props - The `WidgetProps` for this component
 */
export default function AutoCompleteWidget<
  T = any,
  S extends StrictRJSFSchema = RJSFSchema,
  F extends FormContextType = any,
>(props: WidgetProps<T, S, F>) {
  const {
    id,
    placeholder,
    value,
    required,
    readonly,
    disabled,
    onChange,
    onChangeOverride,
    onBlur,
    onFocus,
    autofocus,
    options,
    schema,
    type,
    rawErrors = [],
  } = props;
  const inputProps = getInputProps<T, S, F>(schema, type, options);
  const primeProps = (options.prime || {}) as object;
  const handleChange = ({ target: { value: newValue } }: ChangeEvent<HTMLInputElement>) =>
    onChange(newValue === '' ? options.emptyValue : newValue);
  const handleBlur = () => onBlur && onBlur(id, value);
  const handleFocus = () => onFocus && onFocus(id, value);

  const examples = (schema.examples as string[]).concat(
    schema.default && !(schema.examples as string[]).includes(schema.default.toString())
      ? [schema.default.toString()]
      : [],
  );

  const [items, setItems] = useState<string[]>([]);

  const search = (event: AutoCompleteCompleteEvent) => {
    setItems(examples.filter((example) => example.toString().toLowerCase().includes(event.query.toLowerCase())));
  };

  return (
    <AutoComplete
      id={id}
      name={id}
      placeholder={placeholder}
      {...primeProps}
      {...inputProps}
      loadingIcon={null}
      required={required}
      autoFocus={autofocus}
      disabled={disabled || readonly}
      suggestions={items}
      completeMethod={search}
      value={value || value === 0 ? value : ''}
      dropdown
      invalid={rawErrors.length > 0}
      onChange={onChangeOverride || handleChange}
      onBlur={handleBlur}
      onFocus={handleFocus}
      aria-describedby={ariaDescribedByIds(id, !!schema.examples)}
      /* Make autocomplete look like a dropdown, which looks much nicer */
      pt={{
        root: {
          className: 'p-dropdown',
        },
        input: {
          root: {
            style: { border: 'none' },
          },
        },
        dropdownButton: {
          root: {
            className: 'p-button-text p-button-secondary',
          },
        },
      }}
    />
  );
}
