import { PageID } from "codes/page";
import LoadingScreen from "components/LoadingScreen";
import { AppContextProvider } from "contexts/AppContext";
import useAuth from "hooks/useAuth";
import DashboardLayout from "layouts/dashbord";
import SimpleLayout from "layouts/simple";
import { ElementType, Suspense, lazy, useMemo } from "react";
import { RouteObject, useRoutes } from "react-router-dom";
import { getRoute } from "./path";

const Loadable = (Component: ElementType) => (props: any) => {
  return (
    <Suspense fallback={<LoadingScreen />}>
      <Component {...props} />
    </Suspense>
  );
};

const CommonRoutes = (): RouteObject => ({
  element: <SimpleLayout />,
  children: [
    {
      path: getRoute(PageID.APP_PRIVACY_POLICY),
      element: <PrivacyPolicy />,
    },
  ],
});

const AuthRoutes = (): RouteObject => ({
  element: <SimpleLayout />,
  children: [
    {
      path: getRoute(PageID.LOGIN),
      element: <Login />,
    },
    {
      path: getRoute(PageID.LOGOUT),
      element: <Logout />,
    },
    {
      path: getRoute(PageID.CLEAR_CHANGE_CONTRACT),
      element: <ClearContract />,
    },
  ],
});

const AppRoutes = (): RouteObject => ({
  element: (
    <AppContextProvider>
      <SimpleLayout />
    </AppContextProvider>
  ),
  children: [
    {
      path: getRoute(PageID.APP_RECEIPT_ISSUING_ORDER_INDEX),
      element: <ReceiptIssuingOrder />,
    },
    {
      path: getRoute(PageID.APP_RECEIPT_ISSUING_ORDER_MAIL_ORDER),
      element: <MailOrder />,
    },
    {
      path: getRoute(PageID.APP_RECEIPT_ISSUING_ORDER_EMAIL_ORDER),
      element: <EmailOrder />,
    },
  ],
});

const DashboardRoutes = (): RouteObject => {
  const { canAccess } = useAuth();

  const allChildren = [
    {
      pageId: PageID.NONE,
      element: null,
    },
    {
      pageId: PageID.DASHBOARD_OVERVIEW,
      element: <Dashboard />,
    },
    {
      pageId: PageID.DASHBOARD_CONTRACT_LIST,
      element: <ContractList />,
    },
    {
      pageId: PageID.DASHBOARD_CONTRACT_DETAIL,
      element: <ContractDetail />,
    },
    {
      pageId: PageID.DASHBOARD_CONTRACT_CREATE,
      element: <ContractCreate />,
    },
    {
      pageId: PageID.DASHBOARD_USE_SUMMARY_LIST_BY_CONTRACT,
      element: <UseSummaryByContractList />,
    },
    {
      pageId: PageID.DASHBOARD_RECEIPT_ISSUING_ORDER_CREATE_CUSTOM_HELLO_TECHNO,
      element: <ReceiptIssuingOrderCreateHelloTechno />,
    },
    {
      pageId: PageID.DASHBOARD_RECEIPT_ISSUING_ORDER_LIST_CUSTOM_HELLO_TECHNO,
      element: <ReceiptIssuingOrderListHelloTechno />,
    },
    {
      pageId: PageID.DASHBOARD_RECEIPT_ISSUING_ORDER_DETAIL_CUSTOM_HELLO_TECHNO,
      element: <ReceiptIssuingOrderDetailHelloTechno />,
    },
    {
      pageId: PageID.DASHBOARD_USE_SUMMARY_LIST_CUSTOM_HELLO_TECHNO,
      element: <UseSummaryListHelloTechno />,
    },
    {
      pageId: PageID.DASHBOARD_USE_SUMMARY_DETAIL_CUSTOM_HELLO_TECHNO,
      element: <UseSummaryDetailHelloTechno />,
    },
    {
      pageId: PageID.DASHBOARD_LOGIN_USER_LIST,
      element: <LoginUserList />,
    },
    {
      pageId: PageID.DASHBOARD_LOGIN_USER_CREATE,
      element: <LoginUserCreate />,
    },
    {
      pageId: PageID.DASHBOARD_LOGIN_USER_CHANGE_PASSWORD,
      element: <ChangePassword />,
    },
  ];

  const children: RouteObject[] = useMemo(() => {
    return allChildren
      .filter(({ pageId }) => canAccess(pageId))
      .map(({ pageId, ...others }) => ({
        ...others,
        path: getRoute(pageId),
      }));
  }, [canAccess]);

  return {
    element: <DashboardLayout />,
    children,
  };
};

export function Routes() {
  const { initialized } = useAuth();
  return useRoutes([
    CommonRoutes(),
    AuthRoutes(),
    AppRoutes(),
    DashboardRoutes(),
    {
      path: "403",
      element: <Page403 />,
    },
    {
      path: "*",
      element: initialized ? <Page404 /> : <LoadingScreen />,
    },
  ]);
}

// 認証関連 -------------------------------
const Login = Loadable(lazy(() => import("pages/auth/login")));
const Logout = Loadable(lazy(() => import("pages/auth/logout")));
const ClearContract = Loadable(lazy(() => import("pages/auth/clear-contract")));

// App ---------------------------
const ReceiptIssuingOrder = Loadable(
  lazy(() => import("pages/app/ReceiptIssuingOrder"))
);
const MailOrder = Loadable(lazy(() => import("pages/app/MailOrder")));
const EmailOrder = Loadable(lazy(() => import("pages/app/EmailOrder")));

//ダッシュボード ----------------------------
const Dashboard = Loadable(lazy(() => import("pages/dashboard")));
// 契約関連
const ContractList = Loadable(
  lazy(() => import("pages/dashboard/contract/list"))
);
const ContractDetail = Loadable(
  lazy(() => import("pages/dashboard/contract/detail"))
);
const ContractCreate = Loadable(
  lazy(() => import("pages/dashboard/contract/create"))
);
// 領収証発行依頼
const ReceiptIssuingOrderCreateHelloTechno = Loadable(
  lazy(
    () =>
      import("pages/dashboard/receipt-issuing-order/custom/hello-techno/create")
  )
);
const ReceiptIssuingOrderListHelloTechno = Loadable(
  lazy(
    () =>
      import("pages/dashboard/receipt-issuing-order/custom/hello-techno/list")
  )
);
const ReceiptIssuingOrderDetailHelloTechno = Loadable(
  lazy(
    () =>
      import("pages/dashboard/receipt-issuing-order/custom/hello-techno/detail")
  )
);

// 利用実績関連
const UseSummaryByContractList = Loadable(
  lazy(() => import("pages/dashboard/use-summary/list"))
);
const UseSummaryListHelloTechno = Loadable(
  lazy(() => import("pages/dashboard/use-summary/custom/hello-techno/list"))
);
const UseSummaryDetailHelloTechno = Loadable(
  lazy(() => import("pages/dashboard/use-summary/custom/hello-techno/detail"))
);

//　ログインユーザー管理
const LoginUserList = Loadable(
  lazy(() => import("pages/dashboard/login-user/list"))
);
const LoginUserCreate = Loadable(
  lazy(() => import("pages/dashboard/login-user/create"))
);
const ChangePassword = Loadable(
  lazy(() => import("pages/dashboard/login-user/change-password"))
);

// その他 ---------------------------------

const PrivacyPolicy = Loadable(
  lazy(() => import("pages/common/PrivacyPolicy"))
);
const Page403 = Loadable(lazy(() => import("pages/common/Page403")));
const Page404 = Loadable(lazy(() => import("pages/common/Page404")));
