import { LOCATION_CHANGE as LOCATION_CHANGE_SUCCESS } from '@common-stack/remix-router-redux';
import { NavigationContainer, LinkingOptions } from '@react-navigation/native';
import { cloneDeep, merge } from 'lodash-es';
import React, { MutableRefObject, ReactElement, useRef } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { navigationRef } from '@common-stack/client-react';
import { isUserAuthenticated } from '@adminide-stack/user-auth0-client';

interface INavigationContainerComponentProps {
    children: ReactElement[];
    configurableRoutes: Record<string, any>[];
    independent?: boolean;
    linking?: LinkingOptions<any>;
}

interface INavigationContainerRef {
    name: string;
    key: string;
    params?: Readonly<object | undefined>;
}

export const getPath = (routeName: string, configurableRoutes: Record<string, any>[]) => {
    let resultantPath = '';
    configurableRoutes.forEach((item) => {
        if (item.children?.length) {
            const value = getPath(routeName, item.children);
            if (value) {
                resultantPath = value;
            }
        }
        if (item.navigationRouteName === routeName) {
            resultantPath = item.path;
        }
    });
    return resultantPath;
};

export const configurableRoutesWithNavigationRouteName = (
    configurableRoutes: Record<string, any>[],
    parentName: string = '',
) => {
    return configurableRoutes.map((item) => {
        const resultantName = parentName;
        const navigationRouteName = resultantName.length ? `${resultantName}.${item.name}` : item.name;
        item.navigationRouteName = navigationRouteName;
        if (item.children) {
            item.children = configurableRoutesWithNavigationRouteName(item.children, navigationRouteName);
        }
        return item;
    });
};

export const useLocationChange = () => {
    const dispatch = useDispatch();
    const { authenticated } = isUserAuthenticated();
    const [locationChange, setLocationChange] = React.useState<any>(null);
    const platformState = useSelector((state) => (state as any).platform);

    React.useEffect(() => {
        if (locationChange) setLocation(locationChange);
    }, [locationChange]);

    const setLocation = ({ configurableRoutes, previousRoute = null, orgName = null }: any) => {
        const currentRoute: any = navigationRef.isReady() ? navigationRef?.getCurrentRoute() : null;
        const currentRouteName = currentRoute ? currentRoute!?.name : null;
        const configuredRoutes = configurableRoutesWithNavigationRouteName(configurableRoutes);
        const currentPath = currentRouteName ? getPath(currentRouteName as string, configuredRoutes) : null;
        const previousPath = previousRoute ? getPath(previousRoute?.current!.name, configuredRoutes) : null;
        const currentOrgName = authenticated
            ? orgName
                ? orgName
                : currentRoute!.params?.orgName || platformState?.orgName || previousRoute?.current?.params?.orgName
            : null;
        const currParams = {
            ...(currentRoute!.params || {}),
            orgName: currentOrgName,
        };

        navigationRef?.setParams(currParams);

        dispatch({
            type: LOCATION_CHANGE_SUCCESS,
            payload: {
                currentRoute: {
                    path: currentPath,
                    params: currParams,
                },
                previousRoute: {
                    path: previousPath,
                    params: previousRoute?.current?.params ?? { orgName: '' },
                },
            },
        });
    };

    return { setLocationChange };
};

export const NavigationContainerComponent = ({
    children,
    configurableRoutes,
    independent,
    linking,
}: INavigationContainerComponentProps): ReactElement => {
    const routeNameRef = useRef<INavigationContainerRef | undefined>(undefined) as MutableRefObject<
        INavigationContainerRef | undefined
    >;
    const dispatch = useDispatch();
    const platformState = useSelector((state) => (state as any).platform);
    const { setLocationChange } = useLocationChange();
    //const user = useSelector((state: any) => state.user);
    return (
        <NavigationContainer
            ref={navigationRef}
            linking={linking}
            // independent={independent}
            onReady={() => {
                routeNameRef.current = navigationRef.isReady() ? navigationRef?.getCurrentRoute() : null;
                const currentRoute: any = routeNameRef?.current;
                setLocationChange({
                    configurableRoutes,
                    orgName: platformState?.orgName ?? currentRoute?.params?.orgName ?? '',
                });
            }}
            onStateChange={async () => {
                const previousRoute: any = routeNameRef?.current ? cloneDeep(routeNameRef) : null;
                const currentRoute: any = navigationRef.isReady() ? navigationRef?.getCurrentRoute() : null;
                const previousRouteName = previousRoute ? previousRoute?.current!.name : null;
                const currentRouteName = currentRoute ? currentRoute!?.name : null;

                const configuredRoutes = configurableRoutesWithNavigationRouteName(configurableRoutes);
                const currentPath = currentRouteName ? getPath(currentRouteName as string, configuredRoutes) : null;
                const previousPath = previousRoute ? getPath(previousRoute?.current!.name, configuredRoutes) : null;
                const currParams = {
                    ...(currentRoute!.params || {}),
                    orgName: currentRoute!.params?.orgName || platformState?.orgName,
                };
                //if (previousRouteName && currentRouteName && previousRouteName !== currentRouteName) {
                if (previousPath !== currentPath) {
                    routeNameRef.current = currentRoute;

                    setLocationChange({ configurableRoutes, previousRoute });

                    // dispatch({
                    //     type: LOCATION_CHANGE_SUCCESS,
                    //     payload: {
                    //         currentRoute: {
                    //             path: currentPath,
                    //             params: currParams,
                    //         },
                    //         previousRoute: {
                    //             path: previousPath,
                    //             params: previousRoute?.current?.params ?? { orgName: '' },
                    //         },
                    //     },
                    // });
                }
            }}
        >
            {children}
        </NavigationContainer>
    );
};
