import type { FC, ComponentType } from 'react';
import React, { useState } from 'react';
import { useNavigation, useRoute } from '@react-navigation/native';
import * as sentryService from '../services/sentry.service';
import ErrorScreen from '../screens/ErrorScreen';
import ErrorBoundary from '../components/Errors/ErrorBoundary';

const withErrorBoundary = <ComponentProps extends object>(
    Component: ComponentType<ComponentProps>
): FC<ComponentProps> => {
    const WithErrorBoundary: FC<ComponentProps> & { router?: any } = ({
        ...props
    }: ComponentProps) => {
        const navigation = useNavigation();
        const route = useRoute();

        const [screenError, setScreenError] = useState<any>();

        const handleScreenError = (error: any): void => {
            setScreenError(error);
            sentryService.logException(
                `Screen Level Error Boundary for screen ${route?.name} 
                invoked with an error ${error}`
            );
        };

        if (screenError) {
            return (
                <ErrorScreen
                    title="error.screen.title"
                    message="error.screen.message"
                    buttonTitle="error.goBack"
                    reset={navigation.goBack}
                />
            );
        }

        return (
            <ErrorBoundary onError={handleScreenError}>
                <Component {...props} />
            </ErrorBoundary>
        );
    };

    WithErrorBoundary.router = (Component as any).router;
    WithErrorBoundary.displayName = `WithErrorBoundary(${
        Component.displayName || Component.name || 'Component'
    })`;

    return WithErrorBoundary;
};

export default withErrorBoundary;
