import type { ReactElement, Ref } from "react";
import type { TextFieldElementType, TextFieldProps } from "../TextField";

export type ComboboxOption =
  | string
  | { id?: string; label: string; value: string };

export type ComboboxBaseProps<T extends ComboboxOption = ComboboxOption> =
  TextFieldProps & {
    /** An icon to display in TextField (left side) */
    icon?: ReactElement;
    /** The default value of the selected option */
    defaultValue?: string | undefined;
    /** Callback when the selected option changes */
    onSelected?: ((value: T) => void) | undefined;
    optionComponent?: (
      props: Pick<ComboboxOptionProps<T>, "option" | "isHighlighted">,
    ) => ReactElement;
    /** Prefix for option data-testid attributes (default: "combobox-option") */
    optionTestIdPrefix?: string;
  };

export type ComboboxSyncProps<T extends ComboboxOption = ComboboxOption> =
  ComboboxBaseProps<T> & {
    /** The list of options to display in the dropdown */
    options: ComboboxOptions<T>;
    asyncOptions?: never;
    delay?: never;
    minSearchLength?: never;
    onSearched?: never;
  };

export type ComboboxAsyncProps<T extends ComboboxOption = ComboboxOption> =
  ComboboxBaseProps<T> & {
    options?: never;
    delay?: number;
    minSearchLength?: number | undefined;
    /** A function that returns a list of options to display in the dropdown */
    asyncOptions:
      | ((inputValue: string) => ComboboxOptions<T>)
      | ((
          inputValue: string,
          options?: { signal?: AbortSignal },
        ) => Promise<ComboboxOptions<T>>);
    onSearched?: (searchTerm: string) => void;
  };

export type ComboboxProps<T extends ComboboxOption = ComboboxOption> =
  | ComboboxAsyncProps<T>
  | ComboboxSyncProps<T>;

export type ComboboxOptionGroup<T extends ComboboxOption = ComboboxOption> = {
  heading: string;
  options: readonly T[];
};

export type ComboboxOptions<T extends ComboboxOption = ComboboxOption> =
  | T[]
  | ComboboxOptionGroup<T>[];

export type ComboboxElementType = TextFieldElementType;

export type ComboboxRef = Ref<ComboboxElementType>;

export type ComboboxOptionProps<T extends ComboboxOption = ComboboxOption> = {
  option: T;
  optionComponent?: ComboboxBaseProps<T>["optionComponent"];
  isHighlighted: boolean;
  onOptionSelect: (option: T) => void;
  id: string;
  optionTestIdPrefix?: string;
};
