import React, { ReactNode, useContext } from "react";
import toaster from "toasted-notes";
import classNames from "classnames";
import { Box, BoxProps } from "../Box";
import { Flex } from "../Flex";
import { CloseButton } from "../CloseButton";
import { StatusIcon } from "../Icon";
import { bem } from "../../utilities/bem";
import { STATUS_VARIANT } from "../../types";
import { StatusContext } from "../../contexts/status";
import { ArrowLink, ArrowLinkProps } from "../ArrowLink";

const cn = "Toast";

// @Deprecated
type ToastPosition = "top-right";

export interface ToastProps extends BoxProps {
  title: string;
  content: ReactNode;
  onClose: () => void;
  variant?: STATUS_VARIANT;
}

export interface ToastMessageProps {
  children: ReactNode;
  withIcon?: boolean;
  className?: string;
}

export interface ShowToastProps {
  title: string;
  content: ReactNode;
  position?: ToastPosition;
  duration?: number;
  className?: string;
  variant?: STATUS_VARIANT;
}

export const ToastLink = ({ children, className, ...rest }: ArrowLinkProps) => (
  <ArrowLink
    className={classNames(bem(cn, { e: "link" }), className)}
    {...rest}
  >
    {children}
  </ArrowLink>
);

export const ToastMessage = ({
  children,
  withIcon,
  className,
}: ToastMessageProps) => {
  const variant = useContext(StatusContext);

  return (
    <Box className={classNames(bem(cn, { e: "message" }), className)}>
      {withIcon ? (
        <Box>
          <StatusIcon status={variant} className={bem(cn, { e: "icon" })} />
          {children}
        </Box>
      ) : (
        <>{children}</>
      )}
    </Box>
  );
};

export const Toast = (props: ToastProps) => {
  const {
    title,
    onClose,
    content,
    variant = STATUS_VARIANT.DEFAULT,
    className,
    id,
    ...rest
  } = props;

  return (
    <StatusContext.Provider value={variant}>
      <Box
        id={id}
        className={classNames(bem(cn), bem(cn, { m: variant }), className)}
        {...rest}
      >
        {title && (
          <Flex className={bem(cn, { e: "header" })}>
            {title}

            <CloseButton
              className={bem(cn, { e: "close" })}
              onClick={onClose}
            />
          </Flex>
        )}

        {content && <Flex className={bem(cn, { e: "body" })}>{content}</Flex>}
      </Box>
    </StatusContext.Provider>
  );
};

export const showToast = ({
  position = "top-right",
  duration = 5000,
  variant = STATUS_VARIANT.DEFAULT,
  title,
  content,
  className,
  ...rest
}: ShowToastProps) => {
  const options = {
    position,
    duration,
  };

  return toaster.notify(
    ({ onClose, id }: { onClose: () => void; id?: string }) => (
      <Toast
        {...{
          title,
          onClose,
          content,
          variant,
          className,
          id,
          ...rest,
        }}
      />
    ),
    options,
  );
};

Toast.Link = ToastLink;
Toast.Message = ToastMessage;
