import { Layout } from 'antd';
import { useEffect, useMemo, useState } from 'react';
import { Outlet, useLocation, useNavigate, useSearchParams } from 'react-router-dom';
import { useGestureLayer, useGesturePageState, useSearchLayer } from '../../../layer';
import { useAppStore } from '../../../store';
import { useTokenAccess } from '../tokenAccess';
import { syncAppConfigFromServer, useAppConfig } from '../appConfig';
import { ChatRuntimeBridgeV2 } from '../ChatRuntimeBridgeV2';
import { useUnreadCounts } from '../chatV2/hooks/useUnreadCounts';
import { matchesShortcut, isTypingTarget, scrollToElement } from '../mainView/utils';
import { MainContent } from '../MainContent';
import { MainHeader } from '../MainHeader';
import { MainSidebar } from '../MainSidebar';
import { buildSearchOptions } from './buildSearchOptions';
import { MainLayoutContextProvider } from './MainLayoutContext';
import { useMainLayoutData } from './useMainLayoutData';
import '../MainLayout.css';
import {
  buildApiMenuItems,
  buildApisPath,
  buildChatMenuItems,
  buildChatPath,
  buildDocsMenuItems,
  buildDocsPath,
  buildPlanMenuItems,
  buildPlansPath,
  buildPlayMenuItems,
  buildPlayPath,
  buildSavedLayoutPath,
  DOCS_DEFAULT_FOLDER,
  PLAN_MENU_ANCHOR_IDS,
  renderSidebarIntro,
  resolveCurrentPageDescriptor,
  resolvePlanQuickFilterMenu,
  resolvePlayOpenKeys,
  resolveSavedLayoutIdFromMenuKey,
  resolveTopMenuPath,
  type ApiSectionKey,
  type ChatSectionKey,
  type PlanSectionKey,
  type PlaySidebarKey,
  type TopMenuKey,
} from '../routes';

function parseRoute(pathname: string): {
  topMenu: TopMenuKey;
  docsMenu: string;
  apiMenu: ApiSectionKey;
  planMenu: PlanSectionKey;
  chatMenu: ChatSectionKey;
  playMenu: PlaySidebarKey;
} {
  const segments = pathname.split('/').filter(Boolean);
  const [top, first, second] = segments;

  if (top === 'docs') {
    return {
      topMenu: 'docs',
      docsMenu: first || DOCS_DEFAULT_FOLDER,
      apiMenu: 'components',
      planMenu: 'all',
      chatMenu: 'live',
      playMenu: 'layout',
    };
  }

  if (top === 'apis' && (first === 'components' || first === 'widgets')) {
    return {
      topMenu: 'apis',
      docsMenu: DOCS_DEFAULT_FOLDER,
      apiMenu: first,
      planMenu: 'all',
      chatMenu: 'live',
      playMenu: 'layout',
    };
  }

  if (
    top === 'plans' &&
    (first === 'all' ||
      first === 'in-progress' ||
      first === 'done' ||
      first === 'error' ||
      first === 'release' ||
      first === 'release-review' ||
      first === 'board' ||
      first === 'charts' ||
      first === 'schedule' ||
      first === 'history' ||
      first === 'server-command')
  ) {
    return {
      topMenu: 'plans',
      docsMenu: DOCS_DEFAULT_FOLDER,
      apiMenu: 'components',
      planMenu: first,
      chatMenu: 'live',
      playMenu: 'layout',
    };
  }

  if (top === 'chat' && (first === 'live' || first === 'changes' || first === 'errors' || first === 'manage')) {
    return {
      topMenu: 'chat',
      docsMenu: DOCS_DEFAULT_FOLDER,
      apiMenu: 'components',
      planMenu: 'all',
      chatMenu: first,
      playMenu: 'layout',
    };
  }

  if (top === 'play' && first === 'layout') {
    return {
      topMenu: 'play',
      docsMenu: DOCS_DEFAULT_FOLDER,
      apiMenu: 'components',
      planMenu: 'all',
      chatMenu: 'live',
      playMenu: first,
    };
  }

  if (top === 'play' && first === 'layout-record' && second) {
    return {
      topMenu: 'play',
      docsMenu: DOCS_DEFAULT_FOLDER,
      apiMenu: 'components',
      planMenu: 'all',
      chatMenu: 'live',
      playMenu: `layout-record:${second}`,
    };
  }

  return {
    topMenu: 'plans',
    docsMenu: DOCS_DEFAULT_FOLDER,
    apiMenu: 'components',
    planMenu: 'all',
    chatMenu: 'live',
    playMenu: 'layout',
  };
}

function isRestrictedTopMenu(topMenu: TopMenuKey, hasAccess: boolean) {
  return !hasAccess && topMenu !== 'docs';
}

function resolveSidebarOpenKeys(
  topMenu: TopMenuKey,
  hasAccess: boolean,
  planMenu: PlanSectionKey,
  chatMenu: ChatSectionKey,
) {
  if (!hasAccess) {
    return ['docs-group'];
  }

  if (topMenu === 'docs') {
    return ['docs-group'];
  }

  if (topMenu === 'apis') {
    return ['api-group'];
  }

  if (topMenu === 'play') {
    return resolvePlayOpenKeys();
  }

  if (topMenu === 'plans') {
    return planMenu === 'server-command' ? ['server-group'] : ['plan-group'];
  }

  if (chatMenu === 'errors') {
    return ['app-log-group'];
  }

  return chatMenu === 'manage' ? ['chat-manage-group'] : ['codex-live-group'];
}

export function MainLayout() {
  const location = useLocation();
  const navigate = useNavigate();
  const [searchParams] = useSearchParams();
  const { setCurrentPage, setFocusedComponentId } = useAppStore();
  const { hasAccess } = useTokenAccess();
  const appConfig = useAppConfig();
  const { openSearch, setOptions: setSearchOptions } = useSearchLayer();
  const layoutData = useMainLayoutData();
  const routeState = useMemo(() => parseRoute(location.pathname), [location.pathname]);
  const [sidebarCollapsed, setSidebarCollapsed] = useState(false);
  const [contentExpanded, setContentExpanded] = useState(false);
  const [isMobileViewport, setIsMobileViewport] = useState(false);
  const [sidebarOpenKeys, setSidebarOpenKeys] = useState<string[]>(
    resolveSidebarOpenKeys(routeState.topMenu, hasAccess, routeState.planMenu, routeState.chatMenu),
  );
  const [activePlanQuickFilter, setActivePlanQuickFilter] = useState<
    'working' | 'release-pending-main' | 'automation-failed' | null
  >(routeState.planMenu === 'release' ? 'release-pending-main' : null);
  const [planQuickFilterRequestKey, setPlanQuickFilterRequestKey] = useState(routeState.planMenu === 'release' ? 1 : 0);
  const { componentSampleEntries, widgetSampleEntries, componentSamples, widgetSamples, docsDocuments, savedLayouts, setSavedLayouts, docFolders } = layoutData;
  const { chatUnreadCount } = useUnreadCounts();

  useEffect(() => {
    void syncAppConfigFromServer();
  }, []);

  useEffect(() => {
    const mediaQuery = window.matchMedia('(max-width: 768px)');
    const updateViewport = () => {
      setIsMobileViewport(mediaQuery.matches);
    };

    updateViewport();
    mediaQuery.addEventListener('change', updateViewport);

    return () => {
      mediaQuery.removeEventListener('change', updateViewport);
    };
  }, []);

  useEffect(() => {
    if (!isMobileViewport) {
      setSidebarCollapsed(false);
      return;
    }

    setSidebarCollapsed(routeState.topMenu !== 'docs');
  }, [isMobileViewport, routeState.topMenu]);

  useEffect(() => {
    setSidebarOpenKeys(resolveSidebarOpenKeys(routeState.topMenu, hasAccess, routeState.planMenu, routeState.chatMenu));
  }, [hasAccess, routeState.chatMenu, routeState.planMenu, routeState.topMenu]);

  useEffect(() => {
    if (docFolders.length > 0 && routeState.topMenu === 'docs' && !docFolders.includes(routeState.docsMenu)) {
      navigate(buildDocsPath(docFolders[0]), { replace: true });
    }
  }, [docFolders, navigate, routeState.docsMenu, routeState.topMenu]);

  useEffect(() => {
    const savedLayoutId = resolveSavedLayoutIdFromMenuKey(routeState.playMenu);

    if (savedLayoutId && !savedLayouts.some((record) => record.id === savedLayoutId)) {
      navigate(buildPlayPath('layout'), { replace: true });
    }
  }, [navigate, routeState.playMenu, savedLayouts]);

  useEffect(() => {
    if (!isRestrictedTopMenu(routeState.topMenu, hasAccess)) {
      return;
    }

    navigate(`${buildDocsPath(DOCS_DEFAULT_FOLDER)}${location.search}`, { replace: true });
  }, [hasAccess, location.search, navigate, routeState.topMenu]);

  useEffect(() => {
    if (routeState.topMenu !== 'plans') {
      setActivePlanQuickFilter(null);
      return;
    }

    if (routeState.planMenu === 'release') {
      setActivePlanQuickFilter('release-pending-main');
      return;
    }

    setActivePlanQuickFilter((current) => (current === 'working' || current === 'automation-failed' ? current : null));
  }, [routeState.planMenu, routeState.topMenu]);

  useGesturePageState('anyway');
  useGestureLayer({
    id: 'main-layout',
    enabled: !(isMobileViewport && routeState.topMenu === 'docs' && routeState.docsMenu === 'worklogs'),
    gestures: [
      {
        id: 'mobile-top-right-pull-alert',
        activeStates: ['anyway'],
        mobileOnly: true,
        trigger: 'pull-down-top-right',
        onTrigger: () => {
          openSearch();
        },
      },
      {
        id: 'mobile-middle-right-search-window',
        activeStates: ['anyway'],
        mobileOnly: true,
        trigger: 'pull-left-middle-right',
        onTrigger: () => {
          openSearch('window');
        },
      },
    ],
  });

  useEffect(() => {
    const handleWindowKeyDown = (event: KeyboardEvent) => {
      if (event.repeat || isTypingTarget(event.target)) {
        return;
      }

      if (matchesShortcut(event, appConfig.gestureShortcuts.openWindowSearch)) {
        event.preventDefault();
        openSearch('window');
        return;
      }

      if (matchesShortcut(event, appConfig.gestureShortcuts.openSearch)) {
        event.preventDefault();
        openSearch();
      }
    };

    window.addEventListener('keydown', handleWindowKeyDown);

    return () => {
      window.removeEventListener('keydown', handleWindowKeyDown);
    };
  }, [appConfig.gestureShortcuts.openSearch, appConfig.gestureShortcuts.openWindowSearch, openSearch]);

  const selectedDocs = useMemo(
    () => docsDocuments.filter((document) => document.folder === routeState.docsMenu),
    [docsDocuments, routeState.docsMenu],
  );

  const searchOptions = useMemo(
    () =>
      buildSearchOptions({
        componentSamples,
        widgetSamples,
        docFolders,
        docsDocuments,
        hasAccess,
        navigateTo: (path) => {
          navigate(path);
        },
        setFocusedComponentId,
        requestPlanQuickFilter: (filter) => {
          setActivePlanQuickFilter(filter);
          setPlanQuickFilterRequestKey((previous) => previous + 1);
        },
      }),
    [componentSamples, docFolders, docsDocuments, hasAccess, navigate, setFocusedComponentId, widgetSamples],
  );

  useEffect(() => {
    setSearchOptions(searchOptions);
  }, [searchOptions, setSearchOptions]);

  useEffect(() => {
    setCurrentPage(
      resolveCurrentPageDescriptor({
        topMenu: routeState.topMenu,
        docsMenu: routeState.docsMenu,
        apiMenu: routeState.apiMenu,
        planMenu: routeState.planMenu,
        chatMenu: routeState.chatMenu,
        playMenu: routeState.playMenu,
        savedLayouts,
      }),
    );
  }, [routeState, savedLayouts, setCurrentPage]);

  const currentDocsFolder = docFolders.includes(routeState.docsMenu) ? routeState.docsMenu : docFolders[0] ?? DOCS_DEFAULT_FOLDER;
  const sidebarIntro = renderSidebarIntro(routeState.topMenu);
  const apiMenuItems = useMemo(() => buildApiMenuItems(), []);
  const docsMenuItems = useMemo(() => buildDocsMenuItems(docFolders), [docFolders]);
  const planMenuItems = useMemo(() => buildPlanMenuItems(hasAccess), [hasAccess]);
  const chatMenuItems = useMemo(() => buildChatMenuItems(hasAccess, chatUnreadCount), [chatUnreadCount, hasAccess]);
  const playMenuItems = useMemo(() => buildPlayMenuItems(savedLayouts), [savedLayouts]);
  const showInlineMobileDocsSidebar = isMobileViewport && routeState.topMenu === 'docs';
  const initialSelectedPlanId = Number(searchParams.get('planId'));
  const initialSelectedWorkId = searchParams.get('workId');

  return (
    <MainLayoutContextProvider
      value={{
        topMenu: routeState.topMenu,
        selectedDocsMenu: routeState.docsMenu,
        selectedApiMenu: routeState.apiMenu,
        selectedPlanMenu: routeState.planMenu,
        selectedChatMenu: routeState.chatMenu,
        selectedPlayMenu: routeState.playMenu,
        activePlanQuickFilter,
        planQuickFilterRequestKey,
        initialSelectedPlanId: Number.isFinite(initialSelectedPlanId) ? initialSelectedPlanId : null,
        initialSelectedWorkId,
        selectedDocs,
        docsDocuments,
        componentSampleEntries,
        widgetSampleEntries,
        componentSamples,
        widgetSamples,
        savedLayouts,
        setSavedLayouts,
        searchOptions,
      }}
    >
      <Layout className="app-shell app-shell--docs-api">
        <ChatRuntimeBridgeV2 />
        {contentExpanded ? null : (
          <MainHeader
            activeTopMenu={routeState.topMenu}
            sidebarCollapsed={sidebarCollapsed}
            contentExpanded={contentExpanded}
            isMobileViewport={isMobileViewport}
            onToggleSidebar={() => {
              setSidebarCollapsed((previous) => !previous);
            }}
            onToggleContentExpanded={() => {
              setContentExpanded((previous) => !previous);
            }}
            onChangeTopMenu={(menu) => {
              navigate(resolveTopMenuPath(menu, currentDocsFolder));
              setSidebarCollapsed(false);
            }}
            onOpenPlanQuickFilter={(filter) => {
              const targetPlanMenu = resolvePlanQuickFilterMenu(filter);
              setActivePlanQuickFilter(filter);
              setPlanQuickFilterRequestKey((previous) => previous + 1);
              navigate(buildPlansPath(targetPlanMenu));
              setSidebarCollapsed(isMobileViewport);
              scrollToElement(PLAN_MENU_ANCHOR_IDS[targetPlanMenu] ?? 'plan-menu-all');
            }}
          />
        )}

        <Layout>
          {contentExpanded || (isMobileViewport && sidebarCollapsed && !showInlineMobileDocsSidebar) ? null : (
            <MainSidebar
              activeTopMenu={routeState.topMenu}
              hasAccess={hasAccess}
              sidebarCollapsed={sidebarCollapsed}
              isMobileViewport={isMobileViewport}
              mobileInline={showInlineMobileDocsSidebar}
              openKeys={sidebarOpenKeys}
              apiMenuItems={apiMenuItems}
              docsMenuItems={docsMenuItems}
              planMenuItems={planMenuItems}
              chatMenuItems={chatMenuItems}
              playMenuItems={playMenuItems}
              selectedApiMenu={routeState.apiMenu}
              selectedDocsMenu={routeState.docsMenu}
              selectedPlanMenu={routeState.planMenu}
              selectedChatMenu={routeState.chatMenu}
              selectedPlayMenu={routeState.playMenu}
              onOpenKeysChange={setSidebarOpenKeys}
              onSelectApiMenu={(key) => {
                navigate(buildApisPath(key as ApiSectionKey));
                if (isMobileViewport) {
                  setSidebarCollapsed(true);
                }
              }}
              onSelectDocsMenu={(key) => {
                navigate(buildDocsPath(key));
                if (isMobileViewport && !showInlineMobileDocsSidebar) {
                  setSidebarCollapsed(true);
                }
              }}
              onSelectPlanMenu={(key) => {
                setActivePlanQuickFilter(key === 'release' ? 'release-pending-main' : null);
                setPlanQuickFilterRequestKey((previous) => previous + 1);
                navigate(buildPlansPath(key));
                if (isMobileViewport) {
                  setSidebarCollapsed(true);
                }
              }}
              onSelectChatMenu={(key) => {
                navigate(buildChatPath(key));
                if (isMobileViewport) {
                  setSidebarCollapsed(true);
                }
              }}
              onSelectPlayMenu={(key) => {
                const savedLayoutId = resolveSavedLayoutIdFromMenuKey(key);
                navigate(savedLayoutId ? buildSavedLayoutPath(savedLayoutId) : buildPlayPath(key as 'layout'));
                if (isMobileViewport) {
                  setSidebarCollapsed(true);
                }
              }}
              introColor={sidebarIntro.color}
              introTag={sidebarIntro.tag}
              introDescription={sidebarIntro.description}
            />
          )}

          {isMobileViewport && !sidebarCollapsed && !showInlineMobileDocsSidebar ? null : (
            <MainContent contentExpanded={contentExpanded} onToggleContentExpanded={() => setContentExpanded((previous) => !previous)}>
              <Outlet />
            </MainContent>
          )}
        </Layout>
      </Layout>
    </MainLayoutContextProvider>
  );
}
