import {
  NavigationContainer,
  NavigationContainerRef,
} from "@react-navigation/native";
import * as Linking from "expo-linking";
import React from "react";
import { ErrorBoundary, FallbackProps } from "react-error-boundary";
import { Clipboard, SafeAreaView, ScrollView } from "react-native";
import { useQuery } from "react-query";
import { useTheme } from "./hooks/useTheme";
import { AuthStack } from "./modules/AuthStack";
import { MainTabStack } from "./modules/MainTabStack";
import { useShowTabs } from "./modules/MainTabStack/useShowTabs";
import { MeResponse } from "./types";
import { FullscreenLoading } from "./ui/FullscreenLoading";
import { MyButton } from "./ui/MyButton";
import { MyHeader } from "./ui/MyHeader";
import { MyText } from "./ui/MyText";
import { ScreenWrapper } from "./ui/ScreenWrapper";
import { ReactQueryErrorResetBoundary } from "react-query";
import { ProfileStack } from "./modules/ProfileStack";
import * as Sentry from "sentry-expo";

const prefix = Linking.makeUrl("/");

interface RoutesProps {}

const linking = {
  prefixes: [prefix],
  config: {
    screens: {
      tokens: "tokens/:accessToken/:refreshToken",
    },
  },
};

function ErrorFallback({ resetErrorBoundary, error }: FallbackProps) {
  return (
    <ScreenWrapper>
      <ScrollView>
        <MyHeader>App Crashed:</MyHeader>
        <MyText style={{ marginVertical: 40, fontSize: 16 }}>
          {error?.message}
        </MyText>
        <MyButton
          style={{ marginBottom: 20 }}
          secondary
          onPress={() => Clipboard.setString(error?.stack || "")}
        >
          copy stacktrace to clipboard
        </MyButton>
        <MyButton onPress={resetErrorBoundary}>reload app</MyButton>
      </ScrollView>
    </ScreenWrapper>
  );
}

const myErrorHandler = (error: Error) => {
  Sentry.Native.captureException(error);
};

export const Routes: React.FC<RoutesProps> = ({}) => {
  const { editorBackground } = useTheme();
  const { data, isLoading } = useQuery<MeResponse>("/me");
  const routeNameRef = React.useRef<string | undefined>();
  const navigationRef = React.useRef<NavigationContainerRef>(null);

  let body: any = null;

  if (isLoading) {
    body = <FullscreenLoading />;
  } else if (!data?.user) {
    body = <AuthStack />;
  } else if (data.user.goal && data.user.codeImgIds.length) {
    body = <MainTabStack />;
  } else {
    body = <ProfileStack isNewUser />;
  }

  return (
    <SafeAreaView style={{ flex: 1, backgroundColor: editorBackground }}>
      <ReactQueryErrorResetBoundary>
        {({ reset }) => (
          <ErrorBoundary
            onReset={reset}
            FallbackComponent={ErrorFallback}
            onError={myErrorHandler}
          >
            <NavigationContainer
              ref={navigationRef}
              onStateChange={() => {
                const previousRouteName = routeNameRef.current;
                const currentRouteName = navigationRef.current?.getCurrentRoute()
                  ?.name;

                if (previousRouteName !== currentRouteName) {
                  if (
                    !["swiper", "viewProfile", "matchy"].includes(
                      currentRouteName || ""
                    )
                  ) {
                    useShowTabs.getState().set({ show: false });
                  } else {
                    useShowTabs.getState().set({ show: true });
                  }
                }

                routeNameRef.current = currentRouteName;
              }}
              linking={linking}
              fallback={<FullscreenLoading />}
            >
              {body}
            </NavigationContainer>
          </ErrorBoundary>
        )}
      </ReactQueryErrorResetBoundary>
    </SafeAreaView>
  );
};