"use client";

import { useState } from "react";

import {
  QueryClient,
  QueryClientProvider,
  type QueryClientConfig,
} from "@tanstack/react-query";
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";

import { isApiError } from "@/lib/apiError";

// One QueryClient for the app, with global defaults configured once (Rule 40).
//
// Retry policy is idempotency- and status-aware: queries (GETs) retry only on
// network/5xx and never on 4xx (a 404 or 422 won't fix itself); mutations never
// auto-retry (Rule 29.1 — non-idempotent writes must not replay). queryFns reject
// with a normalised `ApiError`, so we branch on `err.kind`.

const STALE_TIME_MS = 30_000; // 30s — avoids refetch storms for stable-ish data
const GC_TIME_MS = 5 * 60_000; // 5min
const MAX_QUERY_RETRIES = 2;

const config: QueryClientConfig = {
  defaultOptions: {
    queries: {
      staleTime: STALE_TIME_MS,
      gcTime: GC_TIME_MS,
      refetchOnWindowFocus: false,
      retry: (failureCount, error) => {
        if (failureCount >= MAX_QUERY_RETRIES) return false;
        if (isApiError(error)) return error.kind === "network" || error.kind === "server";
        return false;
      },
    },
    mutations: {
      retry: false,
    },
  },
};

export function QueryProvider({ children }: { children: React.ReactNode }) {
  // useState ensures one client instance per app load, stable across re-renders.
  const [queryClient] = useState(() => new QueryClient(config));

  return (
    <QueryClientProvider client={queryClient}>
      {children}
      {process.env.NODE_ENV !== "production" && (
        <ReactQueryDevtools initialIsOpen={false} buttonPosition="bottom-left" />
      )}
    </QueryClientProvider>
  );
}
