/* eslint-disable @typescript-eslint/camelcase */
import React, { useEffect } from 'react'
import Router from 'next/router'

import { ThemeProvider } from 'styled-components'
import { ReactQueryCacheProvider, QueryCache } from 'react-query'
import { Hydrate, dehydrate } from 'react-query/hydration'
import { ReactQueryDevtools } from 'react-query-devtools'
import { ToastProvider } from 'react-toast-notifications'
import { Views, Toast } from '@sentecacommerce-theme/clean-theme'
import dynamic from 'next/dynamic'
import { Config } from '@sentecacommerce-theme/clean-theme'
import Cookies from 'js-cookie'

// THIS HAS TO BE MOVED OUT OF HERE ITS TEMP FIX SO WE CAN RELEASE!!!!!
import {
  productsApi,
  LabelsContextProvider,
  ConfigProvider,
  UIProvider,
  GlobalLabelsProvider,
  CookieProvider,
  SentecaProvider,
  GoogleOneTap,
  GlobalSEO,
  prefetchPredicate,
  prefetchCategories,
  prefetchCmsContent,
  prefetchCmsContentList,
  prefetchListing,
  protectRoute,
  enablePreview,
  AggregationTypeEnum,
  ComponentTypeEnum,
  prefetchMenu,
  InjectedContentProvider,
  prefetchCookies,
  RelevaProvider,
  PixelScript,
  pixelChangeRoute,
} from '@sentecacommerce-theme/lib'

import { GlobalStyles } from '@sentecacommerce-theme/clean-theme'

//https://react-query.tanstack.com/docs/guides/ssr
export const queryCache = new QueryCache()

const injectedContentComponents = {
  Banner: dynamic(() => import('@sentecacommerce-theme/clean-theme').then((mod) => mod.Banner)),
  BannerCarousel: dynamic(() =>
    import('@sentecacommerce-theme/clean-theme').then((mod) => mod.BannerCarousel)
  ),
  Caption: dynamic(() => import('@sentecacommerce-theme/clean-theme').then((mod) => mod.Caption)),
  Carousel: dynamic(() =>
    import('@sentecacommerce-theme/clean-theme').then((mod) => mod.Carousel)
  ),
  Element: dynamic(() => import('@sentecacommerce-theme/clean-theme').then((mod) => mod.Element)),
  Header: dynamic(() => import('@sentecacommerce-theme/clean-theme').then((mod) => mod.Header)),
  Html: dynamic(() => import('@sentecacommerce-theme/clean-theme').then((mod) => mod.Html)),
  ListingBanner: dynamic(() =>
    import('@sentecacommerce-theme/clean-theme').then((mod) => mod.ListingBanner)
  ),
  MerchMenu: dynamic(() =>
    import('@sentecacommerce-theme/clean-theme').then((mod) => mod.MerchMenu)
  ),
  SlidingCTA: dynamic(() =>
    import('@sentecacommerce-theme/clean-theme').then((mod) => mod.SlidingCTA)
  ),
  SubscribeToNewsletter: dynamic(() =>
    import('@sentecacommerce-theme/clean-theme').then((mod) => mod.SubscribeToNewsletter)
  ),
}

const PixelConfig = () => {
  return `const token = document.cookie
  .split('; ')
  .map(el => el.split('='))
  .find(el => el[0] === 'token' || el[0] === 'anonymousToken')[1];
  const cfg = {
  source: 'district-web-client',
  appName: 'District Shoes',
  debug: false,
  initialUserId: JSON.parse(atob(token.split('.')[1])).sub, //get cookies
  };
  window.pixel_cfg = cfg;
  `
}
function App({ Component, pageProps }) {
  useEffect(() => {
    // Init Pixel
    if (
      typeof window !== 'undefined' &&
      window.document &&
      window.document.createElement
    ) {
      const initPixel = (retryCount = 0) => {
        if (Cookies.get('token') || Cookies.get('anonymousToken')) {
          const pixelConfigScript = document.getElementById('pixelConfig')

          if (pixelConfigScript === null) {
            const pixelConfig = document.createElement('script')
            pixelConfig.type = 'application/javascript'
            pixelConfig.id = 'pixelConfig'
            pixelConfig.text = PixelConfig()

            document.head.appendChild(pixelConfig)

            const pixelMain = document.createElement('script')
            pixelMain.type = 'application/javascript'
            pixelMain.id = 'pixelMain'
            pixelMain.text = PixelScript()

            document.head.appendChild(pixelMain)
          }
        } else if (retryCount < 10) {
          setTimeout(() => initPixel(retryCount + 1), 300)
        }
      }
      initPixel()
    }

    // Scroll top on route change
    Router.events.on('routeChangeComplete', () => {
      window.scrollTo(0, 0)

      pixelChangeRoute()
    })
  }, [])

  return (
    <ReactQueryCacheProvider queryCache={queryCache}>
      <SentecaProvider defaultConfig={{ basePath: '/api' }}>
        <Hydrate state={pageProps.dehydratedState}>
          <ConfigProvider config={Config}>
            <GlobalSEO />
            <GoogleOneTap />
            <ReactQueryDevtools initialIsOpen />
            <GlobalStyles />
            <ThemeProvider theme={Config.theme}>
              <LabelsContextProvider>
                <GlobalLabelsProvider labels={Config.globalLabels}>
                  <ToastProvider
                    components={{
                      Toast,
                    }}
                  >
                    <CookieProvider>
                      <RelevaProvider>
                        <UIProvider displayNavbar={true} displaySidebar={true}>
                          <Views />
                          <InjectedContentProvider
                            components={injectedContentComponents}
                            fullWidthContentClass="InjectedContent--full-width"
                            containerClass="InjectedContent--container"
                          >
                            <Component {...pageProps} />
                          </InjectedContentProvider>
                        </UIProvider>
                      </RelevaProvider>
                    </CookieProvider>
                  </ToastProvider>
                </GlobalLabelsProvider>
              </LabelsContextProvider>
            </ThemeProvider>
          </ConfigProvider>
        </Hydrate>
      </SentecaProvider>
    </ReactQueryCacheProvider>
  )
}

const listingSet = new Set([
  '/[slug]/c',
  '/[slug]/b',
  '/[slug]/v',
  '/[slug]/ct',
  '/[slug]/[cat]/c',
  '/[slug]/[cat]/b',
])

App.getInitialProps = async (context) => {
  const pageProps = {}
  const { router, ctx } = context

  if (typeof window === 'undefined') {
    enablePreview(router, ctx)

    await prefetchMenu(queryCache)

    await prefetchCookies(queryCache, Config.interfaceKey)

    if (router.route === '/[slug]/p') {
      await productsApi.usePrefetchProduct(queryCache, router.query.slug, {
        expand: 'brands',
      })
      const dehydratedState = dehydrate(queryCache)
      pageProps.dehydratedState = dehydratedState
    }

    const listing = listingSet.has(router.route)

    if (listing) {
      const predicate = await prefetchPredicate(queryCache, router)

      if (!predicate || predicate.statusCode || predicate.stack) {
        ctx.res.statusCode = 404
        pageProps.errorCode = 404

        return { pageProps }
      }

      await prefetchListing({
        queryCache,
        router,
        predicate,
        defaultLimit: Config.listing.limit,
        defaultSortKey: Config.listing.defaultSortKey,
      })

      await prefetchCategories(queryCache, router, predicate, [
        {
          label: 'Categories',
          aggregationType: AggregationTypeEnum.Terms,
          aggregationDefinition: 'categories',
          filterDefinition: 'category',
          component: ComponentTypeEnum.TextWithLink,
          order: 0,
        },
      ])
    }

    if (router.route === '/search') {
      await prefetchListing({
        queryCache,
        router,
        defaultLimit: Config.listing.limit,
        defaultSortKey: Config.listing.defaultSortKey,
      })
    }

    if (router.route === '/blog') {
      await prefetchCmsContentList(
        queryCache,
        { type: Config.blogConfig.key, limit: Config.blogConfig.limit },
        +(router?.query?.page || '1')
      )
      const dehydratedState = dehydrate(queryCache)
      pageProps.dehydratedState = dehydratedState
    }

    if (router.route === '/blog/[slug]') {
      const isContentFound = await prefetchCmsContent({
        queryCache,
        key: router.query.slug,
      })

      if (!isContentFound) {
        ctx.res.statusCode = 404
      }

      const dehydratedState = dehydrate(queryCache)
      pageProps.dehydratedState = dehydratedState
    }

    const dehydratedState = dehydrate(queryCache)
    pageProps.dehydratedState = dehydratedState
  }

  // If user is not logged in redirect to /
  protectRoute(ctx, 'profile', '/')
  return { pageProps }
}

export default App
