import {
  PropsWithChildren,
  Suspense,
  useCallback,
  useEffect,
  useRef,
  useState,
} from "react";
import { useIsMobile } from "@/hooks/use-is-mobile";
import Drawer from "./drawer";
import Modal from "./modal";
import { ScrollArea, Flex, Loader } from "@mantine/core";

interface SheetProps extends PropsWithChildren {
  title?: string;
  opened: boolean;
  onChange: (next: boolean) => void;
}

const DRAWER_EXIT_MS = 500;
const MODAL_EXIT_MS = 200;
const EXIT_BUFFER_MS = 100;

const Sheet: React.FC<SheetProps> = ({ title, children, opened, onChange }) => {
  const isMobile = useIsMobile();
  const handleClose = useCallback(() => onChange(false), [onChange]);

  const [mounted, setMounted] = useState(opened);
  const openedRef = useRef(opened);
  openedRef.current = opened;
  const handleExited = useCallback(() => {
    if (!openedRef.current) setMounted(false);
  }, []);

  useEffect(() => {
    if (opened) {
      setMounted(true);
      return;
    }
    const exitDuration =
      (isMobile ? DRAWER_EXIT_MS : MODAL_EXIT_MS) + EXIT_BUFFER_MS;
    const timer = window.setTimeout(() => setMounted(false), exitDuration);
    return () => window.clearTimeout(timer);
  }, [opened, isMobile]);

  const SheetComponent = isMobile ? Drawer : Modal;

  if (!opened && !mounted) return null;

  return (
    <SheetComponent
      title={title}
      opened={opened}
      onChange={onChange}
      onClose={handleClose}
      onExited={handleExited}
    >
      <Suspense fallback={
        <Flex justify='center' align='center' w='100%' style={{ minHeight: '25vh' }}>
          <Loader size='lg' />
        </Flex>
      }>
        <ScrollArea.Autosize
          style={{ flex: 1, maxHeight: '75dvh' }}
          scrollbarSize={8}
          scrollbars="y"
          type="scroll"
        >
          {children}
        </ScrollArea.Autosize>
      </Suspense>
    </SheetComponent>
  );
};

export default Sheet;
