import { type FC, type ReactNode, Suspense, useEffect, useState } from 'react';
import { Outlet } from 'react-router-dom';

import Stack from '@material-hu/mui/Stack';
import { experimentalStyled } from '@material-hu/mui/styles';

import HuSpinner from '@material-hu/components/design-system/ProgressIndicators/Spinner';

import { useLayoutContext } from 'src/contexts/LayoutContext';
import { NotificationsProvider } from 'src/contexts/NotificationsContext';
import { PreferencesDrawerProvider } from 'src/contexts/PreferencesDrawerContext';
import { useSidebar } from 'src/contexts/SidebarContext';
import { SocketProvider } from 'src/contexts/SocketContext';
import useHuGoTheme from 'src/hooks/useHuGoTheme';
import { usePaths } from 'src/hooks/usePaths';
import { groupsRoutes } from 'src/pages/dashboard/groups/routes';
import { lazyRetry } from 'src/utils/lazyRetry';
import { getPaddingDashboardLayout, NAVBAR_HEIGHT } from 'src/utils/sidebar';

import ErrorBoundary from 'src/components/ErrorBoundary';

import { SuspenseWithLoadingState } from '../loading/SuspenseWithLoadingState';

import { SidebarSkeleton } from './dashboardSidebar/components/SidebarSkeleton';
import DashboardSidebar from './dashboardSidebar/DashboardSidebar';
import { GlobalHelmetTitlePrefix } from './GlobalHelmetTitlePrefix';
import DashboardNavbar from './navbar/DashboardNavbar';

const IncomingCall = lazyRetry(
  () => import('src/pages/dashboard/videoCall/IncomingCall'),
);
const DarkModeAnnouncement = lazyRetry(() =>
  import('src/components/dashboard/initialPopups').then(module => ({
    default: module.DarkModeAnnouncement,
  })),
);

export type DashboardLayoutProps = {
  children?: ReactNode;
};

type DashboardLayoutWrapperProps = {
  paddingLeft: number;
  isNavbarDisabled: boolean;
};

const DashboardLayoutRoot = experimentalStyled('main')(({ theme }) => ({
  backgroundColor: theme.palette.new.background.layout.default,
  display: 'flex',
  overflow: 'hidden',
  height: '100%',
  width: '100%',
}));

const DashboardLayoutWrapper = experimentalStyled(
  'div',
)<DashboardLayoutWrapperProps>(({ paddingLeft, isNavbarDisabled }) => ({
  display: 'flex',
  flex: '1 1 auto',
  overflow: 'hidden',
  paddingTop: isNavbarDisabled ? '0px' : `${NAVBAR_HEIGHT}px`,
  paddingLeft: `${paddingLeft}px`,
}));

const DashboardLayoutContainer = experimentalStyled('div')({
  display: 'flex',
  flex: '1 1 auto',
  overflow: 'hidden',
});

const DashboardLayoutContent = experimentalStyled('div')({
  flex: '1 1 auto',
  height: '100%',
  overflow: 'auto',
  position: 'relative',
  WebkitOverflowScrolling: 'touch',
});

const DashboardLayout: FC<DashboardLayoutProps> = () => {
  const { setWidth } = useSidebar();
  const {
    isSidebarHidden,
    isNavbarDisabled,
    isSidebarDisabled,
    isSidebarCollapsed,
    collapseSidebar,
    toggleSidebar,
  } = useLayoutContext();

  const HuGoThemeProvider = useHuGoTheme();

  const [isSubMenuOpened, setIsSubMenuOpened] = useState<boolean>(false);
  const [isSidebarLoading, setIsSidebarLoading] = useState<boolean>(true);

  const isGroups = usePaths([groupsRoutes.groups()]);

  // biome-ignore lint/correctness/useExhaustiveDependencies: Not all dependencies are actually needed
  useEffect(() => {
    const sidebarWidth = document.getElementById('sidebar')?.offsetWidth || 0;
    setWidth(sidebarWidth);
  }, [isSidebarCollapsed]);

  const handleSubMenu = (newValue: boolean) => setIsSubMenuOpened(newValue);

  const dashboardLayoutPaddingLeft = getPaddingDashboardLayout(
    isSidebarCollapsed,
    isSubMenuOpened,
    isGroups,
    isSidebarDisabled,
  );

  return (
    <SocketProvider>
      <NotificationsProvider>
        <PreferencesDrawerProvider>
          <DashboardLayoutRoot>
            <Suspense fallback={null}>
              <DarkModeAnnouncement />
            </Suspense>
            {!isNavbarDisabled && (
              <HuGoThemeProvider>
                <DashboardNavbar
                  onSidebarInteraction={toggleSidebar}
                  sidebarDisabled={isSidebarDisabled}
                  hidden={isSidebarHidden}
                  isSidebarCollapsed={isSidebarCollapsed}
                />
              </HuGoThemeProvider>
            )}
            {!isSidebarDisabled && (
              <SuspenseWithLoadingState
                onLoadingChange={setIsSidebarLoading}
                fallback={
                  <Stack
                    sx={{
                      width: dashboardLayoutPaddingLeft,
                      pt: `${NAVBAR_HEIGHT}px`,
                      height: '100%',
                      alignItems: 'center',
                    }}
                  >
                    <SidebarSkeleton
                      width={isSidebarCollapsed ? '40px' : '247px'}
                    />
                  </Stack>
                }
              >
                <DashboardSidebar
                  isCollapsed={isSidebarCollapsed}
                  onSubMenu={handleSubMenu}
                  collapseMenu={collapseSidebar}
                  isSubMenuOpened={isSubMenuOpened}
                  hidden={isSidebarHidden}
                />
              </SuspenseWithLoadingState>
            )}
            <DashboardLayoutWrapper
              id="dashboard-layout-wrapper"
              paddingLeft={
                isSidebarHidden || isSidebarLoading
                  ? 0
                  : dashboardLayoutPaddingLeft
              }
              isNavbarDisabled={isNavbarDisabled}
            >
              <DashboardLayoutContainer>
                <Suspense fallback={<HuSpinner />}>
                  <DashboardLayoutContent id="dashboard-layout-content">
                    <ErrorBoundary resetOnLocationChange>
                      <GlobalHelmetTitlePrefix>
                        <Outlet />
                      </GlobalHelmetTitlePrefix>
                    </ErrorBoundary>
                  </DashboardLayoutContent>
                </Suspense>
              </DashboardLayoutContainer>
            </DashboardLayoutWrapper>
            <Suspense fallback={null}>
              <IncomingCall />
            </Suspense>
          </DashboardLayoutRoot>
        </PreferencesDrawerProvider>
      </NotificationsProvider>
    </SocketProvider>
  );
};

export default DashboardLayout;
