import { Layout } from '@/components/ui'
import { AuthProvider, EnvProvider, FooterProvider } from '@/contexts'
import {
  Auth,
  Bi,
  Checks,
  EDoc,
  Kpi,
  LKScreen,
  NotificationsPage,
  Policy,
  Profile,
  SignUp,
  TechCoverage,
} from '@/pages'
import { YMaps } from '@pbe/react-yandex-maps'
import {
  MutationCache,
  QueryCache,
  QueryClient,
  QueryClientProvider,
} from '@tanstack/react-query'
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
import React from 'react'
import ReactDOM from 'react-dom/client'
import toast, { Toaster } from 'react-hot-toast'
import { Navigate, RouterProvider, createBrowserRouter } from 'react-router-dom'
import { registerSW } from 'virtual:pwa-register'
import { ZodError } from 'zod'
import './main.css'
import { isAbortError, isIphone } from './utils'

// Инициализация PWA
if ('serviceWorker' in navigator) {
  const updateSW = registerSW({
    onNeedRefresh() {
      if (confirm('Доступно обновление. Перезагрузить?')) {
        updateSW(true)
      }
    },
    onOfflineReady() {
      console.log('Приложение готово к работе офлайн')
    },
  })
}

const router = createBrowserRouter([
  {
    path: '/auth',
    element: <Auth />,
  },
  {
    path: '/signup',
    element: <SignUp />,
  },
  {
    path: '/lk-screen',
    element: <LKScreen />,
  },
  {
    path: '/policy',
    element: <Policy />,
  },
  {
    path: '/',
    element: <Layout />,
    errorElement: <Navigate to="/tech-coverage" />,
    children: [
      { index: true, element: <Navigate to="/profile" /> },
      {
        path: 'checks',
        element: <Checks />,
      },
      {
        path: 'notifications',
        element: <NotificationsPage />,
      },
      {
        path: 'tech-coverage',
        children: [
          {
            index: true,
            element: <TechCoverage />,
          },
          {
            path: ':houseId',
            element: <TechCoverage />,
          },
        ],
      },
      {
        path: 'e-doc',
        element: <EDoc />,
      },
      {
        path: 'profile',
        element: <Profile />,
      },
      {
        path: 'bi',
        children: [
          { index: true, element: <Bi /> },
          {
            path: 'kpi',
            children: [
              { index: true, element: <Navigate to="/bi" /> },
              {
                path: ':kpiId',
                element: <Kpi />,
              },
            ],
          },
        ],
      },
    ],
  },
])

function handleError(error: unknown) {
  if (import.meta.env.DEV) console.error(error)
  if (
    isAbortError(error) ||
    (error instanceof Error && error.name === 'CancelledError')
  )
    return
  if (!(error instanceof Error)) return
  if (error instanceof ZodError || error.message === 'parse-error')
    return toast.error('Произошла внутренняя ошибка сервера')
  if (error.message === 'unauthorized')
    return toast.error('Время сессии истекло, авторизуйтесь повторно', {
      id: error.message,
    })
  if (error.message === 'too-many-requests')
    return toast.error(
      'Слишком много одновременных запросов, подождите 10 секунд и обновите страницу',
      {
        id: error.message,
      }
    )
  if (error.message === 'access forbidden')
    return toast.error('Доступ запрещен', {
      id: error.message,
    })

  if (
    error.message.includes('access forbidden') &&
    error.message.split(' ').length === 3
  )
    return

  toast.error(error.message, {
    id: error.message,
  })
}

const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      refetchOnWindowFocus: false,
      staleTime: 1000 * 60, // 1 minute
    },
  },
  queryCache: new QueryCache({
    onError: handleError,
  }),
  mutationCache: new MutationCache({
    onError: (error, _variables, _onMutateResult, mutation) => {
      if (mutation.meta?.suppressGlobalErrorToast) return
      handleError(error)
    },
  }),
})

const isIos = isIphone()

ReactDOM.createRoot(document.querySelector('#react') as HTMLElement).render(
  <React.StrictMode>
    <QueryClientProvider client={queryClient}>
      <EnvProvider
        env={{
          url:
            import.meta.env.MODE === 'test'
              ? import.meta.env.VITE_API_TEST_URL
              : import.meta.env.MODE === 'production'
                ? import.meta.env.VITE_API_PRODUCTION_URL
                : import.meta.env.VITE_API_DEVELOPMENT_URL,

          mode:
            import.meta.env.MODE === 'test'
              ? 'test'
              : import.meta.env.MODE === 'production'
                ? 'production'
                : import.meta.env.MODE === 'localhost'
                  ? 'localhost'
                  : 'development',
        }}
      >
        <AuthProvider
          isLoggedIn={localStorage.getItem('isLoggedIn') === 'true'}
          onSignIn={() => localStorage.setItem('isLoggedIn', 'true')}
          onSignOut={() => localStorage.removeItem('isLoggedIn')}
        >
          <FooterProvider>
            <YMaps
              query={{
                lang: 'ru_RU',
                apikey: '501e0b93-48e7-4aee-ad6e-576dfe531d72',
              }}
            >
              <RouterProvider router={router} />
              {!isIos && <ReactQueryDevtools />}
              <Toaster
                toastOptions={{
                  className: '',
                  style: {
                    border: '1px solid #999',
                    padding: '16px 16px',
                    marginTop: '48px',
                  },
                }}
              />
            </YMaps>
          </FooterProvider>
        </AuthProvider>
      </EnvProvider>
    </QueryClientProvider>
  </React.StrictMode>
)
