import { Content } from '@carbon/react';
import { createBrowserRouter, RouterProvider, Outlet } from 'react-router-dom';
import React, { useEffect, useState } from 'react';
import { ErrorBoundary } from 'react-error-boundary';

import ScrollToTop from './components/ScrollToTop';
import EditorRoutes from './routes/EditorRoutes';
import Extension from './routes/Extension';
import { useUriListForPermissions } from './hooks/UriListForPermissions';
import { PermissionsToCheck, ProcessFile, ProcessModel } from './interfaces';
import { usePermissionFetcher } from './hooks/PermissionService';
import {
  ExtensionUiSchema,
  UiSchemaUxElement,
} from './extension_ui_schema_interfaces';
import HttpService from './services/HttpService';
import { ErrorBoundaryFallback } from './ErrorBoundaryFallack';
import BaseRoutes from './routes/BaseRoutes';
import BackendIsDown from './routes/BackendIsDown';
import Login from './routes/Login';
import NavigationBar from './components/NavigationBar';

export default function ContainerForExtensions() {
  const [backendIsUp, setBackendIsUp] = useState<boolean | null>(null);
  const [extensionUxElements, setExtensionUxElements] = useState<
    UiSchemaUxElement[] | null
  >(null);

  let contentClassName = 'main-site-body-centered';
  if (window.location.pathname.startsWith('/editor/')) {
    contentClassName = 'no-center-stuff';
  }
  const { targetUris } = useUriListForPermissions();
  const permissionRequestData: PermissionsToCheck = {
    [targetUris.extensionListPath]: ['GET'],
  };
  const { ability, permissionsLoaded } = usePermissionFetcher(
    permissionRequestData
  );

  // eslint-disable-next-line sonarjs/cognitive-complexity
  useEffect(() => {
    const processExtensionResult = (processModels: ProcessModel[]) => {
      const eni: UiSchemaUxElement[] = processModels
        .map((processModel: ProcessModel) => {
          const extensionUiSchemaFile = processModel.files.find(
            (file: ProcessFile) => file.name === 'extension_uischema.json'
          );
          if (extensionUiSchemaFile && extensionUiSchemaFile.file_contents) {
            try {
              const extensionUiSchema: ExtensionUiSchema = JSON.parse(
                extensionUiSchemaFile.file_contents
              );
              if (
                extensionUiSchema.ux_elements &&
                !extensionUiSchema.disabled
              ) {
                return extensionUiSchema.ux_elements;
              }
            } catch (jsonParseError: any) {
              console.error(
                `Unable to get navigation items for ${processModel.id}`
              );
            }
          }
          return [] as UiSchemaUxElement[];
        })
        .flat();
      if (eni) {
        setExtensionUxElements(eni);
      }
    };

    const getExtensions = () => {
      setBackendIsUp(true);
      if (!permissionsLoaded) {
        return;
      }
      if (ability.can('GET', targetUris.extensionListPath)) {
        HttpService.makeCallToBackend({
          path: targetUris.extensionListPath,
          successCallback: processExtensionResult,
        });
      } else {
        // set to an empty array so we know that it loaded
        setExtensionUxElements([]);
      }
    };

    HttpService.makeCallToBackend({
      path: targetUris.statusPath,
      successCallback: getExtensions,
      failureCallback: () => setBackendIsUp(false),
    });
  }, [
    targetUris.extensionListPath,
    targetUris.statusPath,
    permissionsLoaded,
    ability,
  ]);

  const routeComponents = () => {
    return [
      {
        path: '*',
        element: <BaseRoutes extensionUxElements={extensionUxElements} />,
      },
      { path: 'editor/*', element: <EditorRoutes /> },
      { path: 'extensions/:page_identifier', element: <Extension /> },
      { path: 'login', element: <Login /> },
    ];
  };

  const backendIsDownPage = () => {
    return [<BackendIsDown />];
  };

  const innerComponents = () => {
    if (backendIsUp === null) {
      return [];
    }
    if (backendIsUp) {
      return <Outlet />;
    }
    return backendIsDownPage();
  };

  const layout = () => {
    return (
      <>
        <NavigationBar extensionUxElements={extensionUxElements} />
        <Content className={contentClassName}>
          <ScrollToTop />
          <ErrorBoundary FallbackComponent={ErrorBoundaryFallback}>
            {innerComponents()}
          </ErrorBoundary>
        </Content>
      </>
    );
  };

  const router = createBrowserRouter([
    {
      path: '*',
      Component: layout,
      children: routeComponents(),
    },
  ]);
  return <RouterProvider router={router} />;
}
