"use client";

import { ReactNode, useCallback, useEffect, useRef, useState } from "react";
import clsx from "clsx";

import { closeModalWithCleanup } from "@/shared/utils/modal";

import { Button, Icon, IconName } from "..";

import styles from "./Modal.module.scss";

export interface ModalProps {
  children: ReactNode;
  open?: boolean;
  isCloseButtonVisible?: boolean;
  className?: string;
  modalClassName?: string;
  onClose: () => void;
  removeNoScroll?: boolean;
  ref?: React.RefObject<HTMLDivElement | null>;
}

function Modal({
  open,
  children,
  isCloseButtonVisible = true,
  className = "",
  modalClassName = "",
  onClose,
  removeNoScroll = true,
  ref,
}: ModalProps): React.ReactNode {
  const modalContentRef = useRef<HTMLDivElement>(null);

  const handleClose = (event: React.MouseEvent) => {
    if (event.target !== event.currentTarget) return;
    closeModalWithCleanup(onClose);
  };

  useEffect(() => {
    if (!removeNoScroll) {
      return;
    }

    if (open) {
      document.body.classList.add("no-scroll");
    }

    return () => {
      document.body.classList.remove("no-scroll");
    };
  }, [open, removeNoScroll]);

  const [position, setPosition] = useState({ top: 0, left: 0 });

  const getModalContentPosition = useCallback(() => {
    const modalContent = modalContentRef.current;
    if (!modalContent)
      return {
        top: 0,
        left: 0,
      };
    const { top, left } = modalContent.getBoundingClientRect();
    return { top, left };
  }, [modalContentRef]);

  useEffect(() => {
    const updatePosition = () => {
      requestAnimationFrame(() => {
        setPosition(getModalContentPosition());
      });
    };

    if (open) {
      updatePosition();
    }

    window.addEventListener("resize", updatePosition);

    return () => {
      window.removeEventListener("resize", updatePosition);
    };
  }, [getModalContentPosition, open]);

  if (!open) return <></>;

  return (
    <div className={clsx(styles.overlay, className)} onClick={handleClose}>
      {isCloseButtonVisible && (
        <Button
          className={styles.crossButton}
          onClick={handleClose}
          style={{
            top: `${position.top + 16}px`,
            left: `${position.left + 15}px`,
          }}
        >
          <Icon
            name={IconName.Cross}
            size={{
              height: 16,
              width: 16,
            }}
          />
        </Button>
      )}
      <div
        className={clsx(styles.modal, modalClassName)}
        ref={ref || modalContentRef}
      >
        {children}
      </div>
    </div>
  );
}

export default Modal;
