import React, {
  useState,
  useEffect,
  createContext,
  useMemo,
  useCallback,
  useRef,
} from "react";
import { Outlet } from "react-router-dom";
import {
  Layout,
  CenterLayout,
  LeftLayout,
  RightLayout,
  MainLayout,
} from "./index.styled";
import {
  Header as HeaderComponent,
  SideNav as SideBar,
  SideMenu,
  FullPageLoader,
  DeveloperBanner,
} from "../";
import { user, sideMenuOptions, getLeftRoutes } from "../../hooks/leftNavMenu";
import InstructorAccountSwitcher from "../instructorAccountSwitcher";
// import SideMenu from "../sideBar/sideMenu";
import EnterpriseRightBar, {
  FallbackRightBar,
} from "../fileRightBar/enterpriseRightBar";
import useHeader from "../header/getHeaderDetails";
import GracePeriod from "../deactivated";
import MobileLayout from "../mobileLayout";
import useTranslation from "../../hooks/useTranslation";
import useMessageKit from "../../hooks/messaging-kit";
import AffiliateRightBar from "../fileRightBar/instructorRightBar2/affiliateRightBar";
import instructorImage from "../../assets/images/instructor.png";
import PersonalRightBar from "../fileRightBar/instructorRightBar2/personalRightBar";
import TestModal from "../fileRightBar/instructorRightBar2/testModal";
import BlankState from "../dashboardState/blankState";
import PendingDeleteState from "../dashboardState/pendingDeleteState";
import { getCookie, setCookie } from "../header/getCookies";
import deleteCookies from "../instructorAccountSwitcher/deleteCookies";

const normalizePathname = (pathname = "") => {
  const normalizedPathname = String(pathname).toLowerCase().trim();
  if (!normalizedPathname || normalizedPathname === "/") {
    return "/";
  }

  return normalizedPathname.endsWith("/")
    ? normalizedPathname.slice(0, -1)
    : normalizedPathname;
};

const AppMainLayout = ({ children }) => {
  const centerLayoutRef = useRef(null);

  const scrollToBottom = useCallback(() => {
    setTimeout(() => {
      if (centerLayoutRef.current) {
        centerLayoutRef.current.scrollTo({
          top: centerLayoutRef.current.scrollHeight,
          behavior: "smooth",
        });
      }
    }, 100);
  }, []);

  const [isOpen, setIsOpen] = useState(true);
  const [rightLayout, setRightLayout] = useState(true);
  const [rightComponent, setRightComponent] = useState();
  const [generalData, setGeneralData] = useState({});
  const [coming, setComing] = useState();
  const [activePage, setActivePage] = useState("reports");
  const [page, setPage] = useState("index");
  const [studyTab, setStudyTab] = useState("analysis");
  const [selectedCourseId, setSelectedCourseId] = useState(null);
  const [hasLayoutBackgroundImage, setHasLayoutBackgroundImage] =
    useState(false);
  const [sideMenuLayout, setSideMenuLayout] = useState(true);
  const [centerLayoutStyle, setCenterLayoutStyle] = useState({});
  const [affiliatesActive, setAffiliatesActive] = useState(false);
  const [accessToken] = useState(() => getCookie("access") ?? "");
  const [envType, setEnvType] = useState("");
  const [newNotifications, setNewNotifications] = useState([]);
  const [affiliateAccount, setAffiliateAccount] = useState(() => {
    const activeAffiliateId = getCookie("affiliateAccount");
    return activeAffiliateId ? { id: activeAffiliateId } : null;
  });
  const [gracePeriod, setGracePeriod] = useState(true); // test
  const [deviceWidth, setDeviceWidth] = useState(window.innerWidth);
  const [showTest, setShowTest] = useState(null);
  const [storageSummary, setStorageSummary] = useState(null);
  const [selectedAccount, setSelectedAccount] = useState();
  const [affilitateSearch, setAffilitateSearch] = useState("");
  const [planRequestAccountId, setPlanRequestAccountId] = useState(null);
  const [
    defaultAffiliateRequestAccountId,
    setDefaultAffiliateRequestAccountId,
  ] = useState(null);
  const [affiliateListRequestAccountId, setAffiliateListRequestAccountId] =
    useState(null);

  // for mobile view
  useEffect(() => {
    const handleResize = () => setDeviceWidth(window.innerWidth);
    window.addEventListener("resize", handleResize);
    return () => window.removeEventListener("resize", handleResize);
  }, []);

  // on page load check local storage for state of isOpen and set that to the state that controls the opening and closing of the navbar
  useEffect(() => {
    window.localStorage.getItem("isOpen") &&
      setIsOpen(
        window.localStorage.getItem("isOpen") === "true" ? true : false,
      );
  }, []);

  const {
    notificationMarkReadData,
    handleGetNotificationMarkRead,
    userPlanData,
    handleGetUserPlan,
    getCurrentSubscriptionData,
    handleCurrentSubscription,
    getDefaultAccount,
    handleGetDefaultAccount,
    user,
    userDetails,
    handleGetFileStorageSummary,
    getFileStorageSummaryData,
  } = useHeader({ default: true });

  const wordBank = [
    "Sign out",
    "Learning",
    "Community",
    "Fun",
    "Duet",
    "Speech",
    "Settings",
    "Notifications",
    "Hello",
    "API",
    "Documentation",
    "Reports",
    "Created",
    "Report",
    "Dictionary",
    "What's your language?",
    "Add account",
    "Developer accounts",
    "Developer",
    "Search",
    "Get started",
    "Sign in",
    "Sorry, you can’t access your account on a mobile browser.",
    "We know it's inconvenient. For better user accessibility, login with a desktop device or via our mobile app.",
    "Download on google play",
    "Download on apple store",
    "Help",
    "10% off your next subscription purchase?",
    "Let's go!",
    "Get a discount when you upgrade to a custom plan and unlock a new world of building.",
    "Contact us",
    "Get more API calls for less with our custom plan",
    "Upgrade now for a 10% discount.",
    "Build the future with Learngual!",
    "Choose our custom plans for more calls and better flexibility.",
    "We know it's inconvenient. For better user accessibility, login with a desktop device.",
  ];

  const {
    setDefaultLang,
    defaultLang,
    findText,
    translations,
    isTranslationsLoading,
    setIsTranslationsLoading,
  } = useTranslation(wordBank);

  // get current default account and store in cookie (from api);
  useEffect(() => {
    if (getDefaultAccount?.data) {
      const nextSelectedAccount = getDefaultAccount?.data;
      const date = new Date();
      date.setDate(date.getDate() + 28);

      const domain = window.location.href.includes("localhost")
        ? "localhost"
        : window.location.hostname?.includes("ca")
          ? ".learngual.ca"
          : ".learngual.com";

      document.cookie =
        "defaultAccountID=" +
        getDefaultAccount?.data?.id +
        `; domain=${domain}; path=/; expires=${date.toUTCString()};`;

      document.cookie =
        "defaultAccountType=" +
        getDefaultAccount?.data?.type +
        `; domain=${domain}; path=/; expires=${date.toUTCString()};`;

      setDefaultLang(getDefaultAccount?.data?.language);

      setSelectedAccount(nextSelectedAccount);
      setGeneralData((currentData) => ({
        ...currentData,
        selectedAccount: nextSelectedAccount,
        defaultAccount: nextSelectedAccount,
      }));
    }
  }, [getDefaultAccount?.data, setDefaultLang]);

  useEffect(() => {
    if (window.location.host.includes("coming")) {
      setComing(true);
    } else {
      setComing(false);
    }
  }, []);

  useEffect(() => {
    if (accessToken) {
      handleGetDefaultAccount();
    }
  }, [accessToken]);

  // setting current environment type
  useEffect(() => {
    if (window.location.hostname.includes("staging")) {
      setEnvType("staging");
    } else if (window.location.hostname.includes("localhost")) {
      setEnvType("localhost");
    } else {
      setEnvType("live");
    }
  }, []);

  // const currentPlan = userPlanData?.data?.current_plan;
  const planState = userPlanData?.data?.state;

  const messageKit = useMessageKit(); // useMessageKit

  const {
    handleGetAllAffiliate,
    getAllAffiliateData,
    getDefaultAffiliateData,
    handleGetDefaultAffiliate,
  } = useHeader();
  const pathname = normalizePathname(
    window.location.pathname || window.location?.href || "/",
  );

  // console.log('pathname', pathname);
  const resolvedSelectedAccount =
    generalData?.selectedAccount ?? selectedAccount ?? getDefaultAccount?.data;
  const selectedAccountId = resolvedSelectedAccount?.id;
  const activeAccountType = useMemo(
    () => String(resolvedSelectedAccount?.type ?? "").toLowerCase(),
    [resolvedSelectedAccount?.type],
  );
  const hasDefaultAccountResolved = Boolean(
    selectedAccountId ||
    getDefaultAccount?.response ||
    getDefaultAccount?.data ||
    getDefaultAccount?.error,
  );
  const hasUserPlanResolved =
    activeAccountType !== "enterprise" && activeAccountType !== "instructor"
      ? true
      : planRequestAccountId === selectedAccountId &&
        Boolean(
          userPlanData?.response || userPlanData?.data || userPlanData?.error,
        );
  const hasDefaultAffiliateResolved =
    activeAccountType !== "instructor"
      ? true
      : defaultAffiliateRequestAccountId === selectedAccountId &&
        Boolean(
          getDefaultAffiliateData?.response ||
          getDefaultAffiliateData?.data ||
          getDefaultAffiliateData?.error,
        );
  const hasAffiliateListResolved =
    activeAccountType !== "instructor"
      ? true
      : affiliateListRequestAccountId === selectedAccountId &&
        Boolean(
          getAllAffiliateData?.response ||
          getAllAffiliateData?.data ||
          getAllAffiliateData?.error,
        );
  const handleGetStorageSummary = useCallback(async () => {
    if (
      activeAccountType === "enterprise" ||
      activeAccountType === "instructor"
    ) {
      const res = await handleGetFileStorageSummary(activeAccountType);
      res?.data && setStorageSummary({ ...res?.data, results: undefined });
    }
  }, [activeAccountType, handleGetFileStorageSummary]);
  const accountName = useMemo(() => {
    const { user: User } = generalData;
    if (!User || !resolvedSelectedAccount) return "..."; // or an empty string
    const defaultAccountName = String(User.first_name).concat(
      " ",
      User.last_name,
    );

    switch (activeAccountType) {
      case "enterprise":
        return (
          resolvedSelectedAccount?.metadata?.organization_name ??
          defaultAccountName
        );
      case "developer":
        return (
          resolvedSelectedAccount?.metadata?.organization_name ??
          resolvedSelectedAccount?.metadata?.org_name ??
          defaultAccountName
        );
      default:
        return defaultAccountName;
    }
  }, [activeAccountType, generalData, resolvedSelectedAccount]);

  //find account name

  const findAccountNames = useCallback(
    (account, User = generalData?.user) => {
      if (!User || !account) return "";
      switch (String(account.type).toLowerCase()) {
        case "enterprise":
          return account?.metadata?.organization_name;
        case "developer":
          return (
            account?.metadata?.organization_name ?? account?.metadata?.org_name
          );
        default:
          return User.first_name.concat(" ", User.last_name);
      }
    },
    [generalData],
  );

  useEffect(() => {
    if (!selectedAccountId) {
      return;
    }

    handleGetStorageSummary();
  }, [handleGetStorageSummary, selectedAccountId]);

  useEffect(() => {
    if (
      !selectedAccountId ||
      (activeAccountType !== "enterprise" && activeAccountType !== "instructor")
    ) {
      return;
    }

    let isMounted = true;

    const fetchUserPlan = async () => {
      await handleGetUserPlan();
      if (isMounted) {
        setPlanRequestAccountId(selectedAccountId);
      }
    };

    fetchUserPlan();

    return () => {
      isMounted = false;
    };
  }, [activeAccountType, selectedAccountId]);

  useEffect(() => {
    if (activeAccountType !== "instructor" || !selectedAccountId) {
      return;
    }

    let isMounted = true;

    const fetchDefaultAffiliate = async () => {
      await handleGetDefaultAffiliate();
      if (isMounted) {
        setDefaultAffiliateRequestAccountId(selectedAccountId);
      }
    };

    fetchDefaultAffiliate();

    return () => {
      isMounted = false;
    };
  }, [activeAccountType, selectedAccountId]);

  useEffect(() => {
    if (activeAccountType !== "instructor" || !selectedAccountId) {
      return;
    }

    let isMounted = true;

    const fetchAffiliateList = async () => {
      await handleGetAllAffiliate({ search: affilitateSearch });
      if (isMounted) {
        setAffiliateListRequestAccountId(selectedAccountId);
      }
    };

    fetchAffiliateList();

    return () => {
      isMounted = false;
    };
  }, [activeAccountType, affilitateSearch, selectedAccountId]);

  // handling instructor affiliate cookie
  const hasAxtiveAffiliateId =
    defaultAffiliateRequestAccountId === selectedAccountId
      ? getDefaultAffiliateData?.data?.id
      : null;
  const activeAffiliateId =
    hasAxtiveAffiliateId ?? affiliateAccount?.id ?? null;

  const affiliateList =
    affiliateListRequestAccountId === selectedAccountId
      ? (getAllAffiliateData?.data?.results?.map?.((account) => {
          const image = account?.profile_photo?.url;
          return {
            name: account?.metadata?.organization_name ?? "...",
            image,
            id: account?.id,
          };
        }) ?? [])
      : [];

  useEffect(() => {
    if (activeAccountType !== "instructor") {
      deleteCookies("affiliateAccount");
      setAffiliateAccount(null);
      return;
    }

    if (hasAxtiveAffiliateId) {
      setCookie("affiliateAccount", hasAxtiveAffiliateId);
      setAffiliateAccount((currentValue) =>
        currentValue?.id === hasAxtiveAffiliateId
          ? currentValue
          : { id: hasAxtiveAffiliateId },
      );
      return;
    }

    if (affiliateAccount?.id) {
      setCookie("affiliateAccount", affiliateAccount.id);
    }
  }, [activeAccountType, affiliateAccount?.id, hasAxtiveAffiliateId]);

  const accountIsPendingDeletion = resolvedSelectedAccount?.pending_delete;
  const isSettingsRoute = pathname.includes("/settings");

  const isEnterpriseExceptionRoute =
    isSettingsRoute ||
    pathname.includes("/file-m") ||
    pathname.includes("/file-manager");
  const isInstructorExceptionRoute =
    isSettingsRoute ||
    pathname.includes("/notif") ||
    pathname.includes("/notification") ||
    pathname.includes("/notifications");
  const shouldBootstrapEnterpriseGate =
    activeAccountType === "enterprise" &&
    !coming &&
    !isEnterpriseExceptionRoute &&
    !hasUserPlanResolved;
  const shouldBootstrapInstructorGate =
    activeAccountType === "instructor" &&
    !coming &&
    !isInstructorExceptionRoute &&
    (!hasUserPlanResolved ||
      !hasDefaultAffiliateResolved ||
      !hasAffiliateListResolved);
  const shouldBootstrapLayout = !resolvedSelectedAccount
    ? !hasDefaultAccountResolved
    : shouldBootstrapEnterpriseGate || shouldBootstrapInstructorGate;
  const shouldShowBlankState =
    !resolvedSelectedAccount && hasDefaultAccountResolved;

  const isPendingDeleteBlockedRoute =
    Boolean(accountIsPendingDeletion) && !isSettingsRoute;

  const isEnterpriseBlockedRoute =
    activeAccountType === "enterprise" &&
    !coming &&
    !isEnterpriseExceptionRoute &&
    (planState === "GRACE PERIOD" ||
      planState === "EXPIRED" ||
      (hasUserPlanResolved && !planState));

  const isInstructorBlockedRoute =
    activeAccountType === "instructor" &&
    !coming &&
    !isInstructorExceptionRoute &&
    hasUserPlanResolved &&
    hasDefaultAffiliateResolved &&
    hasAffiliateListResolved &&
    !planState &&
    !activeAffiliateId;

  const shouldRenderInstructorSwitcher =
    activeAccountType === "instructor" &&
    !accountIsPendingDeletion &&
    hasDefaultAffiliateResolved &&
    hasAffiliateListResolved &&
    affiliateList.length > 0;

  const centerContent = shouldShowBlankState ? (
    <BlankState />
  ) : isPendingDeleteBlockedRoute ? (
    <PendingDeleteState
      deleteDate={resolvedSelectedAccount?.pending_delete_datetime}
    />
  ) : isEnterpriseBlockedRoute ? (
    <GracePeriod
      getCurrentSubscriptionData={getCurrentSubscriptionData}
      handleCurrentSubscription={handleCurrentSubscription}
      gracePeriod={gracePeriod}
      stateType={planState === "GRACE PERIOD" ? 1 : 2}
      findText={findText}
    />
  ) : isInstructorBlockedRoute ? (
    <div className="instructor_expired">
      <h1>{findText("Dashboard")}</h1>
      <div className="instructor_expired_body">
        <div className="instructor_expired_center">
          <img src={instructorImage} alt="" />
          <h4>
            {findText("You haven’t been added to an enterprise account yet")}
          </h4>
          <p>
            {findText(
              "This account will be active once an enterprise assigns you as an instructor.",
            )}
          </p>
        </div>
      </div>
    </div>
  ) : (
    (children ?? <Outlet />)
  );
  const shouldHideRightLayout =
    shouldShowBlankState ||
    isPendingDeleteBlockedRoute ||
    isEnterpriseBlockedRoute ||
    isInstructorBlockedRoute;
  const rightLayoutContent = shouldHideRightLayout
    ? null
    : (rightComponent ??
      (activeAccountType === "enterprise" ? (
        <EnterpriseRightBar
          planState={planState}
          affiliateAccount={affiliateAccount}
          isPendingDelete={accountIsPendingDeletion}
        />
      ) : activeAccountType === "instructor" ? (
        activeAffiliateId ? (
          <AffiliateRightBar
            planState={planState}
            affiliateAccount={activeAffiliateId}
            isPendingDelete={accountIsPendingDeletion}
          />
        ) : null
      ) : activeAccountType === "personal" ? (
        <PersonalRightBar findText={findText} onShowTest={setShowTest} />
      ) : activeAccountType === "developer" ? (
        <DeveloperBanner findText={findText} />
      ) : (
        <FallbackRightBar />
      )));
  console.log("logss");

  return (
    <OutletContext.Provider
      value={{
        messageKit,
        affiliateAccount,
        userDetails,
        findAccountNames,
        accountName,
        user,
        setRightComponent,
        setRightLayout,
        generalData,
        setGeneralData,
        coming,
        hasLayoutBackgroundImage,
        setHasLayoutBackgroundImage,
        setSideMenuLayout,
        activePage,
        setActivePage,
        studyTab,
        setStudyTab,
        page,
        setPage,
        selectedCourseId,
        setSelectedCourseId,
        centerLayoutStyle,
        setCenterLayoutStyle,
        affiliatesActive,
        accessToken,
        envType,
        newNotifications,
        setNewNotifications,
        notificationMarkReadData,
        handleGetNotificationMarkRead,
        planState,
        storageSummary,
        refreshStorageSumary: handleGetStorageSummary,
        findText,
        defaultLang,
        setDefaultLang,
        isTranslationsLoading,
        setIsTranslationsLoading,
        scrollToBottom,
      }}
    >
      {/* display mobile layout on device width*/}
      {deviceWidth < 1200 ? (
        <MobileLayout findText={findText} />
      ) : (
        <>
          {(isTranslationsLoading && Object.keys(translations)?.length === 0) ||
          shouldBootstrapLayout ? (
            <FullPageLoader hasBackground fixed={true} />
          ) : (
            <Layout
              coming={coming}
              hasLayoutBackgroundImage={hasLayoutBackgroundImage}
            >
              <HeaderComponent
                setNewNotifications={setNewNotifications}
                findText={findText}
                defaultLang={defaultLang}
                setDefaultLang={setDefaultLang}
                setIsTranslationsLoading={setIsTranslationsLoading}
                handleGetDefaultAccount={handleGetDefaultAccount}
                getDefaultAccount={getDefaultAccount}
                selectedAccount={resolvedSelectedAccount}
                setSelectedAccount={setSelectedAccount}
              />
              <MainLayout coming={coming}>
                <LeftLayout>
                  <SideBar
                    routes={getLeftRoutes(activeAccountType)}
                    findText={findText}
                  />
                  {!coming && (
                    <>
                      {sideMenuLayout && (
                        <SideMenu
                          user={user}
                          routes={sideMenuOptions}
                          affiliatesActive={affiliateAccount}
                          userType={resolvedSelectedAccount?.type?.toLowerCase()}
                          isOpen={isOpen}
                          setIsOpen={setIsOpen}
                          setRightComponent={setRightComponent}
                          planState={planState}
                          findText={findText}
                        />
                      )}
                    </>
                  )}
                </LeftLayout>
                {
                  <CenterLayout
                    ref={centerLayoutRef}
                    isOpen={isOpen}
                    style={centerLayoutStyle}
                    href={pathname}
                  >
                    {shouldRenderInstructorSwitcher && (
                      <InstructorAccountSwitcher
                        affiliateList={affiliateList}
                        generalData={generalData}
                        onChange={(v) => setAffiliateAccount(v)}
                        setSearch={setAffilitateSearch}
                        defaultAffiliate={getDefaultAffiliateData?.data}
                        findText={findText}
                      />
                    )}
                    {centerContent}
                  </CenterLayout>
                }
                {showTest && (
                  <TestModal
                    data={showTest}
                    onClose={() => {
                      setShowTest(null);
                    }}
                  />
                )}
                {rightLayout && !coming && (
                  <RightLayout>{rightLayoutContent}</RightLayout>
                )}
              </MainLayout>
            </Layout>
          )}
        </>
      )}
    </OutletContext.Provider>
  );
};

export const OutletContext = createContext({});
export default AppMainLayout;
