import { lazy, Suspense, useEffect, useRef, useState } from 'react';
import { LoginView } from './components/LoginView';
import { NotesList } from './components/NotesList';
import { NoteEditor } from './components/NoteEditor';
import { CategoriesSidebar } from './components/CategoriesSidebar';
import { NextcloudAPI } from './api/nextcloud';
import { Note } from './types';
import { syncManager, SyncStatus } from './services/syncManager';
import { localDB } from './db/localDB';
import { useOnlineStatus } from './hooks/useOnlineStatus';
import { categoryColorsSync } from './services/categoryColorsSync';
import { PRINT_EXPORT_QUERY_PARAM } from './printExport';

const LazyPrintView = lazy(async () => {
  const module = await import('./components/PrintView');
  return { default: module.PrintView };
});

const AUTOSAVE_DELAY_MS = 1000;

interface SaveController {
  timerId: number | null;
  revision: number;
  inFlight: Promise<void> | null;
  inFlightRevision: number;
}

interface FlushSaveOptions {
  force?: boolean;
}

const sortNotes = (notes: Note[]) =>
  [...notes].sort((a, b) => b.modified - a.modified);

const toStoredNote = (note: Note): Note => ({
  ...note,
  isSaving: false,
});

const getNoteDraftId = (note: Note | null | undefined) => note?.draftId ?? null;

const createDraftId = () => {
  if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
    return crypto.randomUUID();
  }

  return `draft-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
};

const getRemoteCategory = (note: Note) => {
  if (note.path) {
    const pathParts = note.path.split('/');
    return pathParts.length > 1 ? pathParts.slice(0, -1).join('/') : '';
  }

  if (typeof note.id === 'string') {
    const idParts = note.id.split('/');
    return idParts.length > 1 ? idParts.slice(0, -1).join('/') : '';
  }

  return note.category;
};

const splitNoteContent = (content: string) => {
  const [firstLine = '', ...rest] = content.split('\n');
  return {
    title: firstLine.replace(/^#+\s*/, '').trim(),
    body: rest.join('\n'),
  };
};

const canAutosaveLocalNote = (note: Note) => {
  if (!note.localOnly) {
    return true;
  }

  const { title } = splitNoteContent(note.content);
  return title.length > 0 && note.content.includes('\n');
};

const canForceSaveLocalNote = (note: Note) => {
  if (!note.localOnly) {
    return true;
  }

  const { title } = splitNoteContent(note.content);
  return title.length > 0;
};

function MainApp() {
  const [isLoggedIn, setIsLoggedIn] = useState(false);
  const [api, setApi] = useState<NextcloudAPI | null>(null);
  const [notes, setNotes] = useState<Note[]>([]);
  const [selectedNoteDraftId, setSelectedNoteDraftId] = useState<string | null>(null);
  const [searchText, setSearchText] = useState('');
  const [showFavoritesOnly, setShowFavoritesOnly] = useState(false);
  const [selectedCategory, setSelectedCategory] = useState('');
  const [manualCategories, setManualCategories] = useState<string[]>([]);
  const [isCategoriesCollapsed, setIsCategoriesCollapsed] = useState(false);
  const [isFocusMode, setIsFocusMode] = useState(false);
  const [username, setUsername] = useState('');
  const [theme, setTheme] = useState<'light' | 'dark' | 'system'>('system');
  const [effectiveTheme, setEffectiveTheme] = useState<'light' | 'dark'>('light');
  const [editorFont, setEditorFont] = useState('Source Code Pro');
  const [editorFontSize, setEditorFontSize] = useState(14);
  const [previewFont, setPreviewFont] = useState('Merriweather');
  const [previewFontSize, setPreviewFontSize] = useState(16);
  const [syncStatus, setSyncStatus] = useState<SyncStatus>('idle');
  const [pendingSyncCount, setPendingSyncCount] = useState(0);
  const isOnline = useOnlineStatus();
  const notesRef = useRef<Note[]>([]);
  const saveControllersRef = useRef<Map<string, SaveController>>(new Map());
  const savedSnapshotsRef = useRef<Map<string, Note>>(new Map());

  const setSortedNotes = (updater: Note[] | ((previous: Note[]) => Note[])) => {
    setNotes((previous) => {
      const nextNotes = typeof updater === 'function'
        ? (updater as (previous: Note[]) => Note[])(previous)
        : updater;
      const sortedNotes = sortNotes(nextNotes);
      notesRef.current = sortedNotes;
      return sortedNotes;
    });
  };

  const getNoteByDraftId = (draftId: string | null) =>
    draftId ? notesRef.current.find(note => note.draftId === draftId) ?? null : null;

  const persistNoteToCache = (note: Note) => {
    void localDB.saveNote(toStoredNote(note)).catch((error) => {
      console.error('Failed to persist note locally:', error);
    });
  };

  const ensureSaveController = (draftId: string) => {
    let controller = saveControllersRef.current.get(draftId);
    if (!controller) {
      controller = {
        timerId: null,
        revision: 0,
        inFlight: null,
        inFlightRevision: 0,
      };
      saveControllersRef.current.set(draftId, controller);
    }

    return controller;
  };

  const clearSaveTimer = (draftId: string) => {
    const controller = saveControllersRef.current.get(draftId);
    if (controller?.timerId) {
      window.clearTimeout(controller.timerId);
      controller.timerId = null;
    }
  };

  const applyLoadedNotes = (loadedNotes: Note[]) => {
    const normalizedNotes = sortNotes(loadedNotes);
    const incomingDraftIds = new Set<string>();

    normalizedNotes.forEach((note) => {
      if (!note.draftId) {
        return;
      }

      incomingDraftIds.add(note.draftId);
      if (!note.pendingSave) {
        savedSnapshotsRef.current.set(note.draftId, {
          ...note,
          pendingSave: false,
          isSaving: false,
          saveError: null,
        });
      }
    });

    for (const draftId of Array.from(savedSnapshotsRef.current.keys())) {
      if (!incomingDraftIds.has(draftId)) {
        savedSnapshotsRef.current.delete(draftId);
      }
    }

    notesRef.current = normalizedNotes;
    setNotes(normalizedNotes);
    setSelectedNoteDraftId((current) => {
      if (current && normalizedNotes.some(note => note.draftId === current)) {
        return current;
      }

      return getNoteDraftId(normalizedNotes[0]);
    });
  };

  useEffect(() => {
    const initApp = async () => {
      await localDB.init();
      
      const savedServer = localStorage.getItem('serverURL');
      const savedUsername = localStorage.getItem('username');
      const savedPassword = localStorage.getItem('password');
      const savedTheme = localStorage.getItem('theme') as 'light' | 'dark' | 'system' | null;
      const savedEditorFont = localStorage.getItem('editorFont');
      const savedPreviewFont = localStorage.getItem('previewFont');

      if (savedTheme) {
        setTheme(savedTheme);
      }
      if (savedEditorFont) {
        setEditorFont(savedEditorFont);
      }
      if (savedPreviewFont) {
        setPreviewFont(savedPreviewFont);
      }
      const savedEditorFontSize = localStorage.getItem('editorFontSize');
      const savedPreviewFontSize = localStorage.getItem('previewFontSize');
      if (savedEditorFontSize) {
        setEditorFontSize(parseInt(savedEditorFontSize, 10));
      }
      if (savedPreviewFontSize) {
        setPreviewFontSize(parseInt(savedPreviewFontSize, 10));
      }

      if (savedServer && savedUsername && savedPassword) {
        const apiInstance = new NextcloudAPI({
          serverURL: savedServer,
          username: savedUsername,
          password: savedPassword,
        });
        setApi(apiInstance);
        syncManager.setAPI(apiInstance);
        categoryColorsSync.setAPI(apiInstance);
        setUsername(savedUsername);
        setIsLoggedIn(true);
      }
    };
    
    initApp();
  }, []);

  useEffect(() => {
    const updateEffectiveTheme = () => {
      if (theme === 'system') {
        const isDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
        setEffectiveTheme(isDark ? 'dark' : 'light');
      } else {
        setEffectiveTheme(theme);
      }
    };

    updateEffectiveTheme();

    if (theme === 'system') {
      const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
      const handler = () => updateEffectiveTheme();
      mediaQuery.addEventListener('change', handler);
      return () => mediaQuery.removeEventListener('change', handler);
    }
  }, [theme]);

  useEffect(() => {
    document.documentElement.classList.toggle('dark', effectiveTheme === 'dark');
  }, [effectiveTheme]);

  useEffect(() => {
    syncManager.setStatusCallback((status, count) => {
      setSyncStatus(status);
      setPendingSyncCount(count);
    });
    
    syncManager.setSyncCompleteCallback(async () => {
      // Reload notes from cache after background sync completes
      // Don't call loadNotes() as it triggers another sync - just reload from cache
      const cachedNotes = await localDB.getAllNotes();
      applyLoadedNotes(cachedNotes);
    });
  }, []);

  useEffect(() => {
    if (api && isLoggedIn) {
      loadNotes();
      const interval = setInterval(() => syncNotes(), 300000);
      return () => clearInterval(interval);
    }
  }, [api, isLoggedIn]);

  useEffect(() => {
    if (!isLoggedIn || !isOnline) {
      return;
    }

    notesRef.current
      .filter(note => note.pendingSave && note.draftId)
      .forEach((note) => {
        const draftId = note.draftId as string;
        const controller = ensureSaveController(draftId);
        if (!controller.inFlight && !controller.timerId) {
          controller.timerId = window.setTimeout(() => {
            controller.timerId = null;
            void flushNoteSave(draftId);
          }, 0);
        }
      });
  }, [isLoggedIn, isOnline]);

  useEffect(() => {
    const handleBeforeUnload = () => {
      notesRef.current
        .filter(note => note.pendingSave && note.draftId)
        .forEach((note) => {
          clearSaveTimer(note.draftId!);
          void flushNoteSave(note.draftId!, { force: true });
        });
    };

    window.addEventListener('beforeunload', handleBeforeUnload);
    return () => window.removeEventListener('beforeunload', handleBeforeUnload);
  }, []);

  const loadNotes = async () => {
    try {
      const loadedNotes = await syncManager.loadNotes();
      applyLoadedNotes(loadedNotes);
    } catch (error) {
      console.error('Failed to load notes:', error);
    }
  };

  const syncNotes = async () => {
    try {
      await flushAllPendingSaves();
      await syncManager.syncWithServer();
      await loadNotes();
    } catch (error) {
      console.error('Sync failed:', error);
    }
  };

  const handleLogin = async (serverURL: string, username: string, password: string) => {
    localStorage.setItem('serverURL', serverURL);
    localStorage.setItem('username', username);
    localStorage.setItem('password', password);

    const apiInstance = new NextcloudAPI({ serverURL, username, password });
    setApi(apiInstance);
    syncManager.setAPI(apiInstance);
    categoryColorsSync.setAPI(apiInstance);
    setUsername(username);
    setIsLoggedIn(true);
  };

  const handleLogout = async () => {
    localStorage.removeItem('serverURL');
    localStorage.removeItem('username');
    localStorage.removeItem('password');
    await localDB.clearNotes();
    setApi(null);
    syncManager.setAPI(null);
    categoryColorsSync.setAPI(null);
    setUsername('');
    setNotes([]);
    notesRef.current = [];
    setSelectedNoteDraftId(null);
    setIsLoggedIn(false);
    saveControllersRef.current.clear();
    savedSnapshotsRef.current.clear();
  };

  const handleThemeChange = (newTheme: 'light' | 'dark' | 'system') => {
    setTheme(newTheme);
    localStorage.setItem('theme', newTheme);
  };

  const handleEditorFontChange = (font: string) => {
    setEditorFont(font);
    localStorage.setItem('editorFont', font);
  };

  const handlePreviewFontChange = (font: string) => {
    setPreviewFont(font);
    localStorage.setItem('previewFont', font);
  };

  const handleEditorFontSizeChange = (size: number) => {
    setEditorFontSize(size);
    localStorage.setItem('editorFontSize', size.toString());
  };

  const handlePreviewFontSizeChange = (size: number) => {
    setPreviewFontSize(size);
    localStorage.setItem('previewFontSize', size.toString());
  };

  const handleToggleFavorite = async (note: Note, favorite: boolean) => {
    const draftId = note.draftId;
    if (!draftId) {
      return;
    }

    const optimisticNote = {
      ...note,
      favorite,
      saveError: null,
    };

    setSortedNotes(previousNotes =>
      previousNotes.map(currentNote =>
        currentNote.draftId === draftId ? optimisticNote : currentNote
      )
    );
    persistNoteToCache(optimisticNote);

    try {
      await syncManager.updateFavoriteStatus(optimisticNote, favorite);
      const snapshot = savedSnapshotsRef.current.get(draftId);
      if (snapshot) {
        savedSnapshotsRef.current.set(draftId, {
          ...snapshot,
          favorite,
        });
      }
    } catch (error) {
      console.error('Toggle favorite failed:', error);
    }
  };

  const handleCreateNote = async () => {
    const draftId = createDraftId();
    const note: Note = {
      id: `local:${draftId}`,
      etag: '',
      readonly: false,
      content: '',
      title: 'Untitled',
      category: selectedCategory,
      favorite: false,
      modified: Math.floor(Date.now() / 1000),
      draftId,
      localOnly: true,
      pendingSave: false,
      isSaving: false,
      saveError: null,
      lastSavedAt: undefined,
    };

    savedSnapshotsRef.current.set(draftId, {
      ...note,
      pendingSave: false,
      isSaving: false,
      saveError: null,
    });
    setSortedNotes(previousNotes => [note, ...previousNotes]);
    persistNoteToCache(note);
    setSelectedNoteDraftId(draftId);
  };

  const handleCreateCategory = (name: string) => {
    if (!manualCategories.includes(name)) {
      setManualCategories([...manualCategories, name]);
    }
  };

  const handleRenameCategory = async (oldName: string, newName: string) => {
    // Move all notes from old category to new category
    const notesToMove = notes.filter(note => note.category === oldName);
    
    for (const note of notesToMove) {
      try {
        const movedNote = await syncManager.moveNote(note, newName);
        if (movedNote.draftId) {
          savedSnapshotsRef.current.set(movedNote.draftId, {
            ...movedNote,
            pendingSave: false,
            isSaving: false,
            saveError: null,
          });
        }
        setSortedNotes(previousNotes =>
          previousNotes.map(currentNote =>
            currentNote.draftId === note.draftId ? movedNote : currentNote
          )
        );
      } catch (error) {
        console.error(`Failed to move note ${note.id}:`, error);
      }
    }

    // Update manual categories list
    setManualCategories(prev => 
      prev.map(cat => cat === oldName ? newName : cat)
    );

    // Update selected category if it was the renamed one
    if (selectedCategory === oldName) {
      setSelectedCategory(newName);
    }
  };

  const persistNoteToServer = async (note: Note) => {
    if (note.localOnly) {
      const { title, body } = splitNoteContent(note.content);
      const createdNote = await syncManager.createNote(title, body, note.category);
      return {
        ...createdNote,
        content: note.content,
        title,
        favorite: note.favorite,
        draftId: note.draftId,
        localOnly: false,
      };
    }

    const remoteCategory = getRemoteCategory(note);

    if (remoteCategory !== note.category) {
      const movedNote = await syncManager.moveNote(note, note.category);
      return syncManager.updateNote({
        ...movedNote,
        draftId: note.draftId,
        title: note.title,
        content: note.content,
        favorite: note.favorite,
        localOnly: false,
        pendingSave: false,
        isSaving: false,
        saveError: null,
        lastSavedAt: note.lastSavedAt,
      });
    }

    return syncManager.updateNote(note);
  };

  const flushNoteSave = async (draftId: string, options: FlushSaveOptions = {}): Promise<void> => {
    const controller = ensureSaveController(draftId);
    clearSaveTimer(draftId);

    const currentNote = getNoteByDraftId(draftId);
    if (!currentNote?.pendingSave) {
      return;
    }

    const canPersist = options.force ? canForceSaveLocalNote(currentNote) : canAutosaveLocalNote(currentNote);
    if (!canPersist) {
      return;
    }

    if (controller.inFlight) {
      await controller.inFlight;
      return;
    }

    controller.inFlightRevision = controller.revision;

    setSortedNotes(previousNotes =>
      previousNotes.map(note =>
        note.draftId === draftId
          ? {
              ...note,
              isSaving: true,
              saveError: null,
            }
          : note
      )
    );

    const savePromise = (async () => {
      try {
        const noteToPersist = getNoteByDraftId(draftId);
        if (!noteToPersist?.pendingSave) {
          return;
        }

        const canPersistLatest = options.force ? canForceSaveLocalNote(noteToPersist) : canAutosaveLocalNote(noteToPersist);
        if (!canPersistLatest) {
          return;
        }

        const savedNote = {
          ...(await persistNoteToServer(noteToPersist)),
          draftId,
          localOnly: false,
          pendingSave: false,
          isSaving: false,
          saveError: null,
          lastSavedAt: Date.now(),
        };

        if (noteToPersist.id !== savedNote.id) {
          void localDB.deleteNote(noteToPersist.id).catch((error) => {
            console.error('Failed to remove stale local note cache entry:', error);
          });
        }

        savedSnapshotsRef.current.set(draftId, {
          ...savedNote,
          pendingSave: false,
          isSaving: false,
          saveError: null,
        });

        const latestNote = getNoteByDraftId(draftId);
        const hasNewerChanges = controller.revision > controller.inFlightRevision && latestNote;

        if (latestNote && hasNewerChanges) {
          const mergedPendingNote: Note = {
            ...savedNote,
            content: latestNote.content,
            title: latestNote.title,
            category: latestNote.category,
            favorite: latestNote.favorite,
            modified: latestNote.modified,
            localOnly: false,
            pendingSave: true,
            isSaving: false,
            saveError: null,
          };

          setSortedNotes(previousNotes =>
            previousNotes.map(note =>
              note.draftId === draftId ? mergedPendingNote : note
            )
          );
          persistNoteToCache(mergedPendingNote);
          scheduleNoteSave(draftId, 0);
          return;
        }

        setSortedNotes(previousNotes =>
          previousNotes.map(note =>
            note.draftId === draftId ? savedNote : note
          )
        );
        persistNoteToCache(savedNote);
      } catch (error) {
        console.error('Update note failed:', error);

        const failedNote = getNoteByDraftId(draftId);
        if (!failedNote) {
          return;
        }

        const erroredNote = {
          ...failedNote,
          pendingSave: true,
          isSaving: false,
          saveError: error instanceof Error ? error.message : 'Failed to save note.',
        };

        setSortedNotes(previousNotes =>
          previousNotes.map(note =>
            note.draftId === draftId ? erroredNote : note
          )
        );
        persistNoteToCache(erroredNote);
      } finally {
        controller.inFlight = null;
      }
    })();

    controller.inFlight = savePromise;
    await savePromise;
  };

  const scheduleNoteSave = (draftId: string, delayMs = AUTOSAVE_DELAY_MS) => {
    const controller = ensureSaveController(draftId);
    clearSaveTimer(draftId);

    controller.timerId = window.setTimeout(() => {
      controller.timerId = null;
      void flushNoteSave(draftId);
    }, delayMs);
  };

  const flushAllPendingSaves = async () => {
    const pendingDraftIds = notesRef.current
      .filter(note => note.pendingSave && note.draftId)
      .map(note => note.draftId as string);

    await Promise.all(pendingDraftIds.map(draftId => flushNoteSave(draftId, { force: true })));
  };

  const handleDraftChange = (updatedNote: Note) => {
    const draftId = updatedNote.draftId;
    if (!draftId) {
      return;
    }

    const localNote = {
      ...updatedNote,
      modified: Math.floor(Date.now() / 1000),
      pendingSave: true,
      isSaving: false,
      saveError: null,
    };

    const controller = ensureSaveController(draftId);
    controller.revision += 1;

    setSortedNotes(previousNotes =>
      previousNotes.map(note =>
        note.draftId === draftId ? localNote : note
      )
    );
    persistNoteToCache(localNote);
    scheduleNoteSave(draftId);
  };

  const handleManualSave = async (draftId: string) => {
    await flushNoteSave(draftId, { force: true });
  };

  const handleDiscardNote = (draftId: string) => {
    const snapshot = savedSnapshotsRef.current.get(draftId);
    if (!snapshot) {
      return;
    }

    clearSaveTimer(draftId);
    const controller = ensureSaveController(draftId);
    controller.revision += 1;

    const cleanSnapshot = {
      ...snapshot,
      pendingSave: false,
      isSaving: false,
      saveError: null,
    };

    setSortedNotes(previousNotes =>
      previousNotes.map(note =>
        note.draftId === draftId ? cleanSnapshot : note
      )
    );
    persistNoteToCache(cleanSnapshot);
  };

  const handleSelectNote = async (draftId: string) => {
    if (draftId === selectedNoteDraftId) {
      return;
    }

    if (selectedNoteDraftId) {
      await flushNoteSave(selectedNoteDraftId, { force: true });
    }

    setSelectedNoteDraftId(draftId);
  };

  const handleDeleteNote = async (note: Note) => {
    const draftId = note.draftId;
    if (!draftId) {
      return;
    }

    try {
      clearSaveTimer(draftId);
      if (!note.localOnly) {
        await syncManager.deleteNote(note);
      } else {
        await localDB.deleteNote(note.id);
      }

      saveControllersRef.current.delete(draftId);
      savedSnapshotsRef.current.delete(draftId);

      const remainingNotes = notesRef.current.filter(currentNote => currentNote.draftId !== draftId);
      notesRef.current = sortNotes(remainingNotes);
      setNotes(notesRef.current);

      if (selectedNoteDraftId === draftId) {
        setSelectedNoteDraftId(getNoteDraftId(notesRef.current[0]));
      }
    } catch (error) {
      console.error('Delete note failed:', error);
    }
  };

  const categoriesFromNotes = Array.from(new Set(notes.map(n => n.category).filter(c => c)));
  const categories = Array.from(new Set([...categoriesFromNotes, ...manualCategories])).sort();

  const filteredNotes = notes.filter(note => {
    if (selectedCategory && note.category !== selectedCategory) return false;
    if (showFavoritesOnly && !note.favorite) return false;
    if (searchText) {
      const search = searchText.toLowerCase();
      return note.title.toLowerCase().includes(search) ||
             note.content.toLowerCase().includes(search);
    }
    return true;
  }).sort((a, b) => {
    // Sort favorites first, then by modified date (newest first)
    if (a.favorite !== b.favorite) {
      return a.favorite ? -1 : 1;
    }
    return b.modified - a.modified;
  });

  const selectedNote = notes.find(n => n.draftId === selectedNoteDraftId) || null;
  const hasUnsavedChanges = Boolean(selectedNote?.pendingSave);

  if (!isLoggedIn) {
    return <LoginView onLogin={handleLogin} />;
  }

  return (
    <div className="flex h-screen">
      {!isFocusMode && (
        <>
          <CategoriesSidebar
            categories={categories}
            selectedCategory={selectedCategory}
            onSelectCategory={setSelectedCategory}
            onCreateCategory={handleCreateCategory}
            onRenameCategory={handleRenameCategory}
            isCollapsed={isCategoriesCollapsed}
            onToggleCollapse={() => setIsCategoriesCollapsed(!isCategoriesCollapsed)}
            username={username}
            onLogout={handleLogout}
            theme={theme}
            onThemeChange={handleThemeChange}
            editorFont={editorFont}
            onEditorFontChange={handleEditorFontChange}
            editorFontSize={editorFontSize}
            onEditorFontSizeChange={handleEditorFontSizeChange}
            previewFont={previewFont}
            onPreviewFontChange={handlePreviewFontChange}
            previewFontSize={previewFontSize}
            onPreviewFontSizeChange={handlePreviewFontSizeChange}
          />
          <NotesList
            notes={filteredNotes}
            selectedNoteDraftId={selectedNoteDraftId}
            onSelectNote={handleSelectNote}
            onCreateNote={handleCreateNote}
            onDeleteNote={handleDeleteNote}
            onSync={syncNotes}
            searchText={searchText}
            onSearchChange={setSearchText}
            showFavoritesOnly={showFavoritesOnly}
            onToggleFavorites={() => setShowFavoritesOnly(!showFavoritesOnly)}
            hasUnsavedChanges={hasUnsavedChanges}
            syncStatus={syncStatus}
            pendingSyncCount={pendingSyncCount}
            isOnline={isOnline}
          />
        </>
      )}
      <NoteEditor
        note={selectedNote}
        onChangeNote={handleDraftChange}
        onSaveNote={handleManualSave}
        onDiscardNote={handleDiscardNote}
        onToggleFavorite={handleToggleFavorite}
        categories={categories}
        isFocusMode={isFocusMode}
        onToggleFocusMode={() => setIsFocusMode(!isFocusMode)}
        editorFont={editorFont}
        editorFontSize={editorFontSize}
        previewFont={previewFont}
        previewFontSize={previewFontSize}
        api={api}
      />
    </div>
  );
}

function App() {
  const params = new URLSearchParams(window.location.search);
  const printJobId = params.get(PRINT_EXPORT_QUERY_PARAM);

  if (printJobId) {
    return (
      <Suspense fallback={<div className="min-h-screen bg-gray-100 px-8 py-12 text-gray-900">Preparing print view...</div>}>
        <LazyPrintView jobId={printJobId} />
      </Suspense>
    );
  }

  return <MainApp />;
}

export default App;
