import { cn } from '@/lib/utils';
import { AnimatePresence, motion } from 'framer-motion';
import { AlertCircle, CheckCircle2, Info, X } from 'lucide-react';
import { createContext, ReactNode, useCallback, useContext, useMemo, useState } from 'react';

type Kind = 'success' | 'error' | 'info';
type Toast = { id: number; kind: Kind; title: string; description?: string };
type Api = { toast: (t: Omit<Toast, 'id' | 'kind'> & { kind?: Kind; duration?: number }) => void };

const Ctx = createContext<Api>({ toast: () => {} });
export const useToast = () => useContext(Ctx);

const ICON = { success: CheckCircle2, error: AlertCircle, info: Info } as const;
let seq = 0;

export function ToastProvider({ children }: { children: ReactNode }) {
    const [items, setItems] = useState<Toast[]>([]);
    const dismiss = useCallback((id: number) => setItems((l) => l.filter((t) => t.id !== id)), []);

    const toast = useCallback<Api['toast']>(
        ({ kind = 'success', duration = 3800, ...t }) => {
            const id = ++seq;
            setItems((l) => [...l.slice(-3), { id, kind, ...t }]);
            setTimeout(() => dismiss(id), duration);
        },
        [dismiss],
    );
    const api = useMemo(() => ({ toast }), [toast]);

    return (
        <Ctx.Provider value={api}>
            {children}
            <div className="pointer-events-none fixed inset-x-0 bottom-0 z-[60] flex flex-col items-center gap-2 p-4 sm:items-end sm:p-6" aria-live="polite">
                <AnimatePresence initial={false}>
                    {items.map((t) => {
                        const Icon = ICON[t.kind];
                        return (
                            <motion.div
                                key={t.id}
                                layout
                                initial={{ opacity: 0, y: 16, scale: 0.97 }}
                                animate={{ opacity: 1, y: 0, scale: 1 }}
                                exit={{ opacity: 0, scale: 0.97, transition: { duration: 0.15 } }}
                                transition={{ type: 'spring', stiffness: 420, damping: 32 }}
                                role={t.kind === 'error' ? 'alert' : 'status'}
                                className="glass pointer-events-auto flex w-full max-w-sm items-start gap-3 rounded-xl border border-border p-3.5 shadow-lift"
                            >
                                <Icon className={cn('mt-0.5 size-4 shrink-0', t.kind === 'error' ? 'text-destructive' : t.kind === 'success' ? 'text-primary' : 'text-muted-foreground')} />
                                <div className="min-w-0 flex-1">
                                    <p className="text-sm font-medium">{t.title}</p>
                                    {t.description && <p className="mt-0.5 text-caption">{t.description}</p>}
                                </div>
                                <button onClick={() => dismiss(t.id)} aria-label="Dismiss" className="rounded p-0.5 text-muted-foreground hover:text-foreground"><X className="size-3.5" /></button>
                            </motion.div>
                        );
                    })}
                </AnimatePresence>
            </div>
        </Ctx.Provider>
    );
}
