'use client'

import { useState } from 'react'
import { SessionProvider } from 'next-auth/react'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { httpBatchLink } from '@trpc/client'
import superjson from 'superjson'
import { trpc } from '@/lib/trpc/client'

function makeQueryClient() {
  return new QueryClient({
    defaultOptions: {
      queries: {
        staleTime: 5 * 60 * 1000, // 5 minutes
        refetchOnWindowFocus: false,
        retry: (failureCount, error) => {
          // Retry up to 3 times on server errors (503 cold-start, etc.)
          if (failureCount >= 3) return false
          const msg = (error as Error)?.message ?? ''
          // Retry on JSON parse errors (HTML 503 from nginx) and server errors
          if (msg.includes('is not valid JSON') || msg.includes('Unexpected token')) return true
          if (msg.includes('500') || msg.includes('502') || msg.includes('503')) return true
          return failureCount < 2
        },
        retryDelay: (attemptIndex) => Math.min(2000 * (attemptIndex + 1), 8000),
      },
    },
  })
}

let browserQueryClient: QueryClient | undefined = undefined

function getQueryClient() {
  if (typeof window === 'undefined') {
    // Server: always make a new query client
    return makeQueryClient()
  } else {
    // Browser: make a new query client if we don't already have one
    if (!browserQueryClient) browserQueryClient = makeQueryClient()
    return browserQueryClient
  }
}

function getBaseUrl() {
  if (typeof window !== 'undefined') return ''
  if (process.env.VERCEL_URL) return `https://${process.env.VERCEL_URL}`
  return `http://localhost:${process.env.PORT ?? 3000}`
}

export function Providers({ children }: { children: React.ReactNode }) {
  const queryClient = getQueryClient()

  const [trpcClient] = useState(() =>
    trpc.createClient({
      links: [
        httpBatchLink({
          url: `${getBaseUrl()}/api/trpc`,
          transformer: superjson,
          async fetch(url, options) {
            const res = await globalThis.fetch(url, options)
            // Detect nginx 503 / HTML error pages before tRPC tries to JSON.parse
            if (!res.ok) {
              const ct = res.headers.get('content-type') ?? ''
              if (ct.includes('text/html') || !ct.includes('json')) {
                throw new Error(
                  res.status >= 500
                    ? 'Server is starting up — please wait a moment and try again.'
                    : `Server error (${res.status})`
                )
              }
            }
            return res
          },
        }),
      ],
    })
  )

  return (
    <SessionProvider>
      <trpc.Provider client={trpcClient} queryClient={queryClient}>
        <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
      </trpc.Provider>
    </SessionProvider>
  )
}
