import React, { ReactNode, useRef, useEffect } from 'react';
import { Overlay, useModalOverlay, useDialog, useKeyboard } from 'react-aria';
import { OverlayTriggerState } from 'react-stately';
import { DOMAttributes, FocusableElement } from '@react-types/shared';

import { Icon, IconOptions } from '../Icons/Icon';

/*
  This has to be a separate element otherwise the focus trap fails. Assuming this is because it needs
  to fit inside the 'Overlay' as a form of context.
*/
function PreviewModalContent({ children, onClose, ...props }: { children: ReactNode; onClose: () => void }) {
  const ref = useRef<HTMLDivElement>(null);
  const { dialogProps, titleProps } = useDialog(props, ref);

  return (
    <div {...dialogProps} ref={ref} className="h-full flex flex-col">
      <h3 {...titleProps} className="sr-only">
        Resource Details
      </h3>
      <button type="button" aria-label="Close details" onClick={onClose} className="absolute top-3 right-3">
        <Icon icon={'close' as IconOptions} className="" />
      </button>
      {children}
    </div>
  );
}

export type PreviewModalProps = {
  state: OverlayTriggerState;
  overlayProps: DOMAttributes<FocusableElement>;
  children?: ReactNode;
  onClose: () => void;
};

// Accept a ref for the top level modal
function PreviewModal({ state, overlayProps, children, onClose, ...props }: PreviewModalProps) {
  const modalRef = useRef<HTMLDivElement>(null);

  const overlayRef = useRef<HTMLDivElement>(null);
  const { modalProps, underlayProps } = useModalOverlay(
    { isKeyboardDismissDisabled: true, ...props },
    state,
    overlayRef,
  );

  // Need to handle the ESC escape hatch ourselves as we need to run onClose to deselect the current node
  const { keyboardProps } = useKeyboard({
    onKeyDown: (e) => {
      if (e.key === 'Escape') {
        onClose();
      } else {
        // Need to do this so TAB get handled up higher and cycles though the focus trap
        e.continuePropagation();
      }
    },
  });

  useEffect(() => {
    // Check if the click event has happened outside the modal
    function handleClickOutside(event: MouseEvent) {
      if (modalRef.current && !modalRef.current.contains(event?.target as Node)) {
        onClose();
      }
    }
    // Bind the event listener
    document.addEventListener('mousedown', handleClickOutside);
    return () => {
      // Unbind the event listener on clean up
      document.removeEventListener('mousedown', handleClickOutside);
    };
  }, [modalRef]);

  return (
    <Overlay>
      <div className="squiz-gb-scope">
        <div
          ref={modalRef}
          {...underlayProps}
          {...keyboardProps}
          className="fixed z-[9999] overflow-y-scroll bottom-0 w-full h-[50vh] bg-white border-t border-gray-300"
        >
          <div ref={overlayRef} {...modalProps} className="h-full">
            <PreviewModalContent {...overlayProps} onClose={onClose}>
              {children}
            </PreviewModalContent>
          </div>
        </div>
      </div>
    </Overlay>
  );
}

export default PreviewModal;
