"use client"

import * as React from "react"
import { Toast as ToastPrimitive } from "@base-ui/react/toast"
import { XIcon } from "lucide-react"

import { cn } from "@/lib/utils"

export const toastManager = ToastPrimitive.createToastManager()

type ToastType = "default" | "success" | "error" | "warning" | "info"

interface ToastData {
  type?: ToastType
}

function ToastList() {
  const { toasts } = ToastPrimitive.useToastManager<ToastData>()

  return (
    <ToastPrimitive.Viewport className="fixed top-4 right-4 z-9999 flex w-full max-w-sm flex-col gap-2 outline-none sm:top-6 sm:right-6">
      {toasts.map((toast) => (
        <ToastPrimitive.Root
          key={toast.id}
          toast={toast}
          className={cn(
            "group relative flex w-full flex-col gap-1 overflow-hidden rounded-xl px-4 py-3 text-sm shadow-lg ring-1 transition-all duration-200",
            "data-[transitionstatus=starting]:-translate-y-2 data-[transitionstatus=starting]:opacity-0",
            "data-[transitionstatus=ending]:translate-x-full data-[transitionstatus=ending]:opacity-0",
            toast.data?.type === "success" &&
              "bg-emerald-50 text-emerald-900 ring-emerald-200 dark:bg-emerald-950 dark:text-emerald-100 dark:ring-emerald-800",
            toast.data?.type === "error" &&
              "bg-red-50 text-red-900 ring-red-200 dark:bg-red-950 dark:text-red-100 dark:ring-red-800",
            toast.data?.type === "warning" &&
              "bg-amber-50 text-amber-900 ring-amber-200 dark:bg-amber-950 dark:text-amber-100 dark:ring-amber-800",
            toast.data?.type === "info" &&
              "bg-sky-50 text-sky-900 ring-sky-200 dark:bg-sky-950 dark:text-sky-100 dark:ring-sky-800",
            (!toast.data?.type || toast.data.type === "default") &&
              "bg-white text-foreground ring-foreground/10 dark:bg-neutral-900"
          )}
        >
          <ToastPrimitive.Content className="flex items-start justify-between gap-3">
            <div className="flex flex-col gap-0.5">
              {toast.title && (
                <ToastPrimitive.Title className="text-xs font-semibold leading-snug">
                  {toast.title}
                </ToastPrimitive.Title>
              )}
              {toast.description && (
                <ToastPrimitive.Description className="text-xs opacity-80">
                  {toast.description}
                </ToastPrimitive.Description>
              )}
            </div>
            <ToastPrimitive.Close className="mt-0.5 shrink-0 rounded-md p-1 opacity-60 transition-opacity hover:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring">
              <XIcon className="size-3.5" />
              <span className="sr-only">Dismiss</span>
            </ToastPrimitive.Close>
          </ToastPrimitive.Content>

          {toast.actionProps && (
            <ToastPrimitive.Action
              {...toast.actionProps}
              className="mt-1 self-start rounded-md px-2 py-1 text-xs font-medium underline-offset-2 hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
            />
          )}
        </ToastPrimitive.Root>
      ))}
    </ToastPrimitive.Viewport>
  )
}

function Toaster() {
  return (
    <ToastPrimitive.Provider toastManager={toastManager}>
      <ToastList />
    </ToastPrimitive.Provider>
  )
}

function toast(options: {
  title?: string
  description?: string
  type?: ToastType
  timeout?: number
  actionLabel?: string
  onAction?: () => void
}) {
  toastManager.add({
    title: options.title,
    description: options.description,
    timeout: options.timeout ?? 4000,
    data: { type: options.type ?? "default" },
    ...(options.actionLabel && {
      actionProps: {
        children: options.actionLabel,
        onClick: options.onAction,
      },
    }),
  })
}

toast.success = (title: string, description?: string) =>
  toast({ title, description, type: "success" })

toast.error = (title: string, description?: string) =>
  toast({ title, description, type: "error" })

toast.warning = (title: string, description?: string) =>
  toast({ title, description, type: "warning" })

toast.info = (title: string, description?: string) =>
  toast({ title, description, type: "info" })

export { Toaster, toast }
