'use client';

import { QueryClient } from '@tanstack/react-query';
import { ApiError } from './api-client';

/**
 * 401/403 errors are expected (logged-out users hit protected endpoints during
 * initial render or token expiry) and should stay in the query's error state —
 * components can show a "please sign in" placeholder. Do NOT propagate them to
 * the error boundary, which would unmount the whole dashboard and spam the
 * console.
 *
 * 404 means the backend simply has no data for the query — also non-fatal, let
 * the component render an empty state.
 *
 * Anything else (network errors, 5xx, validation) is a real problem and should
 * bubble up to the error boundary.
 */
function shouldBubbleToBoundary(error: unknown): boolean {
  if (error instanceof ApiError) {
    return error.status !== 401 && error.status !== 403 && error.status !== 404;
  }
  return true;
}

/**
 * Retry only when it's likely transient (network / 5xx). Don't retry 4xx auth
 * or validation failures — they won't fix themselves.
 */
function shouldRetry(failureCount: number, error: unknown): boolean {
  if (error instanceof ApiError) {
    if (error.status >= 400 && error.status < 500) return false;
  }
  return failureCount < 3;
}

function makeQueryClient() {
  return new QueryClient({
    defaultOptions: {
      queries: {
        staleTime: 60 * 1000,
        gcTime: 5 * 60 * 1000,
        retry: shouldRetry,
        retryDelay: (attemptIndex) => Math.min(1000 * 2 ** attemptIndex, 30000),
        refetchOnWindowFocus: false,
        throwOnError: shouldBubbleToBoundary,
      },
      mutations: {
        retry: 1,
      },
    },
  });
}

let browserQueryClient: QueryClient | undefined;

export function getQueryClient() {
  if (typeof window === 'undefined') {
    return makeQueryClient();
  }
  if (!browserQueryClient) {
    browserQueryClient = makeQueryClient();
  }
  return browserQueryClient;
}
