import React, { useImperativeHandle, useState } from 'react';
import { useTheme } from '@emotion/react';

import Toast from './Toast';
import { ToastContainerWrapper } from './StyledToast';
import type { ToastContainerProps, ToastItemProps } from './types';
import type { ToastControllerContextType } from './ToastContext';

const generateID = () =>
  (performance.now().toString(36) + Math.random().toString(36)).replace(
    /\./g,
    ''
  );

const SingleToastDisplay = ({
  toastList,
  setToastList,
}: {
  toastList: ToastItemProps[];
  setToastList: React.Dispatch<React.SetStateAction<ToastItemProps[]>>;
}) => {
  const theme = useTheme();
  const toast = toastList[toastList.length - 1];

  return toast ? (
    <Toast
      {...toast.props}
      key={toast.id}
      style={{ marginBottom: theme.space.small }}
      onDismiss={() => {
        setToastList((state) => state.filter((item) => item.id !== toast.id));
        toast.props.onDismiss?.();
      }}
    />
  ) : null;
};

const ToastContainer = React.forwardRef<
  ToastControllerContextType,
  ToastContainerProps
>(({ displayType = 'single', position = 'bottom', style }, ref) => {
  const theme = useTheme();
  const [toastList, setToastList] = useState<ToastItemProps[]>([]);

  useImperativeHandle(ref, () => ({
    show: (props) => {
      const item = {
        id: generateID(),
        props,
      };

      setToastList((state) => [item, ...state]);
      return item.id;
    },
    hide: (id) => {
      setToastList((state) => state.filter((item) => item.id !== id));
    },
    clearAll: () => {
      setToastList([]);
    },
  }));

  return (
    <ToastContainerWrapper
      pointerEvents="box-none"
      position={position}
      style={style}
    >
      {displayType === 'single' ? (
        <SingleToastDisplay toastList={toastList} setToastList={setToastList} />
      ) : (
        toastList.map(({ id, props }: ToastItemProps) => (
          <Toast
            {...props}
            key={id}
            style={{ marginBottom: theme.space.small }}
            onDismiss={() => {
              setToastList((state) => state.filter((item) => item.id !== id));
              props.onDismiss?.();
            }}
          />
        ))
      )}
    </ToastContainerWrapper>
  );
});

ToastContainer.displayName = 'ToastContainer';

export default ToastContainer;
