import React, { useRef, useState, cloneElement } from 'react';
import classnames from 'classnames';
import MultiSelectTypeahead from './multi-select-typeahead';
import { useVisibleOptions } from '../use-visible-options';
import { useOptionKeyboardNavigation } from '../../hooks/use-option-keyboard-navigation';
import { getNonNativeButtonAttrs } from '../../hooks/use-non-native-button-attrs';
import { Checkbox } from '../../checkbox';
import { TruncateWithTooltip } from '../../truncate-with-tooltip';
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
const SELECT_ALL_KEY = 'SELECT_ALL_KEY';
function CheckboxListItem({
  option,
  optionId,
  optionLabel,
  handleSelect,
  activeOption,
  makeActive,
  onInteraction,
  currentRef,
  optionComponent
}) {
  return /*#__PURE__*/_jsx("div", {
    "test-id": `typeahead-dropdown-item-${option[optionId]}`,
    ref: currentRef,
    className: classnames('typeahead-dropdown-item', {
      active: activeOption && activeOption === option[optionId],
      'sticky-typeahead-dropdown-item': option[optionId] === SELECT_ALL_KEY
    }),
    onMouseEnter: () => makeActive(option[optionId]),
    ...getNonNativeButtonAttrs({
      isDisabled: option.isDisabled,
      onClick: e => onInteraction(e, option),
      onKeyDown: e => onInteraction(e, option)
    }),
    children: /*#__PURE__*/_jsxs("div", {
      className: "checkbox-item-container",
      children: [/*#__PURE__*/_jsx(Checkbox, {
        id: option[optionId],
        testId: `checkbox-${option[optionId]}`,
        className: "margin-right-2",
        onChange: e => {
          e.stopPropagation();
          handleSelect(option);
        },
        isChecked: option.isChecked,
        isDisabled: option.isDisabled,
        indeterminate: option.indeterminate,
        ariaLabel: option[optionLabel]
      }), optionComponent ? (
      /*#__PURE__*/
      // This is wrong way of doing stuff, but I'm, keeping existing typeahead approach for now
      cloneElement(optionComponent, {
        option,
        optionId,
        optionLabel
      })) : /*#__PURE__*/_jsxs("div", {
        className: "columns-container",
        children: [/*#__PURE__*/_jsx("div", {
          className: "label-column-container",
          children: /*#__PURE__*/_jsx(TruncateWithTooltip, {
            className: "label-column",
            children: /*#__PURE__*/_jsx("span", {
              children: option[optionLabel]
            })
          })
        }), /*#__PURE__*/_jsx("div", {
          className: "additional-columns-container",
          children: option?.additionalColumnsKeys?.map(accessorKey => {
            return /*#__PURE__*/_jsx(TruncateWithTooltip, {
              className: "checkbox-item-additional-column",
              children: /*#__PURE__*/_jsx("span", {
                "test-id": `checkbox-item-additional-column-${accessorKey}`,
                children: option[accessorKey]
              }, accessorKey)
            }, accessorKey);
          })
        })]
      })]
    })
  }, String(option[optionId]));
}
function CheckboxOptionList({
  options,
  optionId,
  optionLabel,
  closeDropdown,
  handleSelect,
  searchValue,
  searchFields,
  width,
  inputRef,
  optionComponent,
  listId
}) {
  const {
    visibleOptions
  } = useVisibleOptions({
    searchValue,
    options,
    searchFields,
    isShowAll: false
  });
  const scrollableContainerRef = useRef(null);
  const optionsRefs = visibleOptions.reduce((map, option) => {
    map[option[optionId]] = /*#__PURE__*/React.createRef();
    return map;
  }, {});
  const [activeOption, makeActive] = useOptionKeyboardNavigation(visibleOptions, optionId, handleSelect, closeDropdown, optionsRefs, scrollableContainerRef, 0, 'isDisabled', inputRef);
  const onInteraction = (e, option) => {
    e.preventDefault();
    handleSelect(option);
  };
  return /*#__PURE__*/_jsx("div", {
    className: "typeahead-dropdown-list checkbox-multiselect-container"
    /* eslint-disable-next-line react/forbid-dom-props */,
    style: {
      width
    },
    "test-id": "typeahead-dropdown-list",
    id: listId,
    ref: el => {
      // The element itself is the scrollable container (overflow-y: auto on
      // .checkbox-multiselect-container); keyboard navigation needs the ref
      // here so active options can be scrolled into view.
      scrollableContainerRef.current = el;
    },
    children: visibleOptions.map(option => /*#__PURE__*/_jsx(CheckboxListItem, {
      option: option,
      optionId: optionId,
      optionLabel: optionLabel,
      handleSelect: handleSelect,
      onInteraction: onInteraction,
      currentRef: optionsRefs[option[optionId]],
      activeOption: activeOption,
      makeActive: makeActive,
      optionComponent: optionComponent
    }, option[optionId]))
  });
}
export function CheckboxMultiselectTypeahead({
  options,
  optionId,
  optionLabel = 'label',
  items = [],
  isDisabled,
  validity,
  onSelect: onChange = () => {},
  selectAllRow,
  // @ts-expect-error I'm setting this to null explicitly so that Typeahead would not pass default component to CheckboxListItem
  optionComponent = null,
  shouldShowValidityOnTouched = false,
  ...otherMultiSelectTypeaheadProps
}) {
  // multiselect typeahead does not use typeahead logic for rendering validity message,
  // but in its logic it does not do checks on whether input was touched or not
  // didn't want to introduce this to multiselect typeahead component cause not sure if it's needed there,
  // but it is needed in usages of this one.
  const [isTouched, setTouched] = useState(!!items?.length);
  const allChecked = items.length === options?.length;
  const itemLabels = items?.map(item => {
    const selectedOption = options?.find(optionItem => optionItem[optionId] === item);
    return selectedOption ? selectedOption[optionLabel] : item;
  }) ?? [];
  const modifiedOptions = options?.map(optionItem => ({
    ...optionItem,
    shouldNotCloseDropdown: true,
    isChecked: items?.includes(optionItem[optionId])
  })) ?? [];
  if (modifiedOptions.length && selectAllRow) {
    modifiedOptions.unshift({
      [optionId]: SELECT_ALL_KEY,
      ...selectAllRow,
      shouldNotCloseDropdown: true,
      isChecked: allChecked,
      indeterminate: !!items?.length && items.length < (options?.length ?? 0)
    });
  }
  function onSelect(option) {
    setTouched(true);
    if (option) {
      const id = option[optionId];
      if (id === SELECT_ALL_KEY) {
        // handle select all click
        if (!allChecked) {
          onChange(options?.map(optionItem => optionItem[optionId]));
        } else {
          onChange([]);
        }
      } else if (items.includes(option[optionId])) {
        // toggle selected option
        onChange(items.filter(item => item !== option[optionId]));
      } else {
        // add new selected item
        onChange([...items, option[optionId]]);
      }
    }
  }
  function onDelete(title) {
    setTouched(true);
    const option = options?.find(optionItem => optionItem[optionLabel] === title);
    onChange(items.filter(item => {
      const key = typeof option === 'string' ? option : option?.[optionId];
      return item !== key;
    }));
  }
  let validityValue;
  if (shouldShowValidityOnTouched) {
    validityValue = isTouched ? validity : undefined;
  } else {
    validityValue = validity;
  }
  return /*#__PURE__*/_jsx(MultiSelectTypeahead, {
    ...otherMultiSelectTypeaheadProps,
    isDisabled: isDisabled,
    showAllOnFocus: true,
    items: itemLabels,
    OptionList: CheckboxOptionList,
    optionComponent: optionComponent,
    options: modifiedOptions,
    optionId: optionId,
    optionLabel: optionLabel,
    onSelect: onSelect,
    onDelete: onDelete,
    onBlur: () => setTouched(true),
    keepInvalidText: true,
    shouldShowSelectedOptions: true,
    validity: validityValue,
    dropdownContentClass: classnames('checkbox-multiselect-typeahead-dropdown-content', otherMultiSelectTypeaheadProps?.dropdownContentClass)
  });
}