import {RouteObject, createBrowserRouter} from 'react-router-dom';
import {
  HOME_PATH,
  MAIN_PATH,
  MENU_PATH,
  ROLE_PATH,
  USER_PATH,
  STORAGE_PATH,
  GOODS_PATH,
  PDA_MENU_PATH,
  CONTAINER_PATH,
  MATTER_PATH,
  RAW_IN_STREAM_PATH,
  RAW_OUT_STREAM_PATH,
  SEMI_REPORT_PATH,
  SEMI_DRAW_PATH,
  SEMI_IN_STREAM_PATH,
  SEMI_OUT_STREAM_PATH,
  LOGIN_PATH,
  NO_PERMISSION_PATH,
  FINISH_PRODUCT_IN_STREAM_PATH,
  FINISH_PRODUCT_OUT_STREAM_PATH,
  DEAD_PRODUCT_PATH,
  RESERVE_WARNING_PATH,
  QUALITY_PATH,
  PURCHASE_PATH,
  MATERIAL_BIND_PATH,
  STOCK_PATH,
  DICTIONARY_PATH,
  GS_INTERFACE_LOG_PATH,
  PRODUCTION_REQUISITION_PATH,
  SELL_ORDER_PATH,
  RELOCAT_ORDER_PATH,
  PRODUCT_REPORT_PATH,
  ORDER_LOG_PATH,
  INVENTORY_PATH,
  GS_ERROR_LOG_PATH,
  OTHER_IN_PATH,
  OTHER_OUT_PATH,
  SCREEN_PURCHASE_PATH,
  DELIVER_TRACE_PATH,
} from './name';
import {
  Container,
  Goods,
  Matter,
  Menu,
  NoPermision,
  NotFound,
  Pda,
  RawInStream,
  RawOutStream,
  Role,
  SemiDraw,
  SemiInStream,
  SemiOutStream,
  SemiReport,
  User,
  Storage,
  ProductInStream,
  ProductOutStream,
  ReserveWarning,
  Quality,
  Stock,
  Dictionary,
  GSInterfaceLog,
  ProductionRequisitionOrder,
  RelcationOrder,
  ProductReport,
  DeadProduct,
  PurchaseOrder,
  MaterialBind,
  SellOrder,
  OrderDeleteLog,
  Inventory,
  Login,
  GSErrorLog,
  OtherIn,
  OtherOut,
  ScreenPurchase,
  DeliverTraces,
} from './routes';
import Main from '@pages/main';
import Home from '@pages/home';
import {userStore} from '@stores';
import {getSettings} from '@apis';
import {SettingsData} from '@models';

async function preloadSettings(url: string) {
  try {
    const {id} = userStore.getState();

    const result = await getSettings({userId: String(id), track: url});

    if (result.msg === '200') return new Map([[url, result.data]]);

    return new Map([[url, null]]);
  } catch (error) {
    return new Map([[url, null]]);
  }
}

async function preloadSettingsList(keys: string[]) {
  const data = await Promise.allSettled([
    preloadSettings(keys[0]),
    preloadSettings(keys[1]),
  ]);
  const map = new Map<string, SettingsData | null>();

  data.forEach(function (val, idx) {
    const key = keys[idx];

    if (val.status === 'fulfilled') {
      map.set(key, val.value.get(key) || null);
    } else {
      map.set(key, null);
    }
  });

  return map;
}

export const routes: RouteObject[] = [
  {path: LOGIN_PATH, element: <Login />},
  {
    path: HOME_PATH,
    element: <Home />,
  },
  {path: MAIN_PATH, element: <Main />},
  {
    path: MENU_PATH,
    element: <Menu />,
    async loader() {
      const keys = [MENU_PATH, '/menu_second_level'];

      return preloadSettingsList(keys);
    },
  },
  {
    path: ROLE_PATH,
    element: <Role />,
    async loader() {
      return await preloadSettings(ROLE_PATH);
    },
  },
  {
    path: USER_PATH,
    element: <User />,
    async loader() {
      return await preloadSettings(USER_PATH);
    },
  },
  {
    path: STORAGE_PATH,
    element: <Storage />,
    async loader() {
      return await preloadSettings(USER_PATH);
    },
  },
  {
    path: GOODS_PATH,
    element: <Goods />,
    async loader() {
      return await preloadSettings(GOODS_PATH);
    },
  },
  {
    path: PDA_MENU_PATH,
    element: <Pda />,
    async loader() {
      return await preloadSettings(PDA_MENU_PATH);
    },
  },
  {
    path: CONTAINER_PATH,
    element: <Container />,
    async loader() {
      const keys = [CONTAINER_PATH, '/container_scrap'];

      return preloadSettingsList(keys);
    },
  },
  {
    path: MATTER_PATH,
    element: <Matter />,
    async loader() {
      return await preloadSettings(MATTER_PATH);
    },
  },
  {
    path: QUALITY_PATH,
    element: <Quality />,
    async loader() {
      return await preloadSettings(QUALITY_PATH);
    },
  },
  {
    path: RAW_IN_STREAM_PATH,
    element: <RawInStream />,
    async loader() {
      return await preloadSettings(RAW_IN_STREAM_PATH);
    },
  },
  {
    path: RAW_OUT_STREAM_PATH,
    element: <RawOutStream />,
    async loader() {
      return await preloadSettings(RAW_OUT_STREAM_PATH);
    },
  },
  {
    path: SEMI_REPORT_PATH,
    element: <SemiReport />,
    async loader() {
      return await preloadSettings(SEMI_REPORT_PATH);
    },
  },
  {
    path: SEMI_DRAW_PATH,
    element: <SemiDraw />,
    async loader() {
      return await preloadSettings(SEMI_DRAW_PATH);
    },
  },
  {
    path: SEMI_IN_STREAM_PATH,
    element: <SemiInStream />,
    async loader() {
      return await preloadSettings(SEMI_IN_STREAM_PATH);
    },
  },
  {
    path: SEMI_OUT_STREAM_PATH,
    element: <SemiOutStream />,
    async loader() {
      return await preloadSettings(SEMI_OUT_STREAM_PATH);
    },
  },
  {
    path: FINISH_PRODUCT_IN_STREAM_PATH,
    element: <ProductInStream />,
    async loader() {
      return await preloadSettings(FINISH_PRODUCT_IN_STREAM_PATH);
    },
  },
  {
    path: FINISH_PRODUCT_OUT_STREAM_PATH,
    element: <ProductOutStream />,
    async loader() {
      return await preloadSettings(FINISH_PRODUCT_OUT_STREAM_PATH);
    },
  },
  {
    path: DEAD_PRODUCT_PATH,
    element: <DeadProduct />,
    async loader() {
      return await preloadSettings(DEAD_PRODUCT_PATH);
    },
  },
  {
    path: RESERVE_WARNING_PATH,
    element: <ReserveWarning />,
    async loader() {
      return await preloadSettings(RESERVE_WARNING_PATH);
    },
  },
  {
    path: PURCHASE_PATH,
    element: <PurchaseOrder />,
    async loader() {
      return await preloadSettings(PURCHASE_PATH);
    },
  },
  {
    path: MATERIAL_BIND_PATH,
    element: <MaterialBind />,
    async loader() {
      return await preloadSettings(MATERIAL_BIND_PATH);
    },
  },
  {
    path: STOCK_PATH,
    element: <Stock />,
    async loader() {
      return await preloadSettings(STOCK_PATH);
    },
  },
  {
    path: DICTIONARY_PATH,
    element: <Dictionary />,
    async loader() {
      return await preloadSettings(DICTIONARY_PATH);
    },
  },
  {
    path: GS_INTERFACE_LOG_PATH,
    element: <GSInterfaceLog />,
    async loader() {
      return await preloadSettings(GS_INTERFACE_LOG_PATH);
    },
  },
  {
    path: PRODUCTION_REQUISITION_PATH,
    element: <ProductionRequisitionOrder />,
    async loader() {
      return await preloadSettings(PRODUCTION_REQUISITION_PATH);
    },
  },
  {
    path: SELL_ORDER_PATH,
    element: <SellOrder />,
    async loader() {
      return await preloadSettings(SELL_ORDER_PATH);
    },
  },
  {
    path: RELOCAT_ORDER_PATH,
    element: <RelcationOrder />,
    async loader() {
      return await preloadSettings(RELOCAT_ORDER_PATH);
    },
  },
  {
    path: PRODUCT_REPORT_PATH,
    element: <ProductReport />,
    async loader() {
      return await preloadSettings(PRODUCT_REPORT_PATH);
    },
  },
  {
    path: ORDER_LOG_PATH,
    element: <OrderDeleteLog />,
    async loader() {
      return await preloadSettings(ORDER_LOG_PATH);
    },
  },
  {
    path: INVENTORY_PATH,
    element: <Inventory />,
    async loader() {
      return await preloadSettingsList([
        INVENTORY_PATH,
        '/inventory_log',
        '/inventory_detail',
      ]);
    },
  },
  {
    path: GS_ERROR_LOG_PATH,
    element: <GSErrorLog />,
    async loader() {
      return await preloadSettings(GS_ERROR_LOG_PATH);
    },
  },
  {
    path: OTHER_IN_PATH,
    element: <OtherIn />,
    async loader() {
      return await preloadSettings(OTHER_IN_PATH);
    },
  },
  {
    path: OTHER_OUT_PATH,
    element: <OtherOut />,
    async loader() {
      return await preloadSettings(OTHER_OUT_PATH);
    },
  },
  {
    path: SCREEN_PURCHASE_PATH,
    element: <ScreenPurchase />,
  },
  {
    path: DELIVER_TRACE_PATH,
    element: <DeliverTraces />,
    async loader() {
      return await preloadSettingsList([
        PRODUCTION_REQUISITION_PATH,
        '/deliver_sn',
      ]);
    },
  },
  {path: NO_PERMISSION_PATH, element: <NoPermision />},
  {path: '*', element: <NotFound />},
];

export const router = createBrowserRouter(routes);

export * from './name';
