import { useRef, useState, ReactNode, ReactElement, useEffect } from 'react';

import { DropdownButton } from '@/components/dropdown/components/DropdownButton';
import { DropdownItem } from '@/components/dropdown/components/DropdownItem';
import { DropdownToggler } from '@/components/dropdown/components/DropdownToggler';
import { DropdownContext } from '@/components/dropdown/context/DropdownContext';
import { useClickOutside } from '@/hooks/useClickOutside';
import { classNames } from '@/utils/classNames';

type TDropdownProps = {
  theme?: 'dark' | 'light';
  menuPosition: 'top' | 'bottom';
  toggler: ReactNode;
  children: ReactNode;
  className?: string;
  classNameOptions?: string;
  parentSizes?: DOMRect;
};

const DROPDOWN_TOP_MARGIN = 4;

function Dropdown({
  theme = 'light',
  toggler,
  children,
  menuPosition: position,
  className = '',
  classNameOptions = '',
  parentSizes,
}: TDropdownProps): ReactElement {
  const [menuPosition, setMenuPosition] = useState(position);
  const [showMenu, setShowMenu] = useState(false);
  const dropdownRef = useRef<HTMLDivElement>(null);
  const menuRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    if (parentSizes) {
      const parentBottom = parentSizes.bottom;
      const dropdownMenuHeight = menuRef.current?.getBoundingClientRect().height;
      const dropdownTogglerBottom = dropdownRef.current?.getBoundingClientRect().bottom;

      if (parentBottom && dropdownTogglerBottom && dropdownMenuHeight) {
        if (parentBottom < dropdownTogglerBottom + DROPDOWN_TOP_MARGIN + dropdownMenuHeight) {
          setMenuPosition('top');
        } else {
          setMenuPosition('bottom');
        }
      }
    }
  }, [parentSizes, menuRef.current?.getBoundingClientRect()]);

  const handleButtonClick = (e: React.MouseEvent) => {
    e.stopPropagation();
    setShowMenu(!showMenu);
  };

  useClickOutside(menuRef, () => {
    setShowMenu(false);
  });

  return (
    <DropdownContext.Provider
      value={{
        theme: theme ?? 'light',
        setShowMenu,
      }}
    >
      <div ref={dropdownRef} className={classNames('relative', showMenu ? 'z-50' : 'z-20', className)}>
        <DropdownToggler handleToggle={handleButtonClick}>{toggler}</DropdownToggler>
        {showMenu && (
          <div
            ref={menuRef}
            className={classNames(
              'absolute -right-1.5 border py-2 rounded-lg text-sm animate-menuShow z-50 min-w-[180px] w-max',
              theme === 'light' ? 'bg-gray-ui-100 border-gray' : 'bg-gray-ui border-gray-ui-100/30',
              classNameOptions ?? '',
            )}
            style={{ [menuPosition === 'top' ? 'bottom' : 'top']: 'calc(100% + 4px)' }}
          >
            {children}
          </div>
        )}
      </div>
    </DropdownContext.Provider>
  );
}

Dropdown.Button = DropdownButton;
Dropdown.Item = DropdownItem;

export { Dropdown, TDropdownProps };
