import React, { forwardRef, useImperativeHandle, useState } from 'react';
import PropTypes from 'prop-types';

import { getIAB } from '@/modules/@common/iab/helpers';
import { createFlatTreeMap, getAggregateSelectedIds } from '@/mui/helpers/treeView';

import { Autocomplete, TreeView } from '@/mui/components';

import styles from './IabSelect.module.scss';

const IabSelect = forwardRef((props, ref) => {
  const [open, setOpen] = useState(false);
  const [search, setSearch] = useState('');
  const [flatTree, setFlatTree] = useState(
    createFlatTreeMap(
      getIAB(),
      {
        label: 'name',
        children: 'categories',
      },
      props.tags.map(({ id }) => id),
    ),
  );

  const [autoCompleteValue, setAutoCompleteValue] = useState(getAggregateSelectedIds(flatTree, true));

  const updateTreeState = (selectedFn) => {
    const copiedMap = new Map();

    let hasChanges = false;

    flatTree.forEach((node) => {
      const selected = selectedFn(node);

      if (selected !== node.selected) {
        hasChanges = true;
      }

      copiedMap.set(node.id, {
        ...node,
        selected,
      });
    });

    setFlatTree((prev) => (hasChanges ? copiedMap : prev));

    if (hasChanges) {
      const selected = getAggregateSelectedIds(copiedMap);
      setAutoCompleteValue(selected);
      props.onChange(
        selected.map((id) => {
          const node = flatTree.get(id);

          return {
            ...node.initialNode,
            id: node.id,
            value: node.label,
          };
        }),
      );
    }
  };

  const clear = () => {
    setAutoCompleteValue([]);
    setSearch('');
    setOpen(false);
  };

  // useEffect(() => {
  //   setFlatTree((prev) => {
  //     const copiedMap = new Map();
  //     let hasChanges = false;
  //
  //     flatTree.forEach((node) => {
  //       const selected = props.selectedIds.includes(node.id);
  //
  //       if (node.selected !== selected) {
  //         hasChanges = true;
  //       }
  //
  //       copiedMap.set(node.id, {
  //         ...node,
  //         selected,
  //       });
  //     });
  //
  //     return (hasChanges ? copiedMap : prev);
  //   });
  // }, [props.tags]);

  useImperativeHandle(ref, () => ({
    clear,
  }));

  return (
    <Autocomplete
      open={open}
      fullWidth
      size="small"
      multiple
      limitTags={1}
      inputValue={search}
      value={autoCompleteValue}
      getOptionLabel={(id) => flatTree.get(id).label}
      optionValueKey="id"
      options={[]}
      renderInput={props.renderInput}
      classes={{
        noOptions: styles.NoOptionsWrapper,
      }}
      noOptionsText={
        <TreeView
          flatTree={flatTree}
          searchText={search}
          multiSelect
          autoSuggest
          onNodeSelect={(event, nodeIds) => {
            updateTreeState((sourceNode) => nodeIds.includes(sourceNode.id));
          }}
        />
      }
      onChange={(event, autocompleteValues, reason, value) => {
        if (reason === 'removeOption') {
          const targetNode = flatTree.get(value.option);

          updateTreeState(
            (sourceNode) =>
              sourceNode.selected &&
              sourceNode.id !== targetNode.id &&
              !targetNode.childrenIds.includes(sourceNode.id) &&
              !targetNode.parentPath.includes(sourceNode.id),
          );
        } else if (reason === 'clear') {
          clear();
        }
      }}
      onInputChange={(event, value) => {
        setSearch(value);
      }}
      onOpen={() => {
        setAutoCompleteValue(getAggregateSelectedIds(flatTree, true));
        setTimeout(() => setOpen(true), 0);
      }}
      onClose={() => {
        setOpen(false);
      }}
    />
  );
});

IabSelect.propTypes = {
  renderInput: PropTypes.node.isRequired,
  tags: PropTypes.arrayOf(PropTypes.shape({})).isRequired,
  onChange: PropTypes.func.isRequired,
};

export default IabSelect;
