import React, {
  useMemo,
  useEffect,
  useState,
  useCallback,
  Suspense,
} from "react";
import { App, Layout, message } from "antd";
import { useSelector } from "react-redux";
import {
  Route,
  Routes,
  useNavigate,
  useLocation,
  Navigate,
} from "react-router-dom";
import { Content } from "antd/es/layout/layout";
import { hasToken, getTokenInfo } from "@/utils";
import store from "@/store";
import { LayoutSider, LayoutHeader } from "./components";
import { RootState } from "@/store";
import { RouteType } from "./types";
import { DEFAULT_ADMIN_MENU, DEFAULT_MENU } from "./constants";
import "./index.scss";
import { MemoSpinLoding } from "@/components";
import { isNaN } from "lodash";

const NotFound = React.lazy(() => import("@/components/NotFound"));

export default function CustomLayout() {
  const navigate = useNavigate();
  const location = useLocation();
  const [activeMenuKey, setActiveMenuKey] = useState("/");
  const baseStore = useSelector<RootState, RootState["base"]>(
    (state) => state.base
  );
  const menuList = useMemo<RouteType[]>(() => {
    const list = baseStore.userInfo?.user.isAdmin
      ? [...DEFAULT_MENU, ...DEFAULT_ADMIN_MENU]
      : [...DEFAULT_MENU];

    function deep(v: RouteType[], parent?: RouteType) {
      const stack: RouteType[] = [];
      v.forEach((item) => {
        const { child = [], ...rest } = item;

        if (!!parent) {
          rest.key = parent.key + rest.key;
          rest.parent = {
            key: parent.key,
            label: parent.label,
          };
        }

        stack.push(rest);

        if (!!child.length) {
          stack.push(...deep(child, item));
        }
      });
      return stack;
    }

    return deep(list);
  }, [baseStore.userInfo]);
  const [curMenu, setCurMenu] = useState<null | RouteType>(null);

  useEffect(() => {
    if (!hasToken()) {
      message.open({
        type: "warning",
        content: "登录失效!",
        duration: 4,
      });

      navigate("/login", {
        replace: true,
      });
    } else {
      store.dispatch({ type: "setUserInfo", payload: getTokenInfo() });
    }
  }, [navigate]);

  /**
   * 初始化菜单选中状态
   */
  const getActiveMenu = useCallback(() => {
    const split = location.pathname.split("/").slice(1);
    const pMenu = "/" + split[0];
    if (split.length > 1) {
      const pathname = split
        .map((i) => (!isNaN(Number(i)) ? ":id" : i))
        .join("/");
      setCurMenu(menuList.find((i) => i.key === `/${pathname}`) as RouteType);
    } else {
      setCurMenu(menuList.find((i) => i.key === pMenu) as RouteType);
    }
    setActiveMenuKey(pMenu);
  }, [location, menuList]);

  useEffect(() => {
    getActiveMenu();
  }, [getActiveMenu]);

  const handleMenu = useCallback(
    (item: Partial<RouteType>) => {
      const path = item?.key as string;

      setActiveMenuKey(path);
      navigate(path);
    },
    [setActiveMenuKey, navigate]
  );

  return (
    <App>
      <Layout hasSider className="layout">
        {/* 菜单 */}
        <LayoutSider
          selectedKeys={[activeMenuKey]}
          items={menuList.filter((i) => !i.hide)}
          onClick={handleMenu}
        />

        <Layout style={{ marginLeft: 220 }}>
          {/* 头部 */}
          <LayoutHeader menu={curMenu} />

          {/* 主体 */}
          <Content
            style={{
              margin: "15px",
              overflow: "initial",
              position: "relative",
              background: "#ffffff",
              padding: 20,
              borderRadius: 4,
            }}
          >
            <Suspense fallback={<MemoSpinLoding />}>
              <Routes>
                <Route path="/" element={<Navigate to="/weapon" />} />
                {menuList.map((menu) => (
                  <Route
                    key={menu.key}
                    path={menu.key}
                    Component={menu.component}
                  />
                ))}
                <Route path="*" Component={NotFound} />
              </Routes>
            </Suspense>
          </Content>
        </Layout>
      </Layout>
    </App>
  );
}
