/**
 * Main Application Component with Routing and Authentication
 * 
 * © 2025 Netwerk Digitaal Erfgoed & TextPast. All rights reserved.
 */

import React, { Suspense, useEffect, useState, useCallback } from 'react';
import {
  createBrowserRouter,
  RouterProvider,
  Navigate,
} from 'react-router-dom';
import { AuthProvider } from './contexts/AuthContext';
import { LanguageProvider } from './contexts/LanguageContext';
import { UIStateProvider } from './contexts/UIStateContext';
import { ProtectedRoute } from './components/ProtectedRoute';
import { Layout } from './components/layout/Layout';
import { preloadInstitutions } from './hooks/useGeoApiInstitutions';
import { 
  lazyWithRetry, 
  RouterErrorBoundary, 
  LazyLoadErrorBoundary 
} from './components/common/LazyLoadError';
import { startVersionCheck } from './lib/version-check';
import { RefreshCw } from 'lucide-react';

// Eagerly loaded pages (small, frequently accessed)
import { LoginPage } from './pages/LoginPage';
import { Settings } from './pages/Settings';
import ProjectPlanPage from './pages/ProjectPlanPage';

// Lazy loaded pages with automatic retry on chunk load failures
// These use lazyWithRetry() to handle deployment-related chunk errors gracefully
// Map page - imports maplibre-gl (~1MB)
const NDEMapPage = lazyWithRetry(() => import('./pages/NDEMapPageMapLibre'));
// Visualize page - imports mermaid, d3, elkjs (~1.5MB combined)
const Visualize = lazyWithRetry(() => import('./pages/Visualize').then(m => ({ default: m.Visualize })));
// LinkML viewer - large schema parsing
const LinkMLViewerPage = lazyWithRetry(() => import('./pages/LinkMLViewerPage'));
// Ontology viewer - imports visualization libraries
const OntologyViewerPage = lazyWithRetry(() => import('./pages/OntologyViewerPage'));
// Data mappings page - custodian data mappings explorer
const DataMapPage = lazyWithRetry(() => import('./pages/DataMapPage'));
// Query builder - medium complexity
const QueryBuilderPage = lazyWithRetry(() => import('./pages/QueryBuilderPage'));
// Database page
const Database = lazyWithRetry(() => import('./pages/Database').then(m => ({ default: m.Database })));
// Stats page
const NDEStatsPage = lazyWithRetry(() => import('./pages/NDEStatsPage'));
// Conversation page
const ConversationPage = lazyWithRetry(() => import('./pages/ConversationPage'));
// Institution browser page
const InstitutionBrowserPage = lazyWithRetry(() => import('./pages/InstitutionBrowserPage'));
// Entity resolution review page
const EntityReviewPage = lazyWithRetry(() => import('./pages/EntityReviewPage'));
// Review login page (separate auth from main app)
const ReviewLoginPage = lazyWithRetry(() => import('./pages/ReviewLoginPage'));

import './App.css';

// Loading fallback component for lazy-loaded pages
const PageLoader = () => (
  <div className="flex items-center justify-center h-64">
    <div className="text-center">
      <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600 mx-auto mb-4"></div>
      <p className="text-gray-600 dark:text-gray-400">Loading...</p>
    </div>
  </div>
);

// Wrap lazy components with Suspense and error boundary for chunk load errors
const withSuspense = (Component: React.LazyExoticComponent<React.ComponentType>) => (
  <LazyLoadErrorBoundary>
    <Suspense fallback={<PageLoader />}>
      <Component />
    </Suspense>
  </LazyLoadErrorBoundary>
);

// Create router configuration with protected and public routes
// Documentation routes (linkml, datamap, ontology, browse) are PUBLIC for embedding
// Other pages require authentication via ProtectedRoute
const router = createBrowserRouter([
  {
    path: '/login',
    element: <LoginPage />,
    errorElement: <RouterErrorBoundary />,
  },
  {
    // Dedicated login for review page (separate credentials)
    path: '/review-login',
    element: withSuspense(ReviewLoginPage),
    errorElement: <RouterErrorBoundary />,
  },
  // ========================================================================
  // PUBLIC ROUTES - No authentication required
  // These can be embedded in iframes from other domains (e.g., archief.support)
  // ========================================================================
  {
    path: '/linkml',
    element: <Layout />,
    errorElement: <RouterErrorBoundary />,
    children: [
      {
        index: true,
        element: withSuspense(LinkMLViewerPage),
      },
    ],
  },
  {
    path: '/parsimony',
    element: <Layout />,
    errorElement: <RouterErrorBoundary />,
    children: [
      {
        index: true,
        element: withSuspense(LinkMLViewerPage),
      },
    ],
  },
  {
    path: '/datamap',
    element: <Layout />,
    errorElement: <RouterErrorBoundary />,
    children: [
      {
        index: true,
        element: withSuspense(DataMapPage),
      },
    ],
  },
  {
    path: '/ontology',
    element: <Layout />,
    errorElement: <RouterErrorBoundary />,
    children: [
      {
        index: true,
        element: withSuspense(OntologyViewerPage),
      },
    ],
  },
  {
    path: '/browse',
    element: <Layout />,
    errorElement: <RouterErrorBoundary />,
    children: [
      {
        index: true,
        element: withSuspense(InstitutionBrowserPage),
      },
    ],
  },
  // ========================================================================
  // PROTECTED ROUTES - Authentication required
  // ========================================================================
  {
    path: '/',
    element: (
      <ProtectedRoute>
        <Layout />
      </ProtectedRoute>
    ),
    errorElement: <RouterErrorBoundary />,
    children: [
      {
        // Home page redirects to LinkML viewer
        index: true,
        element: <Navigate to="/linkml" replace />,
      },
      {
        path: 'visualize',
        element: withSuspense(Visualize),
      },
      {
        path: 'database',
        element: withSuspense(Database),
      },
      {
        path: 'settings',
        element: <Settings />,
      },
      {
        // Roadmap page (formerly Home/Project Plan)
        path: 'roadmap',
        element: <ProjectPlanPage />,
      },
      {
        path: 'query-builder',
        element: withSuspense(QueryBuilderPage),
      },
      {
        // Redirect old UML viewer route to unified visualize page
        path: 'uml-viewer',
        element: <Navigate to="/visualize" replace />,
      },
      {
        path: 'map',
        element: withSuspense(NDEMapPage),
      },
      {
        path: 'stats',
        element: withSuspense(NDEStatsPage),
      },
      {
        path: 'conversation',
        element: withSuspense(ConversationPage),
      },
      {
        path: 'review',
        element: withSuspense(EntityReviewPage),
      },
    ],
  },
]);

function App() {
  const [showUpdateBanner, setShowUpdateBanner] = useState(false);
  
  // Preload institution data on app initialization
  // This starts the fetch early so data is ready when user navigates to Map or Browse
  useEffect(() => {
    // Small delay to let the app initialize first
    const timer = setTimeout(() => {
      preloadInstitutions();
    }, 500);
    return () => clearTimeout(timer);
  }, []);

  // Check for new versions periodically
  useEffect(() => {
    const cleanup = startVersionCheck(() => {
      setShowUpdateBanner(true);
    });
    return cleanup;
  }, []);

  const handleRefresh = useCallback(() => {
    // Clear caches and reload
    if ('caches' in window) {
      caches.keys().then(names => {
        names.forEach(name => caches.delete(name));
      });
    }
    window.location.reload();
  }, []);

  return (
    <LanguageProvider>
      <AuthProvider>
        <UIStateProvider>
          {/* New version available banner */}
          {showUpdateBanner && (
            <div className="fixed top-0 left-0 right-0 z-[9999] bg-blue-600 text-white px-4 py-2 text-center text-sm flex items-center justify-center gap-3">
              <span>A new version is available.</span>
              <button
                onClick={handleRefresh}
                className="inline-flex items-center gap-1.5 px-3 py-1 bg-white text-blue-600 rounded font-medium hover:bg-blue-50 transition-colors"
              >
                <RefreshCw className="w-3.5 h-3.5" />
                Refresh
              </button>
              <button
                onClick={() => setShowUpdateBanner(false)}
                className="text-white/80 hover:text-white ml-2"
                aria-label="Dismiss"
              >
                ×
              </button>
            </div>
          )}
          <RouterProvider router={router} />
        </UIStateProvider>
      </AuthProvider>
    </LanguageProvider>
  );
}

export default App;
