import React, { useEffect, useState, useRef } from 'react';
import isEqual from 'lodash-es/isEqual';
import sortBy from 'lodash-es/sortBy';
import classNames from 'classnames';
import { faPlus } from '@fortawesome/free-solid-svg-icons/faPlus';
import { Button, ACCENT_TYPES } from '../button';
import { InfoIcon } from '../info-icon';
import { FormFieldLabel, ValidityMessages } from '../form-field';
import { MESSAGE_TYPES } from '../message';
import { KeyValueInputs } from './key-value-inputs';
import { useTranslation } from '../hooks/use-translation';
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
function useKVPsValidation(hasWarning, warningMessage, defaultValue) {
  const [validity, setValidity] = useState(defaultValue);
  useEffect(() => {
    if (hasWarning) {
      setValidity({
        type: MESSAGE_TYPES.WARNING,
        value: warningMessage
      });
    } else {
      setValidity(defaultValue);
    }
  }, [hasWarning]);
  return [validity, setValidity];
}
function extractObjToArray(val = {}) {
  return Object.entries(val).map(([key, value]) => {
    return {
      name: key,
      value
    };
  });
}
const SUCCESSFUL_VALIDATION_OBJ = {
  type: MESSAGE_TYPES.SUCCESS,
  value: ''
};
const removeEmptyPairs = ({
  name,
  value
}) => !!name && !!value;
const removeDuplicateKeys = ({
  name
}, index, collection) => collection.findIndex(item => item.name === name) === index;
const sortItems = items => sortBy(items, ['name', 'value']);
/** Key Value Pairs
    @midnight-gray-supported
    @alpine-light-supported
 */
export const KeyValuePairs = ({
  value,
  className = '',
  label = '',
  keyLabel = '',
  valueLabel = '',
  helperText = '',
  placeholder: placeholderParams,
  isDisabled = false,
  disabledPairs,
  onChange = () => {},
  hasWarning = false,
  emptyCheck = false,
  warningMessage: warningMessageParams,
  buttonText: buttonTextParams,
  maxItemsTooltipText: maxItemsTooltipTextParams,
  emptyItemErrorText: emptyItemErrorTextParams,
  deleteKeyValueText: deleteKeyValueTextParams,
  buildDuplicateItemErrorText: buildDuplicateItemErrorTextParams,
  testId = 'key-value-pairs',
  infoIconProps = null,
  onError = () => {},
  maxSize = null,
  addButtonAccentType = ACCENT_TYPES.COMMAND,
  keyInputAriaLabel: keyInputAriaLabelParams,
  valueInputAriaLabel: valueInputAriaLabelParams,
  id = ''
}) => {
  const {
    t
  } = useTranslation();
  const placeholder = placeholderParams ?? t('No items found');
  const buttonText = buttonTextParams ?? t('Add item');
  const maxItemsTooltipText = maxItemsTooltipTextParams ?? t('Max number of key-value pairs reached');
  const emptyItemErrorText = emptyItemErrorTextParams ?? t('Above field(s) should not be empty');
  const deleteKeyValueText = deleteKeyValueTextParams ?? t('Delete');
  const keyInputAriaLabel = keyInputAriaLabelParams ?? t('Key input');
  const valueInputAriaLabel = valueInputAriaLabelParams ?? t('Value input');
  const warningMessage = warningMessageParams ?? t('Double-check this value');
  const buildDuplicateItemErrorText = buildDuplicateItemErrorTextParams ?? (({
    name
  }) => t('Duplicated keys ({{name}}) are not allowed.', {
    name
  }));
  // Keep items in array format to ensure duplicate objects CAN be shown (but are not valid)
  const [items, setItems] = useState(extractObjToArray(value));
  const lastInputRef = useRef(null);
  const [validity, setValidity] = useKVPsValidation(hasWarning, warningMessage, SUCCESSFUL_VALIDATION_OBJ);
  useEffect(() => {
    // Adjust `items` if new `value` passed in
    // is different from what is already in `items`
    // (with empty KVPs filtered out).
    //
    // Note: Sort both, since order of object `value` is not guaranteed.
    const sortedOldItems = sortItems(items).filter(removeEmptyPairs).filter(removeDuplicateKeys);
    const newItems = extractObjToArray(value);
    const sortedNewItems = sortItems(newItems);
    if (!isEqual(sortedOldItems, sortedNewItems)) {
      setItems(newItems);
      setValidity(SUCCESSFUL_VALIDATION_OBJ);
    }
  }, [value]);
  function handleChange(updatedItems) {
    let isValid = true;
    const validationResults = updatedItems.reduce((processedItems, item) => {
      const cleanedName = typeof item.name === 'string' ? item.name.trim() : item.name;
      const cleanedValue = typeof item.value === 'string' ? item.value.trim() : item.value;
      const hasKey = cleanedName !== '';
      if (emptyCheck && !(cleanedName && cleanedValue !== undefined && cleanedValue !== '')) {
        setValidity({
          type: MESSAGE_TYPES.ERROR,
          value: emptyItemErrorText
        });
        isValid = false;
      } else if (cleanedName in processedItems && hasKey) {
        setValidity({
          type: MESSAGE_TYPES.ERROR,
          value: buildDuplicateItemErrorText({
            name: cleanedName
          })
        });
        isValid = false;
      }
      processedItems[cleanedName] = item.value;
      return processedItems;
    }, {});
    if (isValid) {
      setValidity(SUCCESSFUL_VALIDATION_OBJ);
      onChange(validationResults);
    } else {
      onError(value);
    }
  }
  function handleUpdateItems(updatedItems, addNewItem = false) {
    setItems(updatedItems);
    if (!addNewItem) {
      handleChange(updatedItems);
    }
  }
  function removeItem(index) {
    const updatedItems = items.filter((option, i) => i !== index);
    handleUpdateItems(updatedItems);
  }
  function addItem() {
    const updatedItems = [...items, {
      name: '',
      value: ''
    }];
    handleUpdateItems(updatedItems, true);
    setTimeout(() => {
      lastInputRef?.current?.focus();
    }, 0);
  }
  function changeItem(index, updatedItem) {
    const updatedItems = [...items];
    if (updatedItems[index]) {
      updatedItems[index] = updatedItem;
      handleUpdateItems(updatedItems);
    }
  }
  const elements = items.length === 0 ? /*#__PURE__*/_jsx("span", {
    className: "kvp-no-text",
    children: placeholder
  }) : /*#__PURE__*/_jsxs(_Fragment, {
    children: [(keyLabel || valueLabel) && /*#__PURE__*/_jsxs("div", {
      className: "kvp-inputs",
      children: [/*#__PURE__*/_jsx("span", {
        className: "key-input",
        children: keyLabel
      }), /*#__PURE__*/_jsx("span", {
        className: "value-input",
        children: valueLabel
      }), /*#__PURE__*/_jsx("span", {
        className: "kvp-inputs-empty-block"
      })]
    }), items.map((item, index) => {
      const paddedIndex = index + 1;
      return /*#__PURE__*/_jsx(KeyValueInputs, {
        validity: validity,
        name: item.name,
        value: item.value,
        isDisabled: isDisabled,
        disabledPairs: disabledPairs,
        onChange: updatedOption => changeItem(index, updatedOption),
        onDelete: () => removeItem(index),
        deleteKeyValueText: `${deleteKeyValueText} ${paddedIndex}`,
        keyLabel: keyLabel,
        valueLabel: valueLabel,
        keyInputAriaLabel: `${keyInputAriaLabel} ${paddedIndex}`,
        valueInputAriaLabel: `${valueInputAriaLabel} ${paddedIndex}`,
        id: id,
        ref: index === items.length - 1 ? lastInputRef : null
      }, index);
    })]
  });
  const maxKVPsLimitReached = !!maxSize && items.length >= maxSize;
  return /*#__PURE__*/_jsxs("div", {
    "test-id": testId,
    className: classNames('kvps-container', className),
    children: [label && /*#__PURE__*/_jsx(FormFieldLabel, {
      label: /*#__PURE__*/_jsxs(_Fragment, {
        children: [label, infoIconProps && /*#__PURE__*/_jsx(InfoIcon, {
          ...infoIconProps
        })]
      }),
      labelTestId: `${testId}-dr-field-label`,
      isDisabled: isDisabled
    }), helperText && /*#__PURE__*/_jsx("div", {
      className: "margin-bottom-2 kvp-items-helper-text",
      children: helperText
    }), /*#__PURE__*/_jsx("div", {
      className: "kvps-items",
      children: elements
    }), /*#__PURE__*/_jsx("div", {
      className: "kvps-form-controls",
      children: /*#__PURE__*/_jsx(Button, {
        testId: `${testId}-add-button`,
        accentType: addButtonAccentType,
        leftIcon: faPlus,
        isDisabled: isDisabled || maxKVPsLimitReached,
        tooltipText: maxKVPsLimitReached ? maxItemsTooltipText : null,
        onClick: addItem,
        children: buttonText
      })
    }), /*#__PURE__*/_jsx(ValidityMessages, {
      validity: validity,
      fieldId: id,
      validationTestId: "key-value-pair-validity"
    })]
  });
};