import { atom } from "jotai";
import type { ToastInstance } from "../components/Toasts";
import { generateId } from "./generateId";
import { jotaiStore } from "./jotai";

export const toastsAtom = atom<ToastInstance[]>([]);

export function showToast({
  id,
  timeout = 5000,
  ...props
}: Omit<ToastInstance, "id" | "timeout" | "uniqueKey"> & {
  id?: ToastInstance["id"];
  timeout?: ToastInstance["timeout"];
}) {
  id = id ?? generateId();
  const uniqueKey = generateId();

  const toasts = jotaiStore.get(toastsAtom);
  const toastWithSameId = toasts.find((t) => t.id === id);

  let delay = 0;
  if (toastWithSameId) {
    hideToast(toastWithSameId);
    // Allow enough time for old toast to animate out
    delay = 200;
  }

  setTimeout(() => {
    const newToast: ToastInstance = { id, uniqueKey, timeout, ...props };
    if (timeout != null) {
      setTimeout(() => hideToast(newToast), timeout);
    }
    jotaiStore.set(toastsAtom, (prev) => [...prev, newToast]);
  }, delay);

  return id;
}

export function hideToastById(id: string) {
  const toast = jotaiStore.get(toastsAtom).find((t) => t.id === id);
  if (toast) hideToast(toast);
}

export function hideToast(toHide: ToastInstance) {
  jotaiStore.set(toastsAtom, (all) => {
    const t = all.find((t) => t.uniqueKey === toHide.uniqueKey);
    t?.onClose?.();
    return all.filter((t) => t.uniqueKey !== toHide.uniqueKey);
  });
}

export function showErrorToast<T>({
  id,
  title,
  message,
}: {
  id: string;
  title: string;
  message: T;
}) {
  return showToast({
    id,
    color: "danger",
    timeout: null,
    message: (
      <div className="w-full">
        <h2 className="text-lg font-bold mb-2">{title}</h2>
        <div className="whitespace-pre-wrap wrap-break-word">{String(message)}</div>
      </div>
    ),
  });
}
