'use client';
import { use, useSyncExternalStore, useTransition } from 'react';
import type { DialogProps, ModalOverlayProps } from 'react-aria-components';
import {
  Button as AriaButton,
  Dialog,
  Heading,
  Modal,
  ModalOverlay,
  OverlayTriggerStateContext,
} from 'react-aria-components';

import clsx from 'clsx';
import { twMerge } from 'tailwind-merge';
import { Button } from '../button/Button';

interface ModalRootProps
  extends DialogProps,
  Pick<ModalOverlayProps, 'isOpen' | 'onOpenChange' | 'isKeyboardDismissDisabled' | 'isDismissable'> {
  className?: string;
}
const ModalRoot = (props: ModalRootProps) => {
  const { isOpen, onOpenChange, isKeyboardDismissDisabled, isDismissable, className, ...dialogProps } = props;
  return (
    <ModalOverlay
      isOpen={isOpen}
      onOpenChange={onOpenChange}
      isKeyboardDismissDisabled={isKeyboardDismissDisabled}
      isDismissable={isDismissable}
      className="absolute top-0 left-0 w-full h-full bg-black/70 z-100"
    >
      <Modal className="fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 supports-[translate:round(up,-50%,1px)]:translate-[round(up,-50%,1px)] min-w-75 bg-white outline-none drop-shadow-modal">
        <Dialog className={twMerge('outline-0', className)} {...dialogProps}>
          {props.children}
        </Dialog>
      </Modal>
    </ModalOverlay>
  );
};

interface ModalHeaderProps {
  hasCloseButton?: boolean;
  children: React.ReactNode;
}
const ModalHeader = (props: ModalHeaderProps) => {
  const ctx = use(OverlayTriggerStateContext);

  const { hasCloseButton = true } = props;
  return (
    <div className="px-5 py-4 flex items-center justify-between gap-1 border-b border-dabeeo-gray-eb">
      <Heading slot="title" className="text-lg text-primary font-bold">
        {props.children}
      </Heading>
      {hasCloseButton && (
        <AriaButton
          onClick={ctx?.close}
          className="text-dabeeo-black-47 cursor-pointer data-focus-visible:ring-2 ring-offset-2 ring-dabeeo-gray-34"
        >
          <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none">
            <path
              d="M18.25 2.4927L17.5074 1.75L10.0021 9.25678L2.49675 1.75L1.7542 2.4927L9.25955 9.99947L1.75 17.5073L2.49255 18.25L9.9979 10.7432L17.5032 18.25L18.2458 17.5073L10.7404 10.0005L18.25 2.4927Z"
              fill="currentColor"
              stroke="currentColor"
              strokeWidth="0.5"
            />
          </svg>
        </AriaButton>
      )}
    </div>
  );
};

interface ModalBodyProps extends React.PropsWithChildren {
  className?: string;
}
const ModalBody = (props: ModalBodyProps) => {
  return <div className={clsx('px-6 py-2.5', props.className)}>{props.children}</div>;
};

interface ModalFooterProps extends React.PropsWithChildren {}
const ModalFooter = (props: ModalFooterProps) => {
  return <div className="px-4 py-2.5 flex justify-center gap-2 border-t border-dabeeo-gray-eb">{props.children}</div>;
};

let _modals: (
  | {
    typeof: 'confirm';
    title?: string;
    content: string;
    confirm?: boolean;
    cancelText?: string;
    onCancel?: () => void;
    confirmText?: string;
    onConfirm: (close: () => void) => void;
  }
  | {
    typeof: 'alert';
    title?: string;
    content: string;
    cancelText?: string;
    onCancel?: () => void;
  }
)[] = [];
let listeners: (() => void)[] = [];
function subscribe(listener: () => void) {
  listeners = [...listeners, listener];
  return () => {
    listeners = listeners.filter((l) => l !== listener);
  };
}
function getSnapshot() {
  return _modals;
}

function emitChange() {
  for (const listener of listeners) {
    listener();
  }
}

type AlertProps = {
  title?: string;
  content?: string;
  cancelText?: string;
  onCancel?: () => void;
};
const alert = (props: AlertProps) => {
  _modals = [
    ..._modals,
    {
      typeof: 'alert',
      content: props.content || '',
      cancelText: props.cancelText || '확인',
      onCancel: props.onCancel,
    },
  ];
  emitChange();
};

const confirm = (props: {
  title?: string;
  content: string;
  cancelText?: string;
  onCancel?: () => void;
  confirmText?: string;
  onConfirm: (close: () => void) => void;
}) => {
  _modals = [
    ..._modals,
    {
      typeof: 'confirm',
      title: props.title,
      content: props.content,
      cancelText: props.cancelText,
      onCancel: props.onCancel,
      confirmText: props.confirmText,
      onConfirm: props.onConfirm,
    },
  ];
  emitChange();
};

function getServerSnapshot() {
  return _modals;
}

const ModalRegion = () => {
  const modals = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);

  const [isPending, startTransition] = useTransition();
  return (
    <>
      {modals.map((modal, idx) => (
        <ModalRoot
          key={`modal-${idx}`}
          aria-label={`모달 ${idx}`}
          className="w-75"
          isOpen
          onOpenChange={(isOpen) => {
            if (!isOpen) {
              _modals = _modals.filter((f) => f !== modal);
              emitChange();
            }
          }}
        >
          {({ close }) => (
            <>
              {modal.title && <ModalHeader>{modal.title}</ModalHeader>}
              <ModalBody className="px-7.5 py-8">
                <p className="text-sm text-dabeeo-black-34 font-medium text-center whitespace-pre-wrap">{modal.content}</p>
              </ModalBody>
              <ModalFooter>
                <Button
                  color="gray"
                  size="large"
                  autoFocus
                  isDisabled={isPending}
                  onClick={() => {
                    close();
                    if (typeof modal.onCancel === 'function') {
                      modal.onCancel();
                    }
                  }}
                >
                  {modal.cancelText || '취소'}
                </Button>
                {modal.typeof === 'confirm' && (
                  <Button
                    color="primary"
                    size="large"
                    isPending={isPending}
                    onClick={() => {
                      startTransition(modal.onConfirm.bind(null, close));
                    }}
                  >
                    {modal.confirmText || '확인'}
                  </Button>
                )}
              </ModalFooter>
            </>
          )}
        </ModalRoot>
      ))}
    </>
  );
};
export { alert, confirm, ModalBody, ModalFooter, ModalHeader, ModalRegion, ModalRoot };
export type { ModalBodyProps, ModalFooterProps, ModalHeaderProps, ModalRootProps };

