import React from 'react';
import SmartBanner from 'react-smartbanner';
import { injectStyle } from 'react-toastify/dist/inject-style';
import { ApolloClient, ApolloProvider } from '@apollo/client';
import { init } from '@sentry/browser';
import AppLayoutBeta from 'beta/components/layouts/AppLayout';
import initializeStoreBeta from 'beta/store';
import AppLayout from 'components/app-layout/AppLayout';
import { Provider } from 'mobx-react';
import NextApp, { AppContext as NextAppContext, AppProps as NextAppProps } from 'next/app';
import getConfig from 'next/config';
import { ParsedUrlQuery } from 'querystring';
import { Provider as ReakitProvider } from 'reakit/Provider';
import initializeStore from 'store';
import { IContext } from 'typings/context';
import { appWithTranslation } from 'utils/i18n';
import { withApollo } from 'utils/withApollo';

import 'isomorphic-fetch';
import 'styles/reportHTML-custom.css';
import 'styles/smartbanner.css';
import 'styles/base.scss';
import 'styles/fonts.css';
import 'styles/forceWidth.scss';
import '@nova-hf/ui/umd/styles.css';

const { publicRuntimeConfig } = getConfig();

// Initialize sentry
init({
  dsn: publicRuntimeConfig.SENTRY_DSN,
  environment: publicRuntimeConfig.NODE_ENV,
});

type PortalAppProps = {
  apolloClient: ApolloClient<object>;
  initialState: object;
  initialStateBeta: object;
  query: ParsedUrlQuery;
};

type AppProps = NextAppProps & PortalAppProps;

interface AppContext extends NextAppContext {
  ctx: IContext;
}

const App = (props: AppProps) => {
  const isServer = typeof window === 'undefined';
  const { Component, pageProps, initialState, initialStateBeta, apolloClient, query } = props;
  const store = isServer ? initialState : initializeStore(props, query, apolloClient);
  const betaStore = isServer ? initialStateBeta : initializeStoreBeta(props, query);
  const toastStyles = isServer ? undefined : injectStyle();
  const isBeta = pageProps?.pathname?.includes('beta');
  toastStyles;
  return (
    <div id="root">
      <SmartBanner
        title={'Nova appið'}
        price={{ ios: 'VERTU MEÐ APP Á HREINU!', android: 'VERTU MEÐ APP Á HREINU!' }}
        storeText={{ ios: '', android: '' }}
      />
      <ReakitProvider>
        <ApolloProvider client={apolloClient}>
          <Provider {...(isBeta ? betaStore : store)}>
            {isBeta ? (
              <AppLayoutBeta>
                <Component {...pageProps} />
              </AppLayoutBeta>
            ) : (
              <AppLayout>
                <Component {...pageProps} />
              </AppLayout>
            )}
          </Provider>
        </ApolloProvider>
      </ReakitProvider>
    </div>
  );
};

App.getInitialProps = async (appContext: AppContext) => {
  const isServer = typeof window === 'undefined';
  const query = appContext.ctx.query;

  const store = initializeStore(
    {},
    query,
    undefined,
    isServer ? appContext.ctx.req?.headers.cookie : '',
  );

  const betaStore = initializeStoreBeta(
    {},
    query,
    isServer ? appContext.ctx.req?.headers.cookie : '',
  );

  appContext.ctx.store = store;
  appContext.ctx.betaStore = betaStore;

  let pageProps = {};

  if (appContext.Component.getInitialProps) {
    pageProps = await NextApp.getInitialProps(appContext);
  }

  return {
    ...pageProps,
    query,
    initialState: store,
    initialStateBeta: betaStore,
  };
};

export default withApollo(appWithTranslation(App));
