"use client";
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, } from "react";
import { createPortal } from "react-dom";
import { cn } from "../../../utils/cn";
const variantStyles = {
    success: "bg-success-50 dark:bg-success-900/30 border-success-200 dark:border-success-800 text-success-800 dark:text-success-200",
    info: "bg-info-50 dark:bg-info-900/30 border-info-200 dark:border-info-800 text-info-800 dark:text-info-200",
};
export const Toast = ({ message, variant = "success", duration = 3000, onClose, className, }) => {
    useEffect(() => {
        if (!onClose || duration <= 0)
            return;
        const timer = setTimeout(onClose, duration);
        return () => clearTimeout(timer);
    }, [duration, onClose]);
    if (!message)
        return null;
    const toastContent = (_jsx("div", { className: cn("fixed bottom-4 right-4 z-[100] px-4 py-3 rounded-lg border shadow-lg text-sm font-medium", variantStyles[variant], className), role: "status", "aria-live": "polite", children: message }));
    if (typeof document !== "undefined" && document.body) {
        return createPortal(toastContent, document.body);
    }
    return toastContent;
};
export default Toast;
const ToastContext = createContext(null);
export function useToast() {
    const ctx = useContext(ToastContext);
    if (!ctx)
        throw new Error("useToast must be used within ToastProvider");
    return ctx;
}
function makeId() {
    return `toast-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
}
export function ToastProvider({ children }) {
    const [toasts, setToasts] = useState([]);
    const timeoutsRef = useRef({});
    const closeToast = useCallback((id) => {
        setToasts((prev) => prev.filter((t) => t.id !== id));
        const t = timeoutsRef.current[id];
        if (t)
            window.clearTimeout(t);
        delete timeoutsRef.current[id];
    }, []);
    const pushToast = useCallback((options) => {
        const id = options.id || makeId();
        const toast = {
            id,
            message: options.message,
            variant: options.variant || "info",
            durationMs: options.durationMs ?? 5000,
            createdAt: Date.now(),
        };
        setToasts((prev) => [toast, ...prev].slice(0, 4));
        const timeout = window.setTimeout(() => {
            closeToast(id);
        }, toast.durationMs);
        timeoutsRef.current[id] = timeout;
        return id;
    }, [closeToast]);
    useEffect(() => {
        return () => {
            for (const id of Object.keys(timeoutsRef.current)) {
                window.clearTimeout(timeoutsRef.current[id]);
            }
            timeoutsRef.current = {};
        };
    }, []);
    const value = useMemo(() => ({ pushToast, closeToast }), [pushToast, closeToast]);
    return (_jsxs(ToastContext.Provider, { value: value, children: [children, _jsx(ToastViewport, { toasts: toasts, onClose: closeToast })] }));
}
function ToastViewport({ toasts, onClose, }) {
    if (toasts.length === 0)
        return null;
    const viewport = (_jsx("div", { className: "fixed top-4 right-4 z-[9999] flex flex-col gap-3 w-[320px] max-w-[calc(100vw-2rem)] pointer-events-none", children: toasts.map((t) => (_jsx(ToastCard, { toast: t, onClose: () => onClose(t.id) }, t.id))) }));
    if (typeof document !== "undefined" && document.body) {
        return createPortal(viewport, document.body);
    }
    return viewport;
}
function ToastCard({ toast, onClose, }) {
    const startXRef = useRef(null);
    const [dx, setDx] = useState(0);
    const [isDragging, setIsDragging] = useState(false);
    const onPointerDown = (e) => {
        startXRef.current = e.clientX;
        setIsDragging(true);
    };
    const onPointerMove = (e) => {
        if (!isDragging || startXRef.current == null)
            return;
        setDx(e.clientX - startXRef.current);
    };
    const onPointerUp = () => {
        if (!isDragging)
            return;
        setIsDragging(false);
        startXRef.current = null;
        if (Math.abs(dx) > 80) {
            onClose();
            return;
        }
        setDx(0);
    };
    const styles = {
        transform: dx ? `translateX(${dx}px)` : undefined,
        transition: isDragging ? "none" : "transform 150ms ease",
    };
    const variantClasses = toast.variant === "success"
        ? "border-success-200 dark:border-success-800 bg-success-50/95 dark:bg-success-900/30 text-success-800 dark:text-success-200"
        : toast.variant === "error"
            ? "border-error-200 dark:border-error-800 bg-error-50/95 dark:bg-error-900/30 text-error-800 dark:text-error-200"
            : "border-neutral-200 dark:border-neutral-700 bg-white/95 dark:bg-neutral-900/70 text-neutral-900 dark:text-white";
    return (_jsx("div", { className: cn("pointer-events-auto select-none rounded-xl border shadow-lg backdrop-blur px-4 py-3", variantClasses), style: styles, onPointerDown: onPointerDown, onPointerMove: onPointerMove, onPointerUp: onPointerUp, onPointerCancel: onPointerUp, role: "status", "aria-live": "polite", children: _jsxs("div", { className: "flex items-start gap-3", children: [_jsx("div", { className: "text-sm font-medium flex-1", children: toast.message }), _jsx("button", { type: "button", onClick: onClose, className: "shrink-0 -mt-1 -mr-1 p-1 rounded-md text-neutral-600 dark:text-neutral-300 hover:bg-black/5 dark:hover:bg-white/10", "aria-label": "Close notification", children: _jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("path", { d: "M18 6 6 18" }), _jsx("path", { d: "M6 6l12 12" })] }) })] }) }));
}
