import { useCallback, useEffect, useRef, useState } from 'react';
import type { BaseSelectProps } from './BaseSelect';
import { BaseSelect } from './BaseSelect';
import type { SelectOption } from './types';

export type AsyncMultiSelectProps<TValue = string> = {
  loadOptions: (query: string) => Promise<SelectOption<TValue>[]>;
  defaultOptions?: SelectOption<TValue>[];
  debounceMs?: number;
} & Omit<BaseSelectProps<TValue>, 'options' | 'isLoading' | 'isMulti'>;

export function AsyncMultiSelect<TValue = string>({
  loadOptions,
  defaultOptions = [],
  debounceMs = 250,
  ...rest
}: AsyncMultiSelectProps<TValue>) {
  const [options, setOptions] = useState<SelectOption<TValue>[]>(defaultOptions);
  const [isLoading, setIsLoading] = useState(false);
  const reqId = useRef(0);
  const timer = useRef<number | null>(null);

  const onQueryChange = useCallback(
    (q: string) => {
      if (timer.current != null) window.clearTimeout(timer.current);
      timer.current = window.setTimeout(async () => {
        const my = ++reqId.current;
        setIsLoading(true);
        try {
          const next = await loadOptions(q);
          if (reqId.current !== my) return;
          setOptions(next);
        } finally {
          if (reqId.current === my) setIsLoading(false);
        }
      }, debounceMs);
    },
    [debounceMs, loadOptions]
  );

  useEffect(() => {
    return () => {
      if (timer.current != null) window.clearTimeout(timer.current);
    };
  }, []);

  return (
    <BaseSelect<TValue>
      {...rest}
      isMulti
      closeMenuOnSelect={false}
      options={options}
      isLoading={isLoading}
      onQueryChange={onQueryChange}
    />
  );
}

