import * as React from "react";

type ToastType = "success" | "error" | "info";

interface Toast {
  id: string;
  message: string;
  type: ToastType;
}

let subscribers: ((toasts: Toast[]) => void)[] = [];
let toasts: Toast[] = [];

const notify = () => {
  for (const sub of subscribers) {
    sub(toasts);
  }
};

const toastBase = (message: string, type: ToastType = "success") => {
  if (
    toasts.some((toast) => toast.message === message && toast.type === type)
  ) {
    return;
  }
  const id = Math.random().toString(36).substring(2, 9);
  toasts = [...toasts, { id, message, type }];
  notify();

  setTimeout(() => {
    toasts = toasts.filter((t) => t.id !== id);
    notify();
  }, 3000);
};

export const toast = Object.assign(toastBase, {
  success: (message: string, options?: { description?: string }) => {
    const finalMessage = options?.description
      ? `${message}
${options.description}`
      : message;
    toastBase(finalMessage, "success");
  },
  error: (message: string, options?: { description?: string }) => {
    const finalMessage = options?.description
      ? `${message}
${options.description}`
      : message;
    toastBase(finalMessage, "error");
  },
  info: (message: string, options?: { description?: string }) => {
    const finalMessage = options?.description
      ? `${message}
${options.description}`
      : message;
    toastBase(finalMessage, "info");
  },
});

export const useToastState = () => {
  const [state, setState] = React.useState<Toast[]>(toasts);

  React.useEffect(() => {
    subscribers.push(setState);
    return () => {
      subscribers = subscribers.filter((sub) => sub !== setState);
    };
  }, []);

  return state;
};
