import type { FC, HTMLAttributes } from 'react';
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { DropdownContext } from './DropdownContext';

export interface DropdownProps extends HTMLAttributes<HTMLElement> {}

const Dropdown: FC<DropdownProps> = ({ children }) => {
  const container = useRef<HTMLDivElement>(null);
  const [isOpen, setIsOpen] = useState(false);
  const toggle = useCallback(() => setIsOpen((prevIsOpen) => !prevIsOpen), [setIsOpen]);
  const value = useMemo(
    () => ({
      isOpen,
      toggle,
    }),
    [isOpen, toggle]
  );

  useEffect(() => {
    // todo: fix this use of `any`
    function handleDocumentClick(e: any) {
      if (container.current?.contains(e.target) && container.current !== e.target) {
        return;
      }

      if (!container.current?.contains(e.target) && container.current !== e.target) {
        setIsOpen(false);

        return;
      }

      toggle();
    }

    ['click'].forEach((eventName) => document.addEventListener(eventName, handleDocumentClick, true));

    return () => {
      ['click'].forEach((eventName) => document.removeEventListener(eventName, handleDocumentClick, true));
    };
  }, [toggle, container]);

  return (
    <DropdownContext.Provider value={value}>
      <div ref={container} data-testid="Dropdown">
        {/* @ts-ignore todo: do we still need this function check? */}
        {typeof children === 'function' ? children(value) : children}
      </div>
    </DropdownContext.Provider>
  );
};

export default Dropdown;
