import {
  createContext,
  useCallback,
  useContext,
  useEffect,
  useMemo,
  useRef,
  useState,
  type ReactNode,
} from 'react'
import styles from '../components/Toast.module.css'

export type ToastVariant = 'success' | 'error' | 'info'

interface ToastItem {
  id: number
  message: string
  variant: ToastVariant
}

interface ToastContextValue {
  showToast: (message: string, variant?: ToastVariant) => void
}

const ToastContext = createContext<ToastContextValue | null>(null)

const TOAST_DURATION_MS = 3200
const ANIMATION_MS = 200

export function ToastProvider({ children }: { children: ReactNode }) {
  const [toast, setToast] = useState<ToastItem | null>(null)
  const [closing, setClosing] = useState(false)
  const idRef = useRef(0)
  const dismissTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)
  const closeTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)

  const clearTimers = useCallback(() => {
    if (dismissTimerRef.current) {
      clearTimeout(dismissTimerRef.current)
      dismissTimerRef.current = null
    }
    if (closeTimerRef.current) {
      clearTimeout(closeTimerRef.current)
      closeTimerRef.current = null
    }
  }, [])

  const dismissToast = useCallback(() => {
    setClosing(true)
    closeTimerRef.current = setTimeout(() => {
      setToast(null)
      setClosing(false)
    }, ANIMATION_MS)
  }, [])

  const showToast = useCallback(
    (message: string, variant: ToastVariant = 'info') => {
      clearTimers()
      idRef.current += 1
      setClosing(false)
      setToast({ id: idRef.current, message, variant })

      dismissTimerRef.current = setTimeout(() => {
        dismissToast()
      }, TOAST_DURATION_MS)
    },
    [clearTimers, dismissToast],
  )

  useEffect(() => clearTimers, [clearTimers])

  const value = useMemo(() => ({ showToast }), [showToast])

  return (
    <ToastContext.Provider value={value}>
      {children}
      <div className={styles.container} aria-live="polite" aria-atomic="true">
        {toast && (
          <div
            key={toast.id}
            className={`${styles.toast} ${styles[toast.variant]} ${closing ? styles.toastOut : styles.toastIn}`}
            role="status"
          >
            {toast.message}
          </div>
        )}
      </div>
    </ToastContext.Provider>
  )
}

export function useToast() {
  const context = useContext(ToastContext)
  if (!context) {
    throw new Error('useToast must be used within ToastProvider')
  }
  return context
}
