import React, {
  createContext,
  ReactNode,
  useCallback,
  useMemo,
  useRef,
} from "react";
import {
  useCurrentScreenData,
  useNavigation,
  useRoute,
  isNavBarVisible,
} from "@applicaster/zapp-react-native-utils/reactHooks";
import { useModalNavigationContext } from "@applicaster/zapp-react-native-ui-components/Contexts/ModalNavigationContext";
import { useNestedNavigationContext } from "@applicaster/zapp-react-native-ui-components/Contexts/NestedNavigationContext";
import { create, StoreApi, UseBoundStore } from "zustand";
import { useShallow } from "zustand/react/shallow";
import { Animated } from "react-native";

interface NavBarStoreState {
  visible: boolean;
  title: string;
  summary: string;
  setVisible: (state: boolean) => void;
  setTitle: (title: string) => void;
  setSummary: (subtitle: string) => void;
  height: number;
  scrollState: number;
  contentPosition: string;
  scrollYAnimated: Animated.Value;
}

interface NavBarState {
  visible: boolean;
  title: string;
  summary: string;
  setVisible: (state: boolean) => void;
  setTitle: (title: string) => void;
  setSummary: (subtitle: string) => void;
}

type ScreenContextType = {
  _navBarStore: UseBoundStore<StoreApi<NavBarStoreState>>;
  navBar: NavBarState;
  legacyFormatScreenData: LegacyNavigationScreenData | null;
};

const createStore = () =>
  create<NavBarStoreState>((set) => ({
    title: "",
    summary: "",
    visible: true,
    height: 0,
    scrollState: 0,
    contentPosition: "",
    scrollYAnimated: new Animated.Value(0),
    setTitle(title) {
      set({ title });
    },
    setSummary(summary) {
      set({ summary });
    },
    setVisible(visible) {
      set({ visible });
    },
  }));

export const ScreenContext = createContext<ScreenContextType>({
  _navBarStore: createStore(),
  navBar: {
    visible: true,
    title: "",
    summary: "",
    setVisible: (_state) => void 0,
    setTitle: (_title) => void 0,
    setSummary: (_subtitle) => void 0,
  },
  legacyFormatScreenData: {} as LegacyNavigationScreenData,
});

export function ScreenContextProvider({
  children,
  pathname,
}: {
  children: ReactNode;
  pathname: string;
}) {
  const { data, modalData, videoModalState, canGoBack } = useNavigation();

  // There are 4 route scenarios
  // For regular screens take date from navigator stack.
  // is path is model grab screenData from modal state
  // if path is video modal grab screenData from video state
  // if path is hook modal grab screenData from hook state

  const { screenData: routeScreenData } = useRoute();

  const isModal = useModalNavigationContext();
  const isNested = useNestedNavigationContext();
  const currentScreenScreenData = useCurrentScreenData();

  const screenNavBarStateRef = useRef<null | ReturnType<typeof createStore>>(
    null
  );

  const getScreenNavBarState = useCallback(() => {
    if (screenNavBarStateRef.current !== null) {
      return screenNavBarStateRef.current;
    }

    const navBarState = createStore();
    screenNavBarStateRef.current = navBarState;

    return navBarState;
  }, []);

  const screenNavBarState = getScreenNavBarState()(
    useShallow((state) => ({
      visible: state.visible,
      title: state.title,
      summary: state.summary,
      setTitle: state.setTitle,
      setSummary: state.setSummary,
      setVisible: state.setVisible,
    }))
  );

  const isHook = pathname.includes("hook");

  // screenData is replacement of useScreenContext()
  const screenData = useMemo(() => {
    if (isModal && modalData) return modalData ?? ({} as NavigationScreenData);

    if (isNested && data?.nested) {
      return data?.nested ?? ({} as ScreenData);
    }

    return data ?? ({} as ScreenData);
  }, [isModal, isNested, modalData, data]);

  const isVisible = isNavBarVisible(
    pathname,
    currentScreenScreenData, // what fallback should be if currentScreenData is not available?
    screenNavBarState.visible,
    canGoBack(isHook, pathname),
    videoModalState
  );

  const navBarState = useMemo(
    () => ({
      title: screenNavBarState.title,
      summary: screenNavBarState.summary,
      visible: isVisible,
      setTitle: screenNavBarState.setTitle,
      setSummary: screenNavBarState.setSummary,
      setVisible: screenNavBarState.setVisible,
    }),
    [isVisible, screenNavBarState.title, screenNavBarState.summary]
  );

  return (
    <ScreenContext.Provider
      value={useMemo(
        () => ({
          _navBarStore: getScreenNavBarState(),
          navBar: navBarState,
          legacyFormatScreenData: routeScreenData,
        }),
        [navBarState, screenData, routeScreenData]
      )}
    >
      {children}
    </ScreenContext.Provider>
  );
}

export function withScreenContext(Component: React.ComponentType<any>) {
  return function WithScreenContextWrapper(props) {
    return (
      <ScreenContext.Consumer>
        {useCallback(
          (value) => (
            <Component {...props} screenContext={value} />
          ),
          [Component, props]
        )}
      </ScreenContext.Consumer>
    );
  };
}
