import React, { useMemo, useEffect, Suspense, useState } from "react";
import { App, Layout } from "antd";
import { useSelector } from "react-redux";
import {
  Route,
  Routes,
  useNavigate,
  Navigate,
  useLocation,
} from "react-router-dom";
import { Content } from "antd/es/layout/layout";
import { hasToken, getTokenInfo, DageLoading } from "@dage/pc-components";
import store from "@/store";
import { LayoutMenu, LayoutHeader } from "./components";
import { RootState } from "@/store";
import LogoImage from "@/assets/images/logo.png";
import { DEFAULT_ADMIN_MENU, DEFAULT_MENU, DageRouteItem } from "@/router";
import "./index.scss";
import { findRouteByPath } from "./utils";
import { userApi } from "@/api";
import { getAuthorizedIds } from "@/utils";
import { YES_OR_NO } from "@/types";

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

export default function CustomLayout() {
  const navigate = useNavigate();
  const location = useLocation();
  const baseStore = useSelector<RootState, RootState["base"]>(
    (state) => state.base
  );
  const [curMeta, setCurMeta] = useState<null | DageRouteItem["meta"]>(null);
  const [menuList, setMenuList] = useState<DageRouteItem[]>([]);

  // 自定义 Content 样式
  const isCustomStyle = curMeta && curMeta.custom;
  const [menuLoading, setMenuLoading] = useState(false);

  const getPermissions = async () => {
    try {
      setMenuLoading(true);
      const data = await userApi.getRole(baseStore.userInfo!.user.roleId);
      const permissonIds = getAuthorizedIds(data.permission);
      const menus = filterAuthorizedRoutes(DEFAULT_MENU, permissonIds);
      setMenuList(menus);
      const target = getFirstPath(menus);
      target && navigate(target);
    } finally {
      setMenuLoading(false);
    }
  };

  useEffect(() => {
    if (!baseStore.userInfo) return;

    if (baseStore.userInfo?.user.isAdmin === YES_OR_NO.YES) {
      setMenuList([...DEFAULT_MENU, ...DEFAULT_ADMIN_MENU]);
    } else {
      getPermissions();
    }
  }, [baseStore]);

  useEffect(() => {
    if (!hasToken()) {
      navigate("/login", {
        replace: true,
      });
    } else {
      store.dispatch({ type: "setUserInfo", payload: getTokenInfo() });
    }
  }, []);

  useEffect(() => {
    const route = findRouteByPath(menuList, location.pathname);
    setCurMeta(route?.meta);
  }, [menuList, location]);

  return (
    <App>
      {menuLoading ? (
        <DageLoading />
      ) : (
        <Layout hasSider className="layout">
          {/* 菜单 */}
          <Layout.Sider
            width={220}
            style={{
              position: "fixed",
              top: 0,
              left: 0,
              bottom: 0,
              background: "#242424",
            }}
          >
            <div className="logo">
              <img draggable="false" alt="logo" src={LogoImage} />
            </div>

            <LayoutMenu
              className="layout-menu"
              theme="dark"
              inlineIndent={20}
              menuData={menuList}
            />
          </Layout.Sider>

          <Layout style={{ marginLeft: 220 }}>
            {/* 头部 */}
            <LayoutHeader menuData={menuList} />

            {/* 主体 */}
            <Content
              style={{
                margin: "15px",
                overflow: "auto",
                position: "relative",
                ...(isCustomStyle
                  ? {}
                  : {
                      background: "#ffffff",
                      padding: "0 25px 25px",
                      borderRadius: 4,
                    }),
              }}
            >
              <Suspense fallback={<DageLoading />}>
                {menuList.length && (
                  <Routes>
                    <Route
                      path="/"
                      element={
                        <Navigate
                          to={menuList[0].redirect || menuList[0].path}
                        />
                      }
                    />
                    {renderRoutes(menuList).map((menu) =>
                      menu.redirect ? (
                        <Route
                          key={menu.path}
                          path={menu.path}
                          element={<Navigate replace to={menu.redirect} />}
                        />
                      ) : (
                        <Route
                          key={menu.path}
                          path={menu.path}
                          Component={menu.Component}
                        />
                      )
                    )}
                    <Route path="*" Component={NotFound} />
                  </Routes>
                )}
              </Suspense>
            </Content>
          </Layout>
        </Layout>
      )}
    </App>
  );
}

function renderRoutes(routes: DageRouteItem[]) {
  function deep(v: DageRouteItem[]) {
    const stack: DageRouteItem[] = [];
    v.forEach((item) => {
      const { children = [], ...rest } = item;

      stack.push(rest);

      if (!!children.length) {
        stack.push(...deep(children));
      }
    });
    return stack;
  }

  return deep(routes);
}

function filterAuthorizedRoutes(routes: DageRouteItem[], permIds: number[]) {
  const filterRoutes = (routeList: DageRouteItem[]): DageRouteItem[] => {
    return routeList
      .map((route) => {
        const newRoute = { ...route };

        if (newRoute.children) {
          newRoute.children = filterRoutes(newRoute.children);
        }

        const shouldKeep = permIds.includes(route.mapId || -1);

        return shouldKeep ? newRoute : null;
      })
      .filter(Boolean) as DageRouteItem[];
  };

  return filterRoutes(routes);
}

function getFirstPath(menus: DageRouteItem[]): string | null {
  if (!menus.length) return null;

  const item = menus[0];
  if (item.children) {
    if (item.children.every((i) => i.hide)) return item.path;
    return getFirstPath(item.children);
  }
  return item.path;
}
