"use client";

import { Portal } from "@/lib/portal/components";
import { atom, useAtom } from "jotai";
import React, { useCallback, useEffect, useState } from "react";
import { ReactNode } from "react";

type toastMessage = {
  msg: ReactNode;
  type?: "error" | "default";
  fading: boolean;
  duration?: number;
};

type IDToastMessage = toastMessage & {
  id: string;
};

const toastAtom = atom<IDToastMessage[]>([]);

export function useToast() {
  const [_, setToasts] = useAtom(toastAtom);

  const createToast = useCallback(
    (t: toastMessage) => {
      const idd = { ...t, id: crypto.randomUUID() };
      setToasts((toasts) => {
        return [...toasts, idd];
      });

      return idd;
    },
    [setToasts]
  );

  const clearToast = useCallback(
    (t: toastMessage) => setToasts((toasts) => toasts.filter((to) => to != t)),
    [setToasts]
  );

  return {
    createToast,
    clearToast,
  };
}

export function Toaster() {
  const [toasts, setToasts] = useAtom(toastAtom);

  const clearToast = useCallback(
    (t: toastMessage) => {
      setToasts((toasts) => {
        return toasts.filter((to) => to !== t);
      });
    },
    [setToasts]
  );

  if (!toasts.length) return <></>;
  return (
    <Portal>
      <div className="fixed bottom-12 left-1/2 -translate-x-1/2 max-w-[95vw] flex flex-col gap-4">
        {toasts.map((t) => (
          <Toast key={"toast " + t.id} toast={t} clearToast={clearToast} />
        ))}
      </div>
    </Portal>
  );
}

function Toast(props: {
  toast: toastMessage;
  clearToast: (t: toastMessage) => void;
}) {
  const { toast, clearToast } = props;
  const [fading, setFading] = useState(false);

  const clear = useCallback(() => {
    setFading(true);
    setTimeout(() => {
      clearToast(toast);
    }, 300);
  }, [clearToast, toast]);

  const fadeOut = useCallback(() => {
    setTimeout(clear, toast.duration ?? 3000);
  }, [clear, toast]);

  useEffect(() => {
    if (!toast.fading) return;
    fadeOut();
  }, [fadeOut, toast]);

  return (
    <div
      data-fading={fading}
      data-type={toast.type}
      className="relative p-6 px-16 toast data-[fading=true]:fade-toast rounded-md bg-mixed-300 data-[type=error]:bg-red-900 border-2 border-mixed-400 data-[type=error]:border-red-700"
    >
      {toast.msg}
      {!toast.fading && (
        <button
          className="top-2 right-2 text-xs absolute"
          onClick={() => clear()}
        >
          Dismiss
        </button>
      )}
    </div>
  );
}
