import type {
  ComboboxOption,
  ComboboxOptionGroup,
  ComboboxOptions,
} from "./types";

// FIXME: This might be better handled with Zod
export function isOptionGroup<T extends ComboboxOption>(
  options: ComboboxOptions<T> | undefined,
): options is ComboboxOptionGroup<T>[] {
  if (!options) return false;
  return (
    typeof options[0] === "object" &&
    "options" in options[0] &&
    options[0].options !== undefined &&
    "heading" in options[0] &&
    options[0].heading !== undefined
  );
}

export const getOptionValue = (option: ComboboxOption | undefined) =>
  typeof option === "string" ? option : option?.value;

export const getOptionLabel = (option: ComboboxOption | undefined) =>
  typeof option === "string" ? option : option?.label;

export function filterOptions<T extends ComboboxOption>(
  options: ComboboxOptions<T>,
  inputValue: string,
): ComboboxOptions<T> {
  if (isOptionGroup(options)) {
    return options
      .map(optionGroup => ({
        ...optionGroup,
        options: optionGroup.options.filter(option =>
          getOptionLabel(option)!
            .toLowerCase()
            .includes(inputValue.toLowerCase()),
        ),
      }))
      .filter(optionGroup => optionGroup.options.length > 0);
  }

  return options.filter(option =>
    getOptionLabel(option)!.toLowerCase().includes(inputValue.toLowerCase()),
  );
}

export function clamp(value: number, min: number, max: number) {
  return Math.min(Math.max(value, min), max);
}

export const buildOptionTestId = (prefix: string, value: string): string =>
  `${prefix}-${value
    .trim()
    .toLowerCase()
    .replace(/[^a-z0-9]+/g, "-")
    .replace(/^-+|-+$/g, "")}`;
