import { useSplitClient } from "@splitsoftware/splitio-react";
import { Button, Result } from "antd";
import LogRocket from "logrocket";
import { lazy, Suspense, useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { Route, Routes, useNavigate } from "react-router-dom";
import { createStructuredSelector } from "reselect";
import DocumentEditorContainer from "../components/document-editor/document-editor.container";
import ErrorBoundary from "../components/error-boundary/error-boundary.component";
import LoadingSpinner from "../components/loading-spinner/loading-spinner.component";
import DisclaimerPage from "../pages/disclaimer/disclaimer.page";
import LandingPage from "../pages/landing/landing.page";
import TechPageContainer from "../pages/tech/tech.page.container";
import SimplifiedPartsPageContainer from "../pages/simplified-parts/simplified-parts.page.container.jsx";
import { setIsPartsEntry, setOnline } from "../redux/application/application.actions";
import { selectIsPartsEntry, selectOnline } from "../redux/application/application.selectors";
import { checkUserSession } from "../redux/user/user.actions";
import { selectBodyshop, selectCurrentEula, selectCurrentUser } from "../redux/user/user.selectors";
import PrivateRoute from "../components/PrivateRoute";
import "./App.styles.scss";
import Eula from "../components/eula/eula.component";
import InstanceRenderMgr from "../utils/instanceRenderMgr";
import ProductFruitsWrapper from "./ProductFruitsWrapper.jsx";
import { NotificationProvider } from "../contexts/Notifications/notificationContext.jsx";
import SocketProvider from "../contexts/SocketIO/socketProvider.jsx";

const ResetPassword = lazy(() => import("../pages/reset-password/reset-password.component"));
const ManagePage = lazy(() => import("../pages/manage/manage.page.container"));
const SignInPage = lazy(() => import("../pages/sign-in/sign-in.page"));
const CsiPage = lazy(() => import("../pages/csi/csi.container.page"));

const mapStateToProps = createStructuredSelector({
  currentUser: selectCurrentUser,
  online: selectOnline,
  bodyshop: selectBodyshop,
  currentEula: selectCurrentEula,
  isPartsEntry: selectIsPartsEntry
});

const mapDispatchToProps = (dispatch) => ({
  checkUserSession: () => dispatch(checkUserSession()),
  setOnline: (isOnline) => dispatch(setOnline(isOnline)),
  setIsPartsEntry: (isParts) => dispatch(setIsPartsEntry(isParts))
});

export function App({
  bodyshop,
  checkUserSession,
  currentUser,
  online,
  setOnline,
  setIsPartsEntry,
  currentEula,
  isPartsEntry
}) {
  const client = useSplitClient().client;
  const [listenersAdded, setListenersAdded] = useState(false);
  const { t } = useTranslation();
  const navigate = useNavigate();

  useEffect(() => {
    if (!navigator.onLine) {
      setOnline(false);
    }
    checkUserSession();
  }, [checkUserSession, setOnline]);

  useEffect(() => {
    const pathname = window.location.pathname;
    const isParts = pathname === "/parts" || pathname.startsWith("/parts/");
    setIsPartsEntry(isParts);
  }, [setIsPartsEntry]);

  //const b = Grid.useBreakpoint();
  // console.log("Breakpoints:", b);

  // Associate event listeners, memoize to prevent multiple listeners being added
  useEffect(() => {
    const offlineListener = () => {
      setOnline(false);
    };

    const onlineListener = () => {
      setOnline(true);
    };

    if (!listenersAdded) {
      console.log("Added events for offline and online");
      window.addEventListener("offline", offlineListener);
      window.addEventListener("online", onlineListener);
      setListenersAdded(true);
    }

    return () => {
      window.removeEventListener("offline", offlineListener);
      window.removeEventListener("online", onlineListener);
    };
  }, [setOnline, listenersAdded]);

  useEffect(() => {
    if (currentUser.authorized && bodyshop) {
      client.setAttribute("imexshopid", bodyshop.imexshopid);

      if (
        client.getTreatment("LogRocket_Tracking") === "on" ||
        window.location.hostname ===
          InstanceRenderMgr({
            imex: "beta.imex.online",
            rome: "beta.romeonline.io"
          })
      ) {
        console.log("LR Start");
        LogRocket.init(
          InstanceRenderMgr({
            imex: "gvfvfw/bodyshopapp",
            rome: "rome-online/rome-online"
          })
        );
      }
    }
  }, [bodyshop, client, currentUser.authorized]);

  if (currentUser.authorized === null) {
    return <LoadingSpinner message={t("general.labels.loggingin")} />;
  }

  if (!online) {
    return (
      <Result
        status="warning"
        title={t("general.labels.nointernet")}
        subTitle={t("general.labels.nointernet_sub")}
        extra={
          <Button type="primary" onClick={() => window.location.reload()}>
            {t("general.actions.refresh")}
          </Button>
        }
      />
    );
  }

  if (currentEula && !currentUser.eulaIsAccepted) {
    return <Eula />;
  }

  // Any route that is not assigned and matched will default to the Landing Page component
  return (
    <Suspense
      fallback={
        <LoadingSpinner
          message={InstanceRenderMgr({
            imex: t("titles.imexonline"),
            rome: t("titles.romeonline")
          })}
        />
      }
    >
      <ProductFruitsWrapper
        currentUser={currentUser}
        bodyshop={bodyshop}
        workspaceCode={bodyshop?.tours_enabled ? "9BkbEseqNqxw8jUH" : ""}
        isPartsEntry={isPartsEntry}
      />

      <NotificationProvider>
        <Routes>
          <Route
            path="*"
            element={
              <ErrorBoundary>
                <LandingPage />
              </ErrorBoundary>
            }
          />
          <Route
            path="/signin"
            element={
              <ErrorBoundary>
                <SignInPage />
              </ErrorBoundary>
            }
          />
          <Route
            path="/resetpassword"
            element={
              <ErrorBoundary>
                <ResetPassword />
              </ErrorBoundary>
            }
          />
          <Route
            path="/csi/:surveyId"
            element={
              <ErrorBoundary>
                <CsiPage />
              </ErrorBoundary>
            }
          />
          <Route
            path="/disclaimer"
            element={
              <ErrorBoundary>
                <DisclaimerPage />
              </ErrorBoundary>
            }
          />
          <Route
            path="/manage/*"
            element={
              <ErrorBoundary>
                <SocketProvider bodyshop={bodyshop} navigate={navigate} currentUser={currentUser}>
                  <PrivateRoute isAuthorized={currentUser.authorized} />
                </SocketProvider>
              </ErrorBoundary>
            }
          >
            <Route path="*" element={<ManagePage />} />
          </Route>
          <Route
            path="/tech/*"
            element={
              <ErrorBoundary>
                <SocketProvider bodyshop={bodyshop} navigate={navigate} currentUser={currentUser}>
                  <PrivateRoute isAuthorized={currentUser.authorized} />
                </SocketProvider>
              </ErrorBoundary>
            }
          >
            <Route path="*" element={<TechPageContainer />} />
          </Route>
          <Route
            path="/parts/*"
            element={
              <ErrorBoundary>
                <SocketProvider bodyshop={bodyshop} navigate={navigate} currentUser={currentUser}>
                  <PrivateRoute isAuthorized={currentUser.authorized} />
                </SocketProvider>
              </ErrorBoundary>
            }
          >
            <Route path="*" element={<SimplifiedPartsPageContainer />} />
          </Route>
          <Route path="/edit/*" element={<PrivateRoute isAuthorized={currentUser.authorized} />}>
            <Route path="*" element={<DocumentEditorContainer />} />
          </Route>
        </Routes>
      </NotificationProvider>
    </Suspense>
  );
}

export default connect(mapStateToProps, mapDispatchToProps)(App);
