import type { SuspenseProps } from "react";
import { lazy, Suspense, useEffect, useLayoutEffect, useRef } from "react";
import { lazily } from "react-lazily";
import ContactFormModal from "@ui_kit/ContactForm";
import dayjs from "dayjs";
import "dayjs/locale/ru";
import SigninDialog from "./pages/auth/Signin";
import SignupDialog from "./pages/auth/Signup";
import {
  Navigate,
  Route,
  Routes,
  useLocation,
  useNavigate,
} from "react-router-dom";
import "./index.css";
import Landing from "./pages/Landing/Landing";
import Main from "./pages/main";
import {
  clearAuthToken,
  createUserAccount,
  devlog,
  getMessageFromFetchError,
  UserAccount,
  useUserFetcher,
} from "@frontend/kitui";
import makeRequest from "@api/makeRequest";
import type { OriginalUserAccount } from "@root/user";
import {
  clearUserData,
  setCustomerAccount,
  setUser,
  setUserAccount,
  useUserStore,
} from "@root/user";
import { enqueueSnackbar } from "notistack";
import PrivateRoute from "@ui_kit/PrivateRoute";
import FloatingSupportChat from "@ui_kit/FloatingSupportChat";

import { Restore } from "./pages/auth/Restore";

import { isAxiosError } from "axios";
import RecoverPassword from "./pages/auth/RecoverPassword";
import { InfoPrivilege } from "./pages/InfoPrivilege";
import OutdatedLink from "./pages/auth/OutdatedLink";
import { useAfterpay } from "@utils/hooks/useAfterpay";

const MyQuizzesFull = lazy(() => import("./pages/createQuize/MyQuizzesFull"));

const ViewPage = lazy(() => import("./pages/ViewPublicationPage"));
const Analytics = lazy(() => import("./pages/Analytics/Analytics"));
const EditPage = lazy(() => import("./pages/startPage/EditPage"));
const { Tariffs } = lazily(() => import("./pages/Tariffs/Tariffs"));
const { DesignPage } = lazily(() => import("./pages/DesignPage/DesignPage"));
const { IntegrationsPage } = lazily(
  () => import("./pages/IntegrationsPage/IntegrationsPage"),
);
const { QuizAnswersPage } = lazily(
  () => import("./pages/QuizAnswersPage/QuizAnswersPage"),
);
const ChatImageNewWindow = lazy(
  () => import("@ui_kit/FloatingSupportChat/ChatImageNewWindow"),
);

dayjs.locale("ru");

const routeslink = [
  {
    path: "/edit",
    page: EditPage,
    header: true,
    sidebar: true,
    footer: true,
  },
  {
    path: "/design",
    page: DesignPage,
    header: true,
    sidebar: true,
    footer: true,
  },
  {
    path: "/integrations",
    page: IntegrationsPage,
    header: true,
    sidebar: true,
    footer: true,
  },
] as const;

const LazyLoading = ({ children, fallback }: SuspenseProps) => (
  <Suspense fallback={fallback ?? <></>}>{children}</Suspense>
);

export function useUserAccountFetcher<T = UserAccount>({
  onError,
  onNewUserAccount,
  url,
  userId,
}: {
  url: string;
  userId: string | null;
  onNewUserAccount: (response: T) => void;
  onError?: (error: any) => void;
}) {
  const onNewUserAccountRef = useRef(onNewUserAccount);
  const onErrorRef = useRef(onError);
  useLayoutEffect(() => {
    onNewUserAccountRef.current = onNewUserAccount;
    onErrorRef.current = onError;
  }, [onError, onNewUserAccount]);
  useEffect(() => {
    if (!userId) return;
    const controller = new AbortController();
    makeRequest<never, T>({
      url,
      contentType: true,
      method: "GET",
      useToken: true,
      withCredentials: false,
      signal: controller.signal,
    })
      .then((result) => {
        devlog("User account", result);
        onNewUserAccountRef.current(result);
      })
      .catch((error) => {
        devlog("Error fetching user account", error);
        if (isAxiosError(error) && error.response?.status === 404) {
          createUserAccount(controller.signal, url.replace("get", "create"))
            .then((result) => {
              devlog("Created user account", result);
              onNewUserAccountRef.current(result as T);
            })
            .catch((error) => {
              devlog("Error creating user account", error);
              onErrorRef.current?.(error);
            });
        } else {
          onErrorRef.current?.(error);
        }
      });
    return () => controller.abort();
  }, [url, userId]);
}

export default function App() {
  const userId = useUserStore((state) => state.userId);
  const location = useLocation();
  const navigate = useNavigate();

  useUserFetcher({
    url: process.env.REACT_APP_DOMAIN + `/user/${userId}`,
    userId,
    onNewUser: setUser,
    onError: (error) => {
      const errorMessage = getMessageFromFetchError(error);
      if (errorMessage) {
        enqueueSnackbar(errorMessage);
        clearUserData();
        clearAuthToken();
      }
    },
  });

  useUserAccountFetcher<UserAccount>({
    url: process.env.REACT_APP_DOMAIN + "/customer/account",
    userId,
    onNewUserAccount: setCustomerAccount,
    onError: (error) => {
      const errorMessage = getMessageFromFetchError(error);
      if (errorMessage) {
        enqueueSnackbar(errorMessage);
        clearUserData();
        clearAuthToken();
        navigate("/signin");
      }
    },
  });

  useUserAccountFetcher<OriginalUserAccount>({
    url: process.env.REACT_APP_DOMAIN + "/squiz/account/get",
    userId,
    onNewUserAccount: setUserAccount,
    onError: (error) => {
      const errorMessage = getMessageFromFetchError(error);
      if (errorMessage) {
        enqueueSnackbar(errorMessage);
        clearUserData();
        clearAuthToken();
        navigate("/signin");
      }
    },
  });

  if (location.state?.redirectTo)
    return (
      <Navigate
        to={location.state.redirectTo}
        replace
        state={{ backgroundLocation: location }}
      />
    );

  useAfterpay();

  return (
    <>
      <ContactFormModal />
      <FloatingSupportChat />
      {location.state?.backgroundLocation && (
        <Routes>
          <Route path="/signin" element={<SigninDialog />} />
          <Route path="/signup" element={<SignupDialog />} />
          <Route path="/recover" element={<Restore />} />
          <Route path="/changepwd" element={<RecoverPassword />} />
          <Route path="/changepwd/expired" element={<OutdatedLink />} />
        </Routes>
      )}
      <Routes location={location.state?.backgroundLocation || location}>
        <Route path="/" element={<Landing />} />
        <Route
          path="/signin"
          element={
            <Navigate to="/" replace state={{ redirectTo: "/signin" }} />
          }
        />
        <Route
          path="/signup"
          element={
            <Navigate to="/" replace state={{ redirectTo: "/signup" }} />
          }
        />
        <Route
          path="/recover"
          element={
            <Navigate to="/" replace state={{ redirectTo: "/recover" }} />
          }
        />
        <Route
          path="/changepwd"
          element={
            <Navigate
              to="/"
              replace
              state={{
                redirectTo: window.location.pathname + window.location.search,
              }}
            />
          }
        />
        <Route
          path="/changepwd/expired"
          element={
            <Navigate
              to="/"
              replace
              state={{ redirectTo: "/changepwd/expired" }}
            />
          }
        />
        <Route
          path="/list"
          element={<LazyLoading children={<MyQuizzesFull />} />}
        />
        <Route
          path={"/view/:quizId"}
          element={<LazyLoading children={<ViewPage />} />}
        />
        <Route
          path={"/tariffs"}
          element={<LazyLoading children={<Tariffs />} />}
        />
        <Route
          path={"/analytics"}
          element={<LazyLoading children={<Analytics />} />}
        />
        <Route
          path={"/results/:quizId"}
          element={<LazyLoading children={<QuizAnswersPage />} />}
        />
        <Route
          path={"/qaz"}
          element={<LazyLoading children={<InfoPrivilege />} />}
        />
        <Route path={"/image/:srcImage"} element={<ChatImageNewWindow />} />
        <Route element={<PrivateRoute />}>
          {routeslink.map((e, i) => (
            <Route
              key={i}
              path={e.path}
              element={
                <LazyLoading
                  children={
                    <Main
                      Page={e.page}
                      header={e.header}
                      sidebar={e.sidebar}
                      footer={e.footer}
                    />
                  }
                />
              }
            />
          ))}
        </Route>
      </Routes>
    </>
  );
}
