import { ScrollToTop } from '@components/ScrollToTop'
import { ErrorBoundary } from '@components/shared'
import { POSTHOG_API_KEY, POSTHOG_HOST } from '@constants'
import { createBeforeSend } from '@fordeer/posthog-error-tracking'
import { FordeerApp } from '@fordeer/ui-components'
import { LoadingPage } from '@layouts/LoadingPage'
import { finishInitialLoading, isAppBridgeModal } from '@layouts/loadingOverlay'
import AppRoutes from '@routes/AppRoutes'
import { AppProvider } from '@shopify/polaris'
import en from '@shopify/polaris/locales/en.json'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { loadAmpliBridge } from '@utils/ampliBridge'
import posthog from 'posthog-js'
import { PostHogProvider } from 'posthog-js/react'
import type React from 'react'
import { StrictMode, Suspense, useEffect, useState } from 'react'
import ReactDOM from 'react-dom/client'
import { BrowserRouter } from 'react-router-dom'
import './styles/global.scss'
const rootEl = document.getElementById('root')
if (!rootEl) throw new Error('Root element not found')

// Before the first render: a page's mount effect can call ampli.* before any
// provider effect runs, and an Ampli that is not loaded drops the event. Events
// raised before the shop context exists are held by the V2 transport instead.
loadAmpliBridge()

const posthogBeforeSend = createBeforeSend({
  appName: FordeerApp.ReelPik,
  environment: import.meta.env.MODE,
})

const posthogBeforeSendCompat = posthogBeforeSend as unknown as NonNullable<
  Parameters<typeof posthog.init>[1]
>['before_send']

if (POSTHOG_API_KEY) {
  posthog.init(POSTHOG_API_KEY, {
    api_host: POSTHOG_HOST,
    autocapture: false,
    capture_pageview: false,
    disable_compression: true,
    // posthog-js 1.379+ silently drops capture() for likely-bot UAs unless opted out
    opt_out_useragent_filter: import.meta.env.DEV,
    // posthog-js 1.379+ defaults to marking localhost as internal/test users
    internal_or_test_user_hostname: import.meta.env.DEV ? null : undefined,
    capture_exceptions: {
      capture_unhandled_errors: true,
      capture_unhandled_rejections: true,
      capture_console_errors: false,
    },
    before_send: posthogBeforeSendCompat,
  })
}

// Configure React Query with sensible defaults
const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      staleTime: 5 * 60 * 1000, // 5 minutes
      retry: (failureCount, error: unknown) => {
        const err = error as { message?: string }
        if (err?.message === 'Unauthorized') return false
        return failureCount < 3
      },
    },
  },
})

const Root = (): React.ReactNode => {
  const [Devtools, setDevtools] = useState<null | React.ComponentType>(null)
  const [isMounted, setIsMounted] = useState(isAppBridgeModal)

  useEffect(() => {
    if (isAppBridgeModal) return

    const timer = setTimeout(() => {
      setIsMounted(true)
      finishInitialLoading()
    }, 500)

    return () => clearTimeout(timer)
  }, [])

  useEffect(() => {
    if (import.meta.env.DEV) {
      import('@tanstack/react-query-devtools')
        .then(mod => setDevtools(() => mod.ReactQueryDevtools))
        .catch(err => {
          console.error('Could not load React Query Devtools', err)
        })
    }
  }, [])
  return (
    <StrictMode>
      <ErrorBoundary>
        <PostHogProvider client={posthog}>
          <QueryClientProvider client={queryClient}>
            <AppProvider i18n={en}>
              <BrowserRouter>
                <div
                  style={{
                    opacity: isMounted ? 1 : 0,
                    transition: 'opacity 0.5s ease-in-out',
                  }}
                >
                  <ScrollToTop />
                  <Suspense fallback={<LoadingPage />}>
                    <AppRoutes />
                  </Suspense>
                </div>
              </BrowserRouter>
            </AppProvider>
            {Devtools && <Devtools />}
          </QueryClientProvider>
        </PostHogProvider>
      </ErrorBoundary>
    </StrictMode>
  )
}

ReactDOM.createRoot(rootEl).render(<Root />)
