import React, { useState, useEffect, useRef } from 'react';
import PropTypes from 'prop-types';
import i18next from 'i18next';
import { get } from 'lodash';
import { ThemeProvider } from 'styled-components';

import { getTheme } from '../../../utils/theme';

import { Props } from './interfaces';

import Button from '../../../Button/index';

import iconDropDown from '../../../images/icon-carret-down-action-black.svg';

import { getRandomInt } from '../../../utils/format';

import {
  DropdownContainer,
  DropdownList,
  DropdownItem,
  DropdownItemText,
  CustomButton,
  Icon,
  IconContainer,
  ToolTipText,
} from './styledComponents';

const Dropdown = (props: Props): JSX.Element => {
  const { theme, label, actions, customButton, setIsActionOpened, index } =
    props;

  const [isDropdownOpen, setIsDropdownOpen] = useState(false);

  const dropdownRef = useRef<HTMLInputElement>(null);

  const updatedTheme = getTheme(theme, 'listView');

  const [dropdownListXPos, setDropdownListXPos] = useState(0);

  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  const actionsAnyType: any[] = actions;

  const randomDropdownListId = `dropdownList-${getRandomInt()}`;

  const areAllActionsHidden = actionsAnyType.every(
    (action) => action.isHidden && action.isHidden()
  );

  const close = () => {
    setIsDropdownOpen(false);
    if (setIsActionOpened) {
      setIsActionOpened(undefined);
    }
  };

  const toggle = (e) => {
    e.stopPropagation();
    if (isDropdownOpen) {
      close();
      return;
    }
    setIsDropdownOpen(true);
    if (setIsActionOpened) {
      setIsActionOpened(index);
    }
  };

  const handleClick = (event) => (handleAction) => {
    event.stopPropagation();
    setIsDropdownOpen(false);
    handleAction();
  };

  useEffect(() => {
    function handleClickOutside(event) {
      const currentRef = get(dropdownRef, 'current');
      if (currentRef && !currentRef.contains(event.target)) {
        close();
      }
    }

    document.addEventListener('mousedown', handleClickOutside);
    return () => {
      document.removeEventListener('mousedown', handleClickOutside);
    };

    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [dropdownRef]);

  useEffect(() => {
    if (!isDropdownOpen) {
      setDropdownListXPos(0);
      return;
    }

    const dropdownListElem = document.getElementById(randomDropdownListId);

    if (dropdownListElem) {
      const dropdownListPos = dropdownListElem.getBoundingClientRect();
      setDropdownListXPos(dropdownListPos.left);
    }
  }, [isDropdownOpen, randomDropdownListId]);

  return (
    <ThemeProvider theme={updatedTheme}>
      {actions.length && !areAllActionsHidden && (
        <DropdownContainer ref={dropdownRef}>
          {customButton ? (
            <CustomButton onClick={(e) => toggle(e)}>
              {customButton(index || 0)}
            </CustomButton>
          ) : (
            <Button
              theme={theme}
              label={label}
              color={updatedTheme.otherAction?.color}
              handleClick={(e) => toggle(e)}
              formatText={false}
              fontSize={14}
              iconOnLeft={false}
              icon={iconDropDown}
              iconCustomStyle={{ width: '10px', height: '6px' }}
              isActive={isDropdownOpen}
              minWidth={125}
              height={40}
              isDisabled={areAllActionsHidden}
            />
          )}
          {isDropdownOpen && (
            <DropdownList id={randomDropdownListId}>
              {actions.map((action, currentIndex) => {
                const actionLabel =
                  typeof action.actionLabel === 'string'
                    ? action.actionLabel
                    : action.actionLabel();

                const dropdownItemId = `item-${get(action, 'id', actionLabel)}`;
                const tooltipTextId = `tooltip-item-${currentIndex}`;

                if (action.isHidden && action.isHidden()) {
                  return null;
                }

                if (action.disabledTooltipText) {
                  const tooltipText = document.getElementById(tooltipTextId);

                  const actionContainer =
                    document.getElementById(dropdownItemId);

                  actionContainer?.addEventListener(
                    'mousemove',
                    function handleTooltipPosition(e) {
                      if (tooltipText) {
                        const left =
                          e.x - dropdownListXPos - tooltipText.offsetWidth - 16;

                        // place the tooltip text above the action button
                        const top = -tooltipText.offsetHeight - 8;

                        tooltipText.style.left = `${left}px`;
                        tooltipText.style.top = `${top}px`;
                      }
                    }
                  );

                  actionContainer?.addEventListener(
                    'mouseleave',
                    function handleLeave() {
                      if (tooltipText) {
                        tooltipText.style.opacity = `0`;
                      }
                    }
                  );

                  actionContainer?.addEventListener(
                    'mouseenter',
                    function handleLeave() {
                      if (tooltipText) {
                        tooltipText.style.opacity = `1`;
                      }
                    }
                  );
                }

                return (
                  <DropdownItem
                    key={dropdownItemId}
                    id={dropdownItemId}
                    isDisabled={action.isDisabled && action.isDisabled()}
                    isHighlighted={
                      action.isHighlighted && action.isHighlighted()
                    }
                    backgroundColor={action.backgroundColor}
                    backgroundColorOnHover={action.backgroundColorOnHover}
                    onClick={(e) => {
                      if (action.isDisabled && action.isDisabled()) {
                        e.stopPropagation();
                        return;
                      }

                      handleClick(e)(action.handleAction);
                    }}
                  >
                    {!!action.isDisabled &&
                      !!action.isDisabled() &&
                      !!action.disabledTooltipText &&
                      !!action.disabledTooltipText() && (
                        <ToolTipText id={tooltipTextId}>
                          {action.disabledTooltipText()}
                        </ToolTipText>
                      )}
                    {action.actionIcon && (
                      <IconContainer>
                        <Icon src={action.actionIcon()} alt="label-icon" />
                      </IconContainer>
                    )}
                    <DropdownItemText>{actionLabel}</DropdownItemText>
                  </DropdownItem>
                );
              })}
            </DropdownList>
          )}
        </DropdownContainer>
      )}
    </ThemeProvider>
  );
};

Dropdown.propTypes = {
  label: PropTypes.string,
  actions: PropTypes.arrayOf(
    PropTypes.shape({
      actionLabel: PropTypes.oneOfType([
        PropTypes.func.isRequired,
        PropTypes.string.isRequired,
      ]),
      actionIcon: PropTypes.func,
      isDisabled: PropTypes.func,
      handleAction: PropTypes.func.isRequired,
      disabledTooltipText: PropTypes.func,
    })
  ).isRequired,
  customButton: PropTypes.func,
  // eslint-disable-next-line react/forbid-prop-types
  theme: PropTypes.objectOf(PropTypes.any),
};

Dropdown.defaultProps = {
  label: i18next.t('COMPONENT_LIST_VIEW_DROPDOWN_ACTIONS'),
  customButton: null,
  theme: null,
};

export default Dropdown;
