"use client";

import * as ToastPrimitives from "@radix-ui/react-toast";
import { Box, Flex, Text } from "@radix-ui/themes";
import { CheckIcon, CircleSlashIcon, XCircleIcon, XIcon } from "lucide-react";
import { createContext, useState } from "react";

export type ToastData = {
  title: string,
  description?: string,
  variant?: 'normal' | 'error' | 'success',
};

function genId() {
  return `${Math.random()}${Date.now()}`; // good enough i guess
}

type ToastDataInternal = ToastData & { id: string };

export const ToastContext = createContext((toast: ToastData) => { });

export default function ToastProvider({
  children,
}: {
  children: React.ReactNode
}) {
  const [toasts, setToasts] = useState<ToastDataInternal[]>([]);

  return (
    <ToastPrimitives.Provider>
      {toasts.map((toast) => (
        <Toast
          key={toast.id}
          toast={toast}
          onClosed={() => setToasts(toasts.filter((t) => t.id != toast.id))}
        />
      ))}

      <ToastContext.Provider value={(toast: ToastData) => {
        // Updating the "local" `toasts` variable before calling `setToasts()` allows us to
        // spawn multiple toasts without re-rendering. Otherwise, calling `toast()` twice
        // will only display the last toast.
        toasts.push({ ...toast, id: genId() });
        setToasts([...toasts]);
      }}>
        {children}
      </ToastContext.Provider>
      <ToastPrimitives.Viewport className="ToastViewport" />
    </ToastPrimitives.Provider>
  );
}

function Toast({ toast, onClosed }: { toast: ToastData, onClosed: () => void }) {
  return (
    <ToastPrimitives.Root
      className={`ToastRoot`}
      duration={5000}
      onOpenChange={(state) => !state && onClosed()}
    >
      <Flex justify="between" align="center" gap="4">
        <Text>
          {
            toast.variant == "error"
              ? <CircleSlashIcon />
              : toast.variant == "success"
              ? <CheckIcon />
              : <></>
          }
        </Text>
        <Box grow="1">
          <ToastPrimitives.Title className="ToastTitle">{toast.title}</ToastPrimitives.Title>
          {toast.description && <ToastPrimitives.Description className="ToastDescription">{toast.description}</ToastPrimitives.Description>}
        </Box>
      </Flex>
      <ToastPrimitives.Close className="bg-transparent border-none p-0">
        <Text color="gray"><XIcon size="16" /></Text>
      </ToastPrimitives.Close>
    </ToastPrimitives.Root>
  );
}
