'use client'

import { useEffect, useState } from 'react'
import { AlertCircle, CheckCircle2, Info, X } from 'lucide-react'

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

type ToastType = 'default' | 'success' | 'error'

type ToastPayload = {
  title: string
  description?: string
  type?: ToastType
}

type ToastItem = ToastPayload & {
  id: string
}

const TOAST_EVENT = 'graduation-certificate-toast'

function emitToast(payload: ToastPayload) {
  window.dispatchEvent(new CustomEvent<ToastPayload>(TOAST_EVENT, { detail: payload }))
}

export const toast = Object.assign(
  (title: string, options?: { description?: string }) =>
    emitToast({ title, description: options?.description, type: 'default' }),
  {
    success: (title: string, options?: { description?: string }) =>
      emitToast({ title, description: options?.description, type: 'success' }),
    error: (title: string, options?: { description?: string }) =>
      emitToast({ title, description: options?.description, type: 'error' })
  }
)

export function Toaster() {
  const [toasts, setToasts] = useState<ToastItem[]>([])

  useEffect(() => {
    function handleToast(event: Event) {
      const payload = (event as CustomEvent<ToastPayload>).detail
      const id = crypto.randomUUID()

      setToasts((current) => [{ ...payload, id }, ...current].slice(0, 5))
      window.setTimeout(() => {
        setToasts((current) => current.filter((toastItem) => toastItem.id !== id))
      }, 3600)
    }

    window.addEventListener(TOAST_EVENT, handleToast)
    return () => window.removeEventListener(TOAST_EVENT, handleToast)
  }, [])

  return (
    <div className="fixed right-4 top-4 z-50 flex w-[min(420px,calc(100vw-2rem))] flex-col gap-2">
      {toasts.map((toastItem) => {
        const Icon =
          toastItem.type === 'success'
            ? CheckCircle2
            : toastItem.type === 'error'
              ? AlertCircle
              : Info

        return (
          <div
            key={toastItem.id}
            className={cn(
              'rounded-lg border bg-card p-4 text-card-foreground shadow-lg',
              toastItem.type === 'success' && 'border-primary/40',
              toastItem.type === 'error' && 'border-destructive/50 text-destructive'
            )}
          >
            <div className="flex gap-3">
              <Icon className="mt-0.5 h-4 w-4 shrink-0" />
              <div className="min-w-0 flex-1">
                <p className="text-sm font-medium leading-none">{toastItem.title}</p>
                {toastItem.description ? (
                  <p className="mt-2 text-sm text-muted-foreground">{toastItem.description}</p>
                ) : null}
              </div>
              <button
                type="button"
                className="rounded-sm opacity-70 transition-opacity hover:opacity-100"
                onClick={() =>
                  setToasts((current) =>
                    current.filter((currentToast) => currentToast.id !== toastItem.id)
                  )
                }
                aria-label="关闭提示"
              >
                <X className="h-4 w-4" />
              </button>
            </div>
          </div>
        )
      })}
    </div>
  )
}
