import { createContext, useCallback, useEffect, useMemo, useRef, useState } from "react";

const MAX_ACTION_TOASTS = 5;
const DEFAULT_DURATION_MS = {
  success: 3500,
  info: 3500,
  error: 5000,
};

export const ActionToastContext = createContext(null);

function createToastId() {
  if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
    return crypto.randomUUID();
  }
  return `toast_${Date.now()}_${Math.random().toString(16).slice(2)}`;
}

export function ActionToastProvider({ children }) {
  const [toasts, setToasts] = useState([]);
  const timerByIdRef = useRef(new Map());

  const dismiss = useCallback((id) => {
    const timer = timerByIdRef.current.get(id);
    if (timer) {
      clearTimeout(timer);
      timerByIdRef.current.delete(id);
    }

    setToasts((prev) => prev.filter((toast) => toast.id !== id));
  }, []);

  const pushToast = useCallback(
    (variant, title, message, options = {}) => {
      const id = createToastId();
      const durationMs = options.durationMs ?? DEFAULT_DURATION_MS[variant] ?? 3500;
      const nextToast = {
        id,
        variant,
        title: String(title || ""),
        message: String(message || ""),
        createdAt: Date.now(),
        durationMs,
      };

      setToasts((prev) => {
        const next = [...prev, nextToast];
        if (next.length > MAX_ACTION_TOASTS) {
          const oldest = next.shift();
          if (oldest) {
            const timer = timerByIdRef.current.get(oldest.id);
            if (timer) {
              clearTimeout(timer);
              timerByIdRef.current.delete(oldest.id);
            }
          }
        }
        return next;
      });

      if (durationMs > 0) {
        const timer = setTimeout(() => dismiss(id), durationMs);
        timerByIdRef.current.set(id, timer);
      }

      return id;
    },
    [dismiss]
  );

  const success = useCallback(
    (title, message, options) => pushToast("success", title, message, options),
    [pushToast]
  );
  const error = useCallback(
    (title, message, options) => pushToast("error", title, message, options),
    [pushToast]
  );
  const info = useCallback(
    (title, message, options) => pushToast("info", title, message, options),
    [pushToast]
  );

  useEffect(() => {
    return () => {
      for (const timer of timerByIdRef.current.values()) {
        clearTimeout(timer);
      }
      timerByIdRef.current.clear();
    };
  }, []);

  const value = useMemo(
    () => ({
      toasts,
      success,
      error,
      info,
      dismiss,
    }),
    [toasts, success, error, info, dismiss]
  );

  return <ActionToastContext.Provider value={value}>{children}</ActionToastContext.Provider>;
}
