"use client";

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

type ToastKind = "info" | "error" | "success";

interface ToastItem {
  id: number;
  message: string;
  kind: ToastKind;
}

type ShowToast = (message: string, kind?: ToastKind) => void;

const ToastContext = createContext<ShowToast | null>(null);

const TOAST_TTL_MS = 4000;

export function ToastProvider({ children }: { children: ReactNode }) {
  const [items, setItems] = useState<ToastItem[]>([]);
  // 单调计数器作 id（不再用 Date.now()+random，避免极小概率碰撞且稳定可测）。
  const nextIdRef = useRef(0);
  // 在途定时器集合：卸载时统一清理，避免 setState-after-unmount 泄漏。
  const timersRef = useRef<Set<ReturnType<typeof setTimeout>>>(new Set());

  const show = useCallback<ShowToast>((message, kind = "info") => {
    const id = nextIdRef.current++;
    setItems((prev) => [...prev, { id, message, kind }]);
    const timer = setTimeout(() => {
      timersRef.current.delete(timer);
      setItems((prev) => prev.filter((t) => t.id !== id));
    }, TOAST_TTL_MS);
    timersRef.current.add(timer);
  }, []);

  // 卸载清理所有在途定时器。
  useEffect(() => {
    const timers = timersRef.current;
    return () => {
      timers.forEach((t) => clearTimeout(t));
      timers.clear();
    };
  }, []);

  const value = useMemo(() => show, [show]);

  return (
    <ToastContext.Provider value={value}>
      {children}
      <div
        className="pointer-events-none fixed bottom-6 right-6 z-50 flex flex-col gap-2"
        aria-live="polite"
        role="status"
      >
        {items.map((t) => (
          <div
            key={t.id}
            className={`pointer-events-auto rounded border px-4 py-2 text-sm shadow-paper ${
              t.kind === "error"
                ? "border-conflict bg-panel text-conflict"
                : t.kind === "success"
                  ? "border-pass bg-panel text-pass"
                  : "border-line bg-panel text-ink"
            }`}
          >
            {t.message}
          </div>
        ))}
      </div>
    </ToastContext.Provider>
  );
}

export function useToast(): ShowToast {
  const ctx = useContext(ToastContext);
  if (!ctx) {
    // 容错：未挂 Provider 时退化为 no-op（不应在生产路径发生）。
    return () => undefined;
  }
  return ctx;
}
