'use client'





import React, {
  createContext,
  useCallback,
  useContext,
  useEffect,
  useState,
  type ReactNode
} from 'react'
import { createRoot } from 'react-dom/client'
import { isPageTransitioning, onPageTransitionEnd } from '../animation/pageTransitionEffect'

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

export interface ToastOptions {
  id?: string
  title?: string
  message: string
  variant?: ToastVariant
  duration?: number // ms, default 4000
}

// add optional closing flag for exit animation
interface ToastInternal extends ToastOptions {
  id: string
  closing?: boolean
}

interface ToastContextValue {
  showToast: (options: ToastOptions) => void
}

// increase fade duration
const TOAST_ANIMATION_MS = 400 // fade-out duration in ms

// --- global toast store so toasts survive route changes ---
let globalToasts: ToastInternal[] = []
type ToastListener = (toasts: ToastInternal[]) => void
const toastListeners = new Set<ToastListener>()
const toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>()

// NEW: portal state (single global React root)
let toastPortalContainer: HTMLDivElement | null = null
let toastPortalRoot: ReturnType<typeof createRoot> | null = null
let toastPortalMounted = false

function notifyToastListeners() {
  for (const listener of toastListeners) {
    listener(globalToasts)
  }
}

function removeToastInternal(id: string) {
  // clear auto-dismiss timer
  const timeout = toastTimeouts.get(id)
  if (timeout) {
    clearTimeout(timeout)
    toastTimeouts.delete(id)
  }

  const existing = globalToasts.find(t => t.id === id)
  if (!existing) return

  if (existing.closing) {
    // already closing: hard-remove immediately
    globalToasts = globalToasts.filter(t => t.id !== id)
    notifyToastListeners()
    return
  }

  // mark as closing to trigger fade-out
  globalToasts = globalToasts.map(t =>
    t.id === id ? { ...t, closing: true } : t
  )
  notifyToastListeners()

  // remove after animation finishes
  setTimeout(() => {
    globalToasts = globalToasts.filter(t => t.id !== id)
    notifyToastListeners()
  }, TOAST_ANIMATION_MS)
}

function addToast(options: ToastOptions) {
  // Defer toast until page transition overlay has fully exited
  if (typeof window !== 'undefined' && isPageTransitioning) {
    onPageTransitionEnd(() => addToast(options))
    return
  }

  const id = options.id ?? `${Date.now()}-${Math.random().toString(36).slice(2)}`
  const toast: ToastInternal = {
    id,
    variant: options.variant ?? 'info',
    duration: options.duration ?? 4000,
    ...options
  }

  globalToasts = [...globalToasts, toast]
  notifyToastListeners()

  if (toast.duration && toast.duration > 0) {
    const timeout = setTimeout(() => {
      removeToastInternal(id)
    }, toast.duration)
    toastTimeouts.set(id, timeout)
  }
}

// NEW: mount a global portal once per browser session
function ensureToastPortalMounted() {
  if (toastPortalMounted) return
  if (typeof document === 'undefined') return

  toastPortalMounted = true
  toastPortalContainer = document.createElement('div')
  document.body.appendChild(toastPortalContainer)
  toastPortalRoot = createRoot(toastPortalContainer)

  // Defer actual render to avoid triggering nested updates during React render
  setTimeout(() => {
    if (!toastPortalRoot) return
    toastPortalRoot.render(<ToastViewport />)
  }, 0)
}

// --- context & provider ---

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

export function useToast(): ToastContextValue {
  const ctx = useContext(ToastContext)
  if (ctx) {
    // Normal path: inside <ToastProvider>
    return ctx
  }

  // Fallback path: no provider mounted, still use global store/portal
  if (typeof window !== 'undefined') {
    ensureToastPortalMounted()
  }

  return {
    showToast: (options: ToastOptions) => {
      addToast(options)
    }
  }
}

interface ToastProviderProps {
  children: ReactNode
}

export function ToastProvider({ children }: ToastProviderProps) {
  // ensure the global portal is mounted when any provider appears
  useEffect(() => {
    ensureToastPortalMounted()
  }, [])

  const showToast = useCallback((options: ToastOptions) => {
    addToast(options)
  }, [])

  return (
    <ToastContext.Provider value={{ showToast }}>
      {children}
    </ToastContext.Provider>
  )
}

// NEW: global viewport rendered via portal, independent of pages/providers
function ToastViewport() {
  const [toasts, setToasts] = useState<ToastInternal[]>(globalToasts)

  useEffect(() => {
    const listener: ToastListener = (next) => setToasts(next)
    toastListeners.add(listener)
    setToasts(globalToasts)
    return () => {
      toastListeners.delete(listener)
    }
  }, [])

  const handleClose = useCallback((id: string) => {
    removeToastInternal(id)
  }, [])

  if (!toasts.length) return null

  return (
    <>
      <div
        className="pp-toast-viewport pointer-events-none fixed inset-x-4 z-50 flex justify-end sm:inset-x-auto sm:right-4 sm:w-auto"
        style={{ bottom: 'calc(env(safe-area-inset-bottom, 0px) + var(--pp-toast-bottom, 5rem))' }}
      >
        <div className="flex max-h-[80vh] w-full flex-col gap-3 overflow-hidden sm:w-80">
          {toasts.map(t => (
            <ToastItem key={t.id} toast={t} onClose={() => handleClose(t.id)} />
          ))}
        </div>
      </div>

      <style jsx global>{`
        .pp-toast-viewport {
          --pp-toast-bottom: 5rem; /* desktop/tablet */
        }
        @media (max-width: 640px) {
          .pp-toast-viewport {
            --pp-toast-bottom: 7rem; /* mobile: lift higher above footer */
          }
        }
      `}</style>
    </>
  )
}

interface ToastItemProps {
  toast: ToastInternal
  onClose: () => void
}

const TOAST_ICONS: Record<ToastVariant, React.ReactElement> = {
  success: (
    <svg viewBox="0 0 20 20" fill="currentColor" className="h-4 w-4">
      <path fillRule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" clipRule="evenodd" />
    </svg>
  ),
  error: (
    <svg viewBox="0 0 20 20" fill="currentColor" className="h-4 w-4">
      <path fillRule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.28 7.22a.75.75 0 00-1.06 1.06L8.94 10l-1.72 1.72a.75.75 0 101.06 1.06L10 11.06l1.72 1.72a.75.75 0 101.06-1.06L11.06 10l1.72-1.72a.75.75 0 00-1.06-1.06L10 8.94 8.28 7.22z" clipRule="evenodd" />
    </svg>
  ),
  info: (
    <svg viewBox="0 0 20 20" fill="currentColor" className="h-4 w-4">
      <path fillRule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a.75.75 0 000 1.5h.253a.25.25 0 01.244.304l-.459 2.066A1.75 1.75 0 0010.747 15H11a.75.75 0 000-1.5h-.253a.25.25 0 01-.244-.304l.459-2.066A1.75 1.75 0 009.253 9H9z" clipRule="evenodd" />
    </svg>
  ),
  warning: (
    <svg viewBox="0 0 20 20" fill="currentColor" className="h-4 w-4">
      <path fillRule="evenodd" d="M8.485 2.495c.673-1.167 2.357-1.167 3.03 0l6.28 10.875c.673 1.167-.17 2.625-1.516 2.625H3.72c-1.347 0-2.189-1.458-1.515-2.625L8.485 2.495zM10 5a.75.75 0 01.75.75v3.5a.75.75 0 01-1.5 0v-3.5A.75.75 0 0110 5zm0 9a1 1 0 100-2 1 1 0 000 2z" clipRule="evenodd" />
    </svg>
  ),
}

const TOAST_VARIANT_STYLES: Record<ToastVariant, { card: string; iconWrap: string; title: string; message: string; close: string }> = {
  success: {
    card:     'border border-emerald-200 border-l-4 border-l-emerald-400 bg-emerald-50/90 shadow-[0_8px_32px_-8px_rgba(5,150,105,0.18)]',
    iconWrap: 'bg-emerald-100 text-emerald-600',
    title:    'text-emerald-800',
    message:  'text-emerald-900/80',
    close:    'text-emerald-400 hover:bg-emerald-100 hover:text-emerald-700',
  },
  error: {
    card:     'border border-red-200 border-l-4 border-l-red-400 bg-red-50/90 shadow-[0_8px_32px_-8px_rgba(220,38,38,0.18)]',
    iconWrap: 'bg-red-100 text-red-600',
    title:    'text-red-800',
    message:  'text-red-900/80',
    close:    'text-red-300 hover:bg-red-100 hover:text-red-700',
  },
  info: {
    card:     'border border-sky-200 border-l-4 border-l-sky-400 bg-sky-50/90 shadow-[0_8px_32px_-8px_rgba(14,165,233,0.18)]',
    iconWrap: 'bg-sky-100 text-sky-600',
    title:    'text-sky-800',
    message:  'text-sky-900/80',
    close:    'text-sky-300 hover:bg-sky-100 hover:text-sky-700',
  },
  warning: {
    card:     'border border-amber-200 border-l-4 border-l-amber-400 bg-amber-50/90 shadow-[0_8px_32px_-8px_rgba(217,119,6,0.18)]',
    iconWrap: 'bg-amber-100 text-amber-600',
    title:    'text-amber-800',
    message:  'text-amber-900/80',
    close:    'text-amber-300 hover:bg-amber-100 hover:text-amber-700',
  },
}

function ToastItem({ toast, onClose }: ToastItemProps) {
  const { title, message, variant } = toast
  const v = variant ?? 'info'
  const styles = TOAST_VARIANT_STYLES[v]

  // local visible state for entry animation
  const [visible, setVisible] = useState(false)

  useEffect(() => {
    const frame = requestAnimationFrame(() => setVisible(true))
    return () => cancelAnimationFrame(frame)
  }, [])

  const isClosing = !!toast.closing
  const motionClasses = isClosing
    ? 'opacity-0 translate-y-2 scale-95'
    : visible
      ? 'opacity-100 translate-y-0 scale-100'
      : 'opacity-0 translate-y-2 scale-95'

  return (
    <div
      className={`
        pointer-events-auto flex w-full items-start gap-3 rounded-2xl
        px-4 py-3.5 backdrop-blur-md transform transition-all duration-400
        ${motionClasses}
        ${styles.card}
      `}
    >
      <div className={`mt-0.5 flex h-7 w-7 shrink-0 items-center justify-center rounded-full ${styles.iconWrap}`}>
        {TOAST_ICONS[v]}
      </div>
      <div className="flex-1 min-w-0">
        {title && (
          <div className={`mb-0.5 text-[11px] font-bold uppercase tracking-widest ${styles.title}`}>
            {title}
          </div>
        )}
        <div className={`text-[13px] leading-snug ${styles.message}`}>{message}</div>
      </div>
      <button
        type="button"
        onClick={onClose}
        className={`ml-1 mt-0.5 inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-lg text-sm transition-colors focus:outline-none focus:ring-2 focus:ring-slate-300 ${styles.close}`}
        aria-label="Close notification"
      >
        ×
      </button>
    </div>
  )
}
