"use client";

import { MutationCache, QueryCache, QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { useCallback, useEffect, useRef, useState } from "react";
import { useRouter } from "next/navigation";
import { toast } from "@heroui/react";
import { signOut, useSession } from "@/lib/auth-client";
import { APIError } from "@/lib/api";

/** 监听 better-auth 会话变为 null（服务端过期/异地登出等场景）*/
function SessionMonitor({ onExpired }: { onExpired: () => void }) {
  const { data: session, isPending } = useSession();
  const wasLoggedIn = useRef(false);

  useEffect(() => {
    if (isPending) return;
    if (session) {
      wasLoggedIn.current = true;
    } else if (wasLoggedIn.current) {
      wasLoggedIn.current = false;
      onExpired();
    }
  }, [session, isPending, onExpired]);

  return null;
}

export function ReactQueryProvider({ children }: { children: React.ReactNode }) {
  const router = useRouter();
  const isHandling = useRef(false);

  const handleExpired = useCallback(async () => {
    if (isHandling.current) return;
    isHandling.current = true;
    try {
      await signOut({ fetchOptions: { credentials: "include" } });
    } catch {
      // ignore sign-out errors
    }
    toast.warning("登录已过期，请重新登录");
    router.push("/login");
  }, [router]);

  // Stable ref so the QueryClient (created once) always calls the latest handler
  const handleExpiredRef = useRef(handleExpired);
  handleExpiredRef.current = handleExpired;

  const [queryClient] = useState(
    () =>
      new QueryClient({
        queryCache: new QueryCache({
          onError: (error) => {
            if (error instanceof APIError && error.status === 401) {
              handleExpiredRef.current();
            }
          },
        }),
        mutationCache: new MutationCache({
          onError: (error) => {
            if (error instanceof APIError && error.status === 401) {
              handleExpiredRef.current();
            }
          },
        }),
        defaultOptions: {
          queries: {
            staleTime: 10_000,
          },
        },
      }),
  );

  return (
    <QueryClientProvider client={queryClient}>
      <SessionMonitor onExpired={handleExpired} />
      {children}
    </QueryClientProvider>
  );
}
