import React from "react";
import { BrowserRouter, useLocation } from "react-router-dom";

import { Stack } from "@mui/material";

import NavRail from "./components/NavRail";
import LoadingScreen from "./containers/LoadingScreen";
import { useApi } from "./contexts/ApiContext";
import DialogContextProvider, { BcomDialog } from "./contexts/DialogContext";
import { useI18n } from "./contexts/I18nContext";
import { RouterContextProvider } from "./contexts/RouterContext";
import { useUser } from "./contexts/UserContext";
import AcceptInvitePage from "./pages/AcceptInvitePage";
import LoginPage from "./pages/LoginPage";
import ResetPasswordPage from "./pages/ResetPasswordPage";
import { Router, RouterProps } from "./router/Router";
import { LogoType, NavigationOverrides } from "./types";

export interface AdminProps extends RouterProps {
  logo?: LogoType;
  logoSymbol?: LogoType;
  loginLogoHeight?: number | string;
  title?: string;
  subtitle?: string;
  version?: string;
  navigation: NavigationOverrides;
  basename?: string;
  /**
   * An optional base path to strip from the frontend navigation, usually this
   * is something along the lines of `/api/v1/` and if only a schema is provided
   * it will be automatically set to the dirname of that schema path.
   */
  basepath?: string;
}

const AdminContent: React.FC<AdminProps> = ({
  logo,
  logoSymbol,
  loginLogoHeight,
  title,
  subtitle,
  version,
  navigation,
  extensions,
  dashboard,
  basename,
  basepath,
}) => {
  const api = useApi();
  const i18n = useI18n();
  const { hasTriedToFetchUser, user } = useUser();
  const location = useLocation();

  const hasLoaded = Boolean(api != null && i18n != null);
  const hasUser = user != null;

  // Check if we're on public routes
  const isAcceptInviteRoute = location.pathname === "/user/accept-invite";
  const isResetPasswordRoute = location.pathname === "/user/reset-password";

  if (!hasLoaded || !hasTriedToFetchUser) {
    return <LoadingScreen />;
  }

  // Show accept invite page if on that route, regardless of auth status
  if (isAcceptInviteRoute) {
    return <AcceptInvitePage logo={logo} logoHeight={loginLogoHeight} title={title} />;
  }

  // Show reset password page if on that route, regardless of auth status
  if (isResetPasswordRoute) {
    return <ResetPasswordPage logo={logo} logoHeight={loginLogoHeight} title={title} />;
  }

  // Show login page if not authenticated
  if (!hasUser) {
    return <LoginPage logo={logo} logoHeight={loginLogoHeight} title={title} />;
  }

  // Show authenticated content
  return (
    <RouterContextProvider basename={basename} stripPathPrefix={basepath}>
      <DialogContextProvider>
        <BcomDialog />
        <Stack direction={{ xs: "column", sm: "row" }}>
          <NavRail
            logo={logoSymbol ?? logo}
            navigation={navigation}
            subtitle={subtitle}
            title={title}
            version={version}
          />

          <Router dashboard={dashboard} extensions={extensions} />
        </Stack>
      </DialogContextProvider>
    </RouterContextProvider>
  );
};

export const Admin: React.FC<AdminProps> = (props) => {
  return (
    <Stack
      sx={{
        minWidth: "100%",
        minHeight: "100%",
        bgcolor: "background.default",
      }}
    >
      <BrowserRouter basename={props.basename}>
        <AdminContent {...props} />
      </BrowserRouter>
    </Stack>
  );
};

export default Admin;
