import { createContext, useContext, useState, useCallback, useEffect, useRef } from 'react'
import { IconCheck, IconX, IconInfoCircle, IconAlertTriangle } from '@tabler/icons-react'

type ToastType = 'success' | 'error' | 'info' | 'warning'

interface Toast {
  id: string
  message: string
  type: ToastType
  duration: number
}

interface ToastAPI {
  success: (msg: string, duration?: number) => void
  error: (msg: string, duration?: number) => void
  info: (msg: string, duration?: number) => void
  warning: (msg: string, duration?: number) => void
}

const ToastContext = createContext<ToastAPI>({
  success: () => {},
  error: () => {},
  info: () => {},
  warning: () => {},
})

export function useToast() {
  return useContext(ToastContext)
}

// global emitter for non-React code (api.ts etc)
type ToastFn = (msg: string, type?: string) => void
let globalToast: ToastFn | null = null
export function setGlobalToast(fn: ToastFn) { globalToast = fn }
export function emitToast(msg: string, type: ToastType = 'info') {
  if (globalToast) globalToast(msg, type)
}

let idCounter = 0

const TYPE_COLORS: Record<ToastType, string> = {
  success: 'var(--success)',
  error: 'var(--error)',
  warning: 'var(--warning)',
  info: 'var(--info)',
}

const TYPE_ICONS: Record<ToastType, typeof IconCheck> = {
  success: IconCheck,
  error: IconX,
  warning: IconAlertTriangle,
  info: IconInfoCircle,
}

const MAX_VISIBLE = 5

function ToastItem({ toast, onDismiss }: { toast: Toast; onDismiss: (id: string) => void }) {
  const [exiting, setExiting] = useState(false)
  const timerRef = useRef<ReturnType<typeof setTimeout>>()
  const Icon = TYPE_ICONS[toast.type]

  useEffect(() => {
    timerRef.current = setTimeout(() => {
      setExiting(true)
      setTimeout(() => onDismiss(toast.id), 200)
    }, toast.duration)
    return () => clearTimeout(timerRef.current)
  }, [toast.id, toast.duration, onDismiss])

  const handleClose = () => {
    clearTimeout(timerRef.current)
    setExiting(true)
    setTimeout(() => onDismiss(toast.id), 200)
  }

  return (
    <div
      style={{
        display: 'flex',
        alignItems: 'center',
        gap: 10,
        padding: '10px 14px',
        background: 'var(--surface)',
        border: '1px solid var(--border)',
        borderLeft: `3px solid ${TYPE_COLORS[toast.type]}`,
        borderRadius: 'var(--radius-md)',
        boxShadow: 'var(--shadow-md)',
        fontSize: 'var(--text-sm)',
        color: 'var(--text)',
        maxWidth: 400,
        minWidth: 220,
        animation: exiting ? 'toastOut 200ms ease-out forwards' : 'toastIn 250ms var(--ease-out)',
        pointerEvents: 'auto',
      }}
    >
      <Icon
        size={16}
        stroke={2.5}
        style={{ color: TYPE_COLORS[toast.type], flexShrink: 0 }}
        aria-hidden="true"
      />
      <span style={{ flex: 1, lineHeight: 1.4 }}>{toast.message}</span>
      <button
        onClick={handleClose}
        aria-label="Dismiss"
        style={{
          background: 'none',
          border: 'none',
          color: 'var(--text-tertiary)',
          cursor: 'pointer',
          padding: 2,
          lineHeight: 0,
          flexShrink: 0,
        }}
      >
        <IconX size={14} stroke={2} />
      </button>
    </div>
  )
}

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

  const dismiss = useCallback((id: string) => {
    setToasts((prev) => prev.filter((t) => t.id !== id))
  }, [])

  const add = useCallback((message: string, type: ToastType, duration = 4000) => {
    const id = `toast-${++idCounter}`
    setToasts((prev) => {
      const next = [...prev, { id, message, type, duration }]
      return next.slice(-MAX_VISIBLE)
    })
  }, [])

  const api: ToastAPI = {
    success: useCallback((msg: string, dur?: number) => add(msg, 'success', dur), [add]),
    error: useCallback((msg: string, dur?: number) => add(msg, 'error', dur), [add]),
    info: useCallback((msg: string, dur?: number) => add(msg, 'info', dur), [add]),
    warning: useCallback((msg: string, dur?: number) => add(msg, 'warning', dur), [add]),
  }

  useEffect(() => {
    setGlobalToast((msg, type) => add(msg, (type as ToastType) || 'info'))
    return () => { globalToast = null }
  }, [add])

  return (
    <ToastContext.Provider value={api}>
      {children}
      <div
        role="status"
        aria-live="polite"
        aria-label="Notifications"
        style={{
          position: 'fixed',
          top: 16,
          left: '50%',
          transform: 'translateX(-50%)',
          zIndex: 9999,
          display: 'flex',
          flexDirection: 'column',
          gap: 8,
          pointerEvents: 'none',
        }}
      >
        {toasts.map((t) => (
          <ToastItem key={t.id} toast={t} onDismiss={dismiss} />
        ))}
      </div>
    </ToastContext.Provider>
  )
}
