import {
  DndContext,
  KeyboardSensor,
  PointerSensor,
  closestCenter,
  useSensor,
  useSensors,
} from "@dnd-kit/core";
import {
  SortableContext,
  sortableKeyboardCoordinates,
  useSortable,
} from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";
import {
  Box,
  List,
  Menu,
  MenuItem,
  Paper,
  SvgIcon,
  ThemeProvider,
} from "@mui/material";
import dayjs from "dayjs";
import relativeTime from "dayjs/plugin/relativeTime";
import type { CSSProperties } from "react";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { useTranslation } from "react-i18next";
import { Outlet, useNavigate } from "react-router";
import { SWRConfig } from "swr";

import iconDark from "@/assets/image/icon_dark.svg?react";
import iconLight from "@/assets/image/icon_light.svg?react";
import LogoSvg from "@/assets/image/logo.svg?react";
import { BaseErrorBoundary } from "@/components/base";
import { LayoutItem } from "@/components/layout/layout-item";
import { LayoutTraffic } from "@/components/layout/layout-traffic";
import { NoticeManager } from "@/components/layout/notice-manager";
import { UpdateButton } from "@/components/layout/update-button";
import { WindowControls } from "@/components/layout/window-controller";
import { useI18n } from "@/hooks/use-i18n";
import { useVerge } from "@/hooks/use-verge";
import { useWindowDecorations } from "@/hooks/use-window";
import { useThemeMode } from "@/services/states";
import getSystem from "@/utils/get-system";

import {
  useAppInitialization,
  useCustomTheme,
  useLayoutEvents,
  useLoadingOverlay,
  useNavMenuOrder,
} from "./_layout/hooks";
import { handleNoticeMessage } from "./_layout/utils";
import { navItems } from "./_routers";

import "dayjs/locale/ru";
import "dayjs/locale/zh-cn";

export const portableFlag = false;

type NavItem = (typeof navItems)[number];

type MenuContextPosition = { top: number; left: number };

interface SortableNavMenuItemProps {
  item: NavItem;
  label: string;
}

const SortableNavMenuItem = ({ item, label }: SortableNavMenuItemProps) => {
  const {
    attributes,
    listeners,
    setNodeRef,
    transform,
    transition,
    isDragging,
  } = useSortable({
    id: item.path,
  });

  const style: CSSProperties = {
    transform: CSS.Transform.toString(transform),
    transition,
  };

  if (isDragging) {
    style.zIndex = 100;
  }

  return (
    <LayoutItem
      to={item.path}
      icon={item.icon}
      sortable={{
        setNodeRef,
        attributes,
        listeners,
        style,
        isDragging,
      }}
    >
      {label}
    </LayoutItem>
  );
};

dayjs.extend(relativeTime);

const OS = getSystem();

const Layout = () => {
  const mode = useThemeMode();
  const isDark = mode !== "light";
  const { t } = useTranslation();
  const { theme } = useCustomTheme();
  const { verge, mutateVerge, patchVerge } = useVerge();
  const { language } = verge ?? {};
  const navCollapsed = verge?.collapse_navbar ?? false;
  const { switchLanguage } = useI18n();
  const navigate = useNavigate();
  const themeReady = useMemo(() => Boolean(theme), [theme]);

  const [menuUnlocked, setMenuUnlocked] = useState(false);
  const [menuContextPosition, setMenuContextPosition] =
    useState<MenuContextPosition | null>(null);

  const windowControlsRef = useRef<any>(null);
  const { decorated } = useWindowDecorations();

  const sensors = useSensors(
    useSensor(PointerSensor, {
      activationConstraint: {
        distance: 6,
      },
    }),
    useSensor(KeyboardSensor, {
      coordinateGetter: sortableKeyboardCoordinates,
    }),
  );

  const handleMenuOrderOptimisticUpdate = useCallback(
    (order: string[]) => {
      mutateVerge(
        (prev) => (prev ? { ...prev, menu_order: order } : prev),
        false,
      );
    },
    [mutateVerge],
  );

  const handleMenuOrderPersist = useCallback(
    (order: string[]) => patchVerge({ menu_order: order }),
    [patchVerge],
  );

  const {
    menuOrder,
    navItemMap,
    handleMenuDragEnd,
    isDefaultOrder,
    resetMenuOrder,
  } = useNavMenuOrder({
    enabled: menuUnlocked,
    items: navItems,
    storedOrder: verge?.menu_order,
    onOptimisticUpdate: handleMenuOrderOptimisticUpdate,
    onPersist: handleMenuOrderPersist,
  });

  const handleMenuContextMenu = useCallback(
    (event: React.MouseEvent<HTMLElement>) => {
      event.preventDefault();
      event.stopPropagation();
      setMenuContextPosition({ top: event.clientY, left: event.clientX });
    },
    [],
  );

  const handleMenuContextClose = useCallback(() => {
    setMenuContextPosition(null);
  }, []);

  const handleResetMenuOrder = useCallback(() => {
    setMenuContextPosition(null);
    void resetMenuOrder();
  }, [resetMenuOrder]);

  const handleUnlockMenu = useCallback(() => {
    setMenuUnlocked(true);
    setMenuContextPosition(null);
  }, []);

  const handleLockMenu = useCallback(() => {
    setMenuUnlocked(false);
    setMenuContextPosition(null);
  }, []);

  const handleToggleNavCollapsed = useCallback(() => {
    setMenuContextPosition(null);
    void patchVerge({ collapse_navbar: !navCollapsed });
  }, [navCollapsed, patchVerge]);

  const customTitlebar = useMemo(
    () =>
      !decorated ? (
        <div className="the_titlebar" data-tauri-drag-region="true">
          <WindowControls ref={windowControlsRef} />
        </div>
      ) : null,
    [decorated],
  );

  useLoadingOverlay(themeReady);
  useAppInitialization();

  const handleNotice = useCallback(
    (payload: [string, string]) => {
      const [status, msg] = payload;
      try {
        handleNoticeMessage(status, msg, t, navigate);
      } catch (error) {
        console.error("[通知处理] 失败:", error);
      }
    },
    [t, navigate],
  );

  useLayoutEvents(handleNotice);

  useEffect(() => {
    if (language) {
      dayjs.locale(language === "zh" ? "zh-cn" : language);
      switchLanguage(language);
    }
  }, [language, switchLanguage]);

  if (!themeReady) {
    return (
      <div
        style={{
          width: "100vw",
          height: "100vh",
          background: mode === "light" ? "#fff" : "#181a1b",
          transition: "background 0.2s",
          display: "flex",
          alignItems: "center",
          justifyContent: "center",
          color: mode === "light" ? "#333" : "#fff",
        }}
      ></div>
    );
  }

  return (
    <SWRConfig
      value={{
        errorRetryCount: 3,
        // TODO remove the 5000ms
        errorRetryInterval: 5000,
        onError: (error, key) => {
          // FIXME the condition should not be handle gllobally
          if (key !== "getAutotemProxy") {
            console.error(`SWR Error for ${key}:`, error);
            return;
          }

          // FIXME we need a better way to handle the retry when first booting app
          const silentKeys = [
            "getVersion",
            "getClashConfig",
            "getAutotemProxy",
          ];
          if (silentKeys.includes(key)) return;

          console.error(`[SWR Error] Key: ${key}, Error:`, error);
        },
        dedupingInterval: 2000,
      }}
    >
      <ThemeProvider theme={theme}>
        {/* 左侧底部窗口控制按钮 */}
        <NoticeManager position={verge?.notice_position} />
        <div
          style={{
            animation: "fadeIn 0.5s",
            WebkitAnimation: "fadeIn 0.5s",
          }}
        />
        <style>
          {`
            @keyframes fadeIn {
              from { opacity: 0; }
              to { opacity: 1; }
            }
          `}
        </style>
        <Paper
          square
          elevation={0}
          className={`${OS} layout${navCollapsed ? " layout--nav-collapsed" : ""}`}
          style={{
            borderTopLeftRadius: "0px",
            borderTopRightRadius: "0px",
          }}
          onContextMenu={(e) => {
            if (
              OS === "windows" &&
              !["input", "textarea"].includes(
                e.currentTarget.tagName.toLowerCase(),
              ) &&
              !e.currentTarget.isContentEditable
            ) {
              e.preventDefault();
            }
          }}
          sx={[
            ({ palette }) => ({ bgcolor: palette.background.paper }),
            OS === "linux"
              ? {
                  borderRadius: "8px",
                  width: "100vw",
                  height: "100vh",
                }
              : {},
          ]}
        >
          {/* Custom titlebar - rendered only when decorated is false, memoized for performance */}
          {customTitlebar}

          <div className="layout-content">
            <div className="layout-content__left">
              <div className="the-logo" data-tauri-drag-region="false">
                <div
                  data-tauri-drag-region="true"
                  style={{
                    height: "27px",
                    display: "flex",
                    justifyContent: "space-between",
                  }}
                >
                  <SvgIcon
                    component={isDark ? iconDark : iconLight}
                    style={{
                      height: "36px",
                      width: "36px",
                      marginTop: "-3px",
                      marginRight: "5px",
                      marginLeft: "-3px",
                    }}
                    inheritViewBox
                  />
                  <LogoSvg fill={isDark ? "white" : "black"} />
                </div>
                <UpdateButton className="the-newbtn" />
              </div>

              {menuUnlocked && (
                <Box
                  sx={(theme) => ({
                    px: 1.5,
                    py: 0.75,
                    mx: "auto",
                    mb: 1,
                    maxWidth: 250,
                    borderRadius: 1.5,
                    fontSize: 12,
                    fontWeight: 600,
                    textAlign: "center",
                    color: theme.palette.warning.contrastText,
                    bgcolor:
                      theme.palette.mode === "light"
                        ? theme.palette.warning.main
                        : theme.palette.warning.dark,
                  })}
                >
                  {t("layout.components.navigation.menu.reorderMode")}
                </Box>
              )}

              {menuUnlocked ? (
                <DndContext
                  sensors={sensors}
                  collisionDetection={closestCenter}
                  onDragEnd={handleMenuDragEnd}
                >
                  <SortableContext items={menuOrder}>
                    <List
                      className="the-menu"
                      onContextMenu={handleMenuContextMenu}
                    >
                      {menuOrder.map((path) => {
                        const item = navItemMap.get(path);
                        if (!item) {
                          return null;
                        }
                        return (
                          <SortableNavMenuItem
                            key={item.path}
                            item={item}
                            label={t(item.label)}
                          />
                        );
                      })}
                    </List>
                  </SortableContext>
                </DndContext>
              ) : (
                <List
                  className="the-menu"
                  onContextMenu={handleMenuContextMenu}
                >
                  {menuOrder.map((path) => {
                    const item = navItemMap.get(path);
                    if (!item) {
                      return null;
                    }
                    return (
                      <LayoutItem
                        key={item.path}
                        to={item.path}
                        icon={item.icon}
                      >
                        {t(item.label)}
                      </LayoutItem>
                    );
                  })}
                </List>
              )}

              <Menu
                open={Boolean(menuContextPosition)}
                onClose={handleMenuContextClose}
                anchorReference="anchorPosition"
                anchorPosition={
                  menuContextPosition
                    ? {
                        top: menuContextPosition.top,
                        left: menuContextPosition.left,
                      }
                    : undefined
                }
                transitionDuration={200}
                slotProps={{
                  list: {
                    sx: { py: 0.5 },
                  },
                }}
              >
                <MenuItem onClick={handleToggleNavCollapsed} dense>
                  {navCollapsed
                    ? t("layout.components.navigation.menu.expandNavBar")
                    : t("layout.components.navigation.menu.collapseNavBar")}
                </MenuItem>
                <MenuItem
                  onClick={menuUnlocked ? handleLockMenu : handleUnlockMenu}
                  dense
                >
                  {menuUnlocked
                    ? t("layout.components.navigation.menu.lock")
                    : t("layout.components.navigation.menu.unlock")}
                </MenuItem>
                <MenuItem
                  onClick={handleResetMenuOrder}
                  dense
                  disabled={isDefaultOrder}
                >
                  {t("layout.components.navigation.menu.restoreDefaultOrder")}
                </MenuItem>
              </Menu>

              <div className="the-traffic">
                <LayoutTraffic />
              </div>
            </div>

            <div className="layout-content__right">
              <div className="the-bar"></div>
              <div className="the-content">
                <BaseErrorBoundary>
                  <Outlet />
                </BaseErrorBoundary>
              </div>
            </div>
          </div>
        </Paper>
      </ThemeProvider>
    </SWRConfig>
  );
};

export default Layout;
