'use client';
import { FunctionComponent, PropsWithChildren, ReactNode, useState } from 'react';
import { useTranslations } from 'next-intl';
import { Box, Stack, useTheme } from '@mui/material';
import { AppIconButton, ErrorBoundary, RouteFadeIn } from '@/components';
import { LinkToPage } from '@/utils';
import { TopBar } from './components';
import SideBar from './components/SideBar';
import { DarkModeToggleButton } from './components/DarkModeButton';
import { TOP_BAR_DESKTOP_HEIGHT, TOP_BAR_MOBILE_HEIGHT } from './config';
import { useRouteTitle } from './routeTitle';

interface Props {
  sidebarItems: Array<LinkToPage>;
  /** Rendered below the sidebar's brand header (the nurse shell's `ProfileSummary` identity card). */
  sidebarIdentity?: ReactNode;
  /** Rendered in the TopBar, before the header controls (the admin/partner identity chip). */
  identity?: ReactNode;
  /** Extra chrome actions (e.g. the notification bell) rendered next to the dark-mode toggle. */
  headerActions?: ReactNode;
  /**
   * A mobile-only (`<md`) bottom nav rendered under the content column (the nurse shell's 5-tab
   * bar). Receives a callback that opens the same mobile drawer the TopBar's menu button opens, so
   * a "more" tab can reveal the rest of the sidebar without a second drawer.
   */
  mobileBottomBar?: (openMobileSidebar: () => void) => ReactNode;
}

/**
 * The shared engine behind the nurse/admin/partner shells: a fixed `TopBar` showing the current
 * page title (`useRouteTitle`, longest-prefix over `ROUTES.*`) plus a `SideBar` that renders as a
 * mobile overlay and a desktop in-flow column at once (see `SideBar` for why that kills the SSR
 * flash). The sidebar and the main column are flex siblings in a row — native RTL flexbox puts the
 * sidebar at the reading-start side with no manual offset math.
 * @layout TopBarAndSideBarLayout
 */
const TopBarAndSideBarLayout: FunctionComponent<PropsWithChildren<Props>> = ({
  children,
  sidebarItems,
  sidebarIdentity,
  identity,
  headerActions,
  mobileBottomBar,
}) => {
  const tChrome = useTranslations('routeChrome');
  const tCommon = useTranslations('common');
  const theme = useTheme();
  const title = useRouteTitle();
  const [mobileOpen, setMobileOpen] = useState(false);

  const anchor = theme.direction === 'rtl' ? 'right' : 'left';

  const headerControls = (
    <Stack direction="row" sx={{ alignItems: 'center', gap: 0.5 }}>
      {identity}
      {headerActions}
      {/* DarkModeToggleButton subscribes to useColorScheme() on its own — this layout never re-renders on a theme flip */}
      <DarkModeToggleButton />
    </Stack>
  );

  return (
    <Stack sx={{ minHeight: '100vh' }}>
      <TopBar
        startNode={
          <AppIconButton
            icon="menu"
            title={tCommon('open_sidebar')}
            onClick={() => setMobileOpen(true)}
            sx={{ display: { xs: 'inline-flex', md: 'none' } }}
          />
        }
        title={title ?? ''}
        align="start"
        endNode={headerControls}
      />

      <Stack direction="row" sx={{ flexGrow: 1, pt: { xs: TOP_BAR_MOBILE_HEIGHT, md: TOP_BAR_DESKTOP_HEIGHT } }}>
        <SideBar
          items={sidebarItems}
          identity={sidebarIdentity}
          anchor={anchor}
          mobileOpen={mobileOpen}
          onMobileClose={() => setMobileOpen(false)}
        />

        <Stack component="main" sx={{ flexGrow: 1, minWidth: 0, padding: 2 }}>
          <ErrorBoundary
            name="Content"
            title={tChrome('error_title')}
            body={tChrome('error_body')}
            retryLabel={tChrome('error_retry')}
          >
            <RouteFadeIn>{children}</RouteFadeIn>
          </ErrorBoundary>
        </Stack>
      </Stack>

      {mobileBottomBar && <Box sx={{ display: { xs: 'block', md: 'none' } }}>{mobileBottomBar(() => setMobileOpen(true))}</Box>}
    </Stack>
  );
};

export default TopBarAndSideBarLayout;
