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

import { useButtonClasses } from '@/components/buttons/hooks/useButtonClasses';
import { IconClose } from '@/components/icon';
import { ModalContent } from '@/components/modal/components/ModalContent';
import { useClickOutside } from '@/hooks/useClickOutside';
import { classNames } from '@/utils/classNames';

export type TModalProps = {
  isShown: boolean;
  setIsShown: (isShown: boolean) => void;
  children: ReactNode;
  hideClose?: boolean;
};

const Modal = ({ isShown, children, setIsShown, hideClose }: TModalProps): ReactElement => {
  const contentRef = useRef<HTMLDivElement | null>(null);

  const buttonClasses = useButtonClasses({
    color: 'transparent',
    size: 'md',
    shape: 'square',
    className: '',
  });

  useClickOutside(contentRef, () => setIsShown(false));

  useEffect(() => {
    if (isShown) {
      document.body.style.overflow = 'hidden';
      const popupElement = document.querySelector('.animate-showPopdown');

      const handleTransitionEnd = () => {
        popupElement?.classList.remove('animate-showPopdown');
        popupElement?.removeEventListener('transitionend', handleTransitionEnd);
      };

      popupElement?.addEventListener('transitionend', handleTransitionEnd);
    } else {
      document.body.style.overflow = '';
    }
  }, [isShown]);

  return (
    <div
      className={classNames(
        'fixed inset-0 z-30 flex justify-center w-full opacity-0 transition-opacity duration-std overflow-y-auto',
        isShown ? 'opacity-100 visible' : 'invisible',
      )}
    >
      {isShown && (
        <div
          className={
            'flex items-center justify-center bg-gray-ui bg-opacity-80 relative w-full min-h-full overflow-y-auto'
          }
        >
          <div
            className={classNames('flex relative z-50 m-auto', isShown ? 'animate-showPopdown' : '')}
            ref={contentRef}
          >
            <div className="relative">
              {children}
              {!hideClose && (
                <div className="absolute top-3.5 right-3.5 z-50">
                  <button onClick={() => setIsShown(false)} className={buttonClasses}>
                    <IconClose className="pointer-events-none" />
                  </button>
                </div>
              )}
            </div>
          </div>
        </div>
      )}
    </div>
  );
};

Modal.Content = ModalContent;

export { Modal };
