import { MutationCache, QueryCache, QueryClient } from '@tanstack/react-query';
import { ApiError } from './api-client';
import { notifyError } from './feedback';

function describeError(error: unknown): string {
  if (error instanceof ApiError) {
    return error.problem.detail ?? error.problem.title ?? 'Erro no servidor';
  }
  if (error instanceof Error && error.message) return error.message;
  return 'Erro inesperado';
}

/**
 * QueryClient canônico do SAR.
 * Defaults conservadores: refetch on focus desabilitado (Visual DNA: "sereno"),
 * stale-while-revalidate para tempo real bater no Socket.IO, não em polling.
 * Erros nunca são silenciosos: falha de query/mutation sem tratamento local
 * vira toast — Sandra/Daniel jamais devem "achar que salvou".
 */
export const queryClient = new QueryClient({
  queryCache: new QueryCache({
    onError: (error) => {
      notifyError(`Falha ao carregar dados: ${describeError(error)}`, 'query-error');
    },
  }),
  mutationCache: new MutationCache({
    onError: (error, _variables, _context, mutation) => {
      if (mutation.options.onError) return; // a tela já dá feedback próprio
      notifyError(describeError(error), 'mutation-error');
    },
  }),
  defaultOptions: {
    queries: {
      staleTime: 30_000, // 30s — Socket.IO atualiza antes na maioria dos casos
      gcTime: 5 * 60_000, // 5min em cache antes de garbage collect
      refetchOnWindowFocus: false, // evita "refresh fantasma" — Sandra/Daniel se distraem
      refetchOnReconnect: true,
      retry: (failureCount, error) => {
        // 4xx não retry; 5xx até 2 retries
        const status = (error as { status?: number })?.status;
        if (status && status >= 400 && status < 500) return false;
        return failureCount < 2;
      },
      retryDelay: (attempt) => Math.min(1000 * 2 ** attempt, 30_000),
    },
    mutations: {
      retry: false, // mutations não retry automático — Idempotency-Key no servidor cuida disso
    },
  },
});
