/**
 * @file AppRoutes.tsx - Application route definitions and route guard components.
 * Defines all client-side routes, including protected routes that require authentication, parameter validation guards, and the nested context providers required by Processing routes.
 */

import {
  Route,
  Navigate,
  createRoutesFromElements,
  useParams,
} from 'react-router-dom';
import { type ReactNode, useEffect } from 'react';
import { ProtectedRoute } from './components/ProtectedRoute.tsx';
import { toast } from 'react-toastify';
import { ProcessPermissionsProvider } from './contexts/ProcessPermissionsContext.tsx';
import { WorkItemProvider } from './contexts/WorkItemContext.tsx';
import { DocumentProvider } from './contexts/DocumentContext.tsx';
import { ProcessingUIProvider } from './contexts/ProcessingUIContext.tsx';
import { HotkeysProvider } from 'react-hotkeys-hook';
import { useTranslation } from 'react-i18next';

// Import pages
import { ApplicationError } from './pages/ApplicationError.tsx';
import { AutoOpen } from './pages/AutoOpen.tsx';
import { Forbidden } from './pages/Forbidden.tsx';
import { Home } from './pages/Home.tsx';
import { Login } from './pages/Login.tsx';
import { NotFound } from './pages/NotFound.tsx';
import { Processing } from './pages/Processing.tsx';

/**
 * Displays an error toast listing the missing URL parameters, then redirects to the home page.
 * Used as the element for Processing sub-routes that are missing required path segments.
 *
 * @param paramNames List of required param names
 * @returns Navigation back to home page
 */
const MissingParamRedirect = ({ paramNames }: { paramNames: string[] }) => {
  const { t } = useTranslation(undefined, {
    keyPrefix: 'app_routes.components.missing_param_redirect',
  });

  useEffect(() => {
    toast.error(`${t('error')} ` + paramNames.join(', '));
  }, []);

  return <Navigate to={'/'} />;
};

/**
 * Validates that the specified URL parameters are valid numbers.
 * Redirects to the home page with an error toast if any parameter is non-numeric.
 * Renders children when all parameters are valid.
 *
 * @param paramNames List of required numeric param names
 * @param children Child node to render
 * @returns Navigation back to home page or child nodes
 */
const ValidateNumericParams = ({
  paramNames,
  children,
}: {
  paramNames: string[];
  children: ReactNode;
}) => {
  const params = useParams();

  const invalidParam = paramNames.find((name) => {
    const value = params[name];
    return value !== undefined && (isNaN(Number(value)) || value.trim() === '');
  });

  const { t } = useTranslation(undefined, {
    keyPrefix: 'app_routes.components.validate_numeric_params',
  });

  useEffect(() => {
    if (invalidParam) {
      toast.error(`${t('error')} ` + invalidParam);
    }
  }, [invalidParam]);

  if (invalidParam) {
    return <Navigate to={'/'} />;
  }

  return <>{children}</>;
};

// Define application routes as JSX elements
export const routes = createRoutesFromElements(
  <>
    <Route path={'/'} element={<Navigate to={'/home'} replace />} />
    <Route path={'*'} element={<Navigate to={'/not-found'} replace />} />

    <Route
      path={'/login'}
      element={<Login />}
      handle={{ showNavbar: false, title: 'Login' }}
    />

    <Route
      path={'/forbidden'}
      element={<Forbidden />}
      handle={{ showNavbar: true, title: '403 Forbidden' }}
    />

    <Route
      path={'/not-found'}
      element={<NotFound />}
      handle={{ showNavbar: true, title: '404 Not Found' }}
    />

    <Route
      path={'/application-error'}
      element={<ApplicationError />}
      handle={{ showNavbar: true, title: 'Application Error' }}
    />

    <Route
      path={'/home'}
      element={
        <ProtectedRoute>
          <ProcessPermissionsProvider>
            <Home />
          </ProcessPermissionsProvider>
        </ProtectedRoute>
      }
      handle={{ showNavbar: true, title: 'Home' }}
    />

    {/* Auto-open routes */}
    <Route
      path={'/auto-open'}
      handle={{ showNavbar: true, title: 'Auto-open' }}
    >
      <Route
        index
        element={
          <ProtectedRoute>
            <AutoOpen />
          </ProtectedRoute>
        }
      />
      <Route
        path={':processId'}
        element={<MissingParamRedirect paramNames={['queueId']} />}
      />
      <Route
        path={':processId/:queueId'}
        element={
          <ProtectedRoute>
            <AutoOpen />
          </ProtectedRoute>
        }
      />
    </Route>

    {/* Processing routes */}
    <Route
      path={'/processing'}
      handle={{ showNavbar: true, title: 'Processing' }}
    >
      <Route
        index
        element={
          <MissingParamRedirect
            paramNames={['processId', 'queueId', 'workItemReferenceId']}
          />
        }
      />
      <Route
        path={':processId'}
        element={
          <MissingParamRedirect
            paramNames={['queueId', 'workItemReferenceId']}
          />
        }
      />
      <Route
        path={':processId/:queueId'}
        element={<MissingParamRedirect paramNames={['workItemReferenceId']} />}
      />
      <Route
        path={':processId/:queueId/:workItemReferenceId'}
        element={
          <ProtectedRoute>
            <ValidateNumericParams
              paramNames={['processId', 'queueId', 'workItemReferenceId']}
            >
              <ProcessPermissionsProvider>
                <WorkItemProvider>
                  <DocumentProvider>
                    <ProcessingUIProvider>
                      <HotkeysProvider>
                        <Processing />
                      </HotkeysProvider>
                    </ProcessingUIProvider>
                  </DocumentProvider>
                </WorkItemProvider>
              </ProcessPermissionsProvider>
            </ValidateNumericParams>
          </ProtectedRoute>
        }
      />
    </Route>
  </>
);
