// dependency: @react-native-firebase
// @ts-ignore
globalThis.RNFB_SILENCE_MODULAR_DEPRECATION_WARNINGS = true;
// dependency
// @ts-nocheck
import type { ApolloClient, NormalizedCacheObject } from '@apollo/client';
import { ApolloProvider } from '@apollo/client';
import React, { useEffect, useState } from 'react';
import { Provider } from 'react-redux';

import { StyleSheet, UIManager } from 'react-native';
import BootSplash from 'react-native-bootsplash';
import type { Store } from 'redux';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
import { createApolloClient } from './src/apollo/apollo-client';
import { createApolloCache } from './src/apollo/cache';
import { restoreReactiveVars } from './src/apollo/reactive-vars';
import { BrandingProvider } from './src/branding';
import ErrorBoundary from './src/components/Errors/ErrorBoundary';
import InstallGooglePlayServicesComponent from './src/components/InstallGooglePlayServices';
import BackgroundRefetchTimeoutHandler from './src/components/BackgroundRefetchTimeoutHandler';
import NetworkStateHandler from './src/components/NetworkStateHandler';
import SplashScreenLoader from './src/screens/SplashScreen/SplashScreenLoader';
import { AUTH0_SDK_CONFIG, findSegmentWriteKey } from './src/config';
import { isAndroid } from './src/constants/device';
import RootNavigator from './src/navigation/RootNavigator';
import createReduxStore from './src/redux';
import ErrorScreen from './src/screens/ErrorScreen';
import * as analyticsService from './src/services/analytics.service';
import * as otaUpdateService from './src/services/otaUpdate/otaUpdate.service';
import * as performanceAnalyticsService from './src/services/performanceAnalytics/performanceAnalytics.service';
import { Traces } from './src/services/performanceAnalytics/types';
import * as pushNotificationService from './src/services/pushNotification/pushNotification.service';
import * as sentryService from './src/services/sentry.service';
import { enableXHRDebugging, isDev } from './src/utils/dev';
import { asError } from './src/utils/error-util';
import { BottomSheetModalProvider } from '@gorhom/bottom-sheet';
import { Auth0Provider } from 'react-native-auth0';
import { DatadogWrapper } from './src/components/Datadog/DatadogWrapper';
import { isDebug } from './src/utils/debug';
import * as exitAppService from './src/services/exitApp.service.ts';
import { ChristmasThemeProvider } from './src/hooks/useChristmasTheme';
import { MOBILE_REFETCH_QUERIES_ON_BACKGROUND } from './src/constants/features';
import useHasFeature from './src/hooks/auth/useHasFeature';

sentryService.initialize();
pushNotificationService.initBeforeApp();

interface AppServices {
    reduxStore: Store;
    apolloClient: ApolloClient<NormalizedCacheObject>;
}

export const bootstrap = (global: typeof globalThis) => {
    if (isDev()) {
        enableXHRDebugging(global);
    }
};

bootstrap(global || {});

if (isAndroid() && UIManager.setLayoutAnimationEnabledExperimental) {
    UIManager.setLayoutAnimationEnabledExperimental(true);
}

const App = () => {
    const [appError, setAppError] = useState<Error>();
    const [appServices, setAppServices] = useState<AppServices | null>(null);
    const hasBackgroundRefetchTimeout = useHasFeature(
        MOBILE_REFETCH_QUERIES_ON_BACKGROUND
    );

    const handleAppError = (error: Error) => {
        setAppError(error);
        sentryService.logException(
            `Global Level Error Boundary invoked with an error ${error}`
        );
    };

    useEffect(() => {
        try {
            otaUpdateService.denyRestart();
            performanceAnalyticsService.startTrace(Traces.app);
            requestAnimationFrame(() => {
                BootSplash.hide({ fade: true }).catch(error =>
                    sentryService.logException(asError(error))
                );
            });
            analyticsService.initialize(findSegmentWriteKey());
            otaUpdateService.trackRollback().catch(sentryService.logException);
        } catch (error) {
            setAppError(asError(error));
        }
        return () => {
            if (!isDebug() && isAndroid()) {
                exitAppService.exit();
            }
        };
    }, []);

    useEffect(() => {
        (async () => {
            try {
                const { store: reduxStore, storeLoaded } = createReduxStore({
                    onError: handleAppError
                });

                await storeLoaded;

                const apolloCache = await createApolloCache();
                const apolloClient = createApolloClient(apolloCache);
                await restoreReactiveVars();

                setAppServices({ reduxStore, apolloClient });
            } catch (error) {
                setAppError(asError(error));
            }
        })();
    }, []);

    if (appError) {
        return (
            <BrandingProvider>
                <ErrorScreen isAppLevel />
            </BrandingProvider>
        );
    }

    if (appServices === null) {
        return (
            <BrandingProvider>
                <SplashScreenLoader />
            </BrandingProvider>
        );
    }

    const { reduxStore, apolloClient } = appServices;

    return (
        <DatadogWrapper>
            <Auth0Provider
                domain={AUTH0_SDK_CONFIG.domain}
                clientId={AUTH0_SDK_CONFIG.clientId}
            >
                <GestureHandlerRootView style={styles.gestureContainer}>
                    <BrandingProvider>
                        <ChristmasThemeProvider>
                            <ErrorBoundary onError={handleAppError}>
                                <InstallGooglePlayServicesComponent>
                                    <Provider store={reduxStore}>
                                        <ApolloProvider client={apolloClient}>
                                            <BottomSheetModalProvider>
                                                <NetworkStateHandler />
                                                <RootNavigator />
                                                {hasBackgroundRefetchTimeout ? (
                                                    <BackgroundRefetchTimeoutHandler />
                                                ) : null}
                                            </BottomSheetModalProvider>
                                        </ApolloProvider>
                                    </Provider>
                                </InstallGooglePlayServicesComponent>
                            </ErrorBoundary>
                        </ChristmasThemeProvider>
                    </BrandingProvider>
                </GestureHandlerRootView>
            </Auth0Provider>
        </DatadogWrapper>
    );
};

const styles = StyleSheet.create({
    gestureContainer: { flex: 1 }
});

export default otaUpdateService.decorate(sentryService.decorate(App));
