/**
 * Main application layout and orchestration for document and settings workspaces.
 */
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import type { JSX } from 'react';
import { LogOut, User } from 'lucide-react';

import ActionModal from './components/ActionModal';
import DocumentGrid from './components/DocumentGrid';
import LoginScreen from './components/LoginScreen';
import DocumentViewer from './components/DocumentViewer';
import PathInput from './components/PathInput';
import ProcessingLogPanel from './components/ProcessingLogPanel';
import SearchFiltersBar from './components/SearchFiltersBar';
import SettingsScreen from './components/SettingsScreen';
import UploadSurface from './components/UploadSurface';
import {
  clearProcessingLogs,
  downloadBlobFile,
  deleteDocument,
  exportContentsMarkdown,
  getCurrentAuthSession,
  getAppSettings,
  listDocuments,
  listPaths,
  listProcessingLogs,
  listTags,
  listTypes,
  loginWithPassword,
  logoutCurrentSession,
  resetAppSettings,
  searchDocuments,
  trashDocument,
  updateAppSettings,
  uploadDocuments,
} from './lib/api';
import type { AppSettings, AppSettingsUpdate, AuthUser, DmsDocument, ProcessingLogEntry } from './types';

type AppScreen = 'documents' | 'settings';
type DocumentView = 'active' | 'trash';
type AuthPhase = 'checking' | 'unauthenticated' | 'authenticated';

interface DialogOption {
  key: string;
  label: string;
  tone?: 'neutral' | 'primary' | 'warning' | 'danger';
}

interface DialogState {
  title: string;
  message: string;
  options: DialogOption[];
}

/**
 * Defines the root DMS frontend component.
 */
export default function App(): JSX.Element {
  const DEFAULT_PAGE_SIZE = 12;
  const [authPhase, setAuthPhase] = useState<AuthPhase>('checking');
  const [authUser, setAuthUser] = useState<AuthUser | null>(null);
  const [authError, setAuthError] = useState<string | null>(null);
  const [isAuthenticating, setIsAuthenticating] = useState<boolean>(false);
  const [screen, setScreen] = useState<AppScreen>('documents');
  const [documentView, setDocumentView] = useState<DocumentView>('active');
  const [documents, setDocuments] = useState<DmsDocument[]>([]);
  const [totalDocuments, setTotalDocuments] = useState<number>(0);
  const [currentPage, setCurrentPage] = useState<number>(1);
  const [isLoading, setIsLoading] = useState<boolean>(false);
  const [isUploading, setIsUploading] = useState<boolean>(false);
  const [searchText, setSearchText] = useState<string>('');
  const [activeSearchQuery, setActiveSearchQuery] = useState<string>('');
  const [selectedDocumentId, setSelectedDocumentId] = useState<string | null>(null);
  const [selectedDocumentIds, setSelectedDocumentIds] = useState<string[]>([]);
  const [exportPathInput, setExportPathInput] = useState<string>('');
  const [tagFilter, setTagFilter] = useState<string>('');
  const [typeFilter, setTypeFilter] = useState<string>('');
  const [pathFilter, setPathFilter] = useState<string>('');
  const [processedFrom, setProcessedFrom] = useState<string>('');
  const [processedTo, setProcessedTo] = useState<string>('');
  const [knownTags, setKnownTags] = useState<string[]>([]);
  const [knownPaths, setKnownPaths] = useState<string[]>([]);
  const [knownTypes, setKnownTypes] = useState<string[]>([]);
  const [appSettings, setAppSettings] = useState<AppSettings | null>(null);
  const [settingsSaveAction, setSettingsSaveAction] = useState<(() => Promise<void>) | null>(null);
  const [processingLogs, setProcessingLogs] = useState<ProcessingLogEntry[]>([]);
  const [isLoadingLogs, setIsLoadingLogs] = useState<boolean>(false);
  const [isClearingLogs, setIsClearingLogs] = useState<boolean>(false);
  const [processingLogError, setProcessingLogError] = useState<string | null>(null);
  const [isSavingSettings, setIsSavingSettings] = useState<boolean>(false);
  const [isRunningBulkAction, setIsRunningBulkAction] = useState<boolean>(false);
  const [error, setError] = useState<string | null>(null);
  const [dialogState, setDialogState] = useState<DialogState | null>(null);
  const dialogResolverRef = useRef<((value: string) => void) | null>(null);
  const isAdmin = authUser?.role === 'admin';

  const pageSize = useMemo(() => {
    const configured = appSettings?.display?.cards_per_page;
    if (!configured || Number.isNaN(configured)) {
      return DEFAULT_PAGE_SIZE;
    }
    return Math.max(1, Math.min(200, configured));
  }, [appSettings]);

  const presentDialog = useCallback((title: string, message: string, options: DialogOption[]): Promise<string> => {
    setDialogState({ title, message, options });
    return new Promise<string>((resolve) => {
      dialogResolverRef.current = resolve;
    });
  }, []);

  const requestConfirmation = useCallback(
    async (title: string, message: string, confirmLabel = 'Confirm'): Promise<boolean> => {
      const choice = await presentDialog(title, message, [
        { key: 'cancel', label: 'Cancel', tone: 'neutral' },
        { key: 'confirm', label: confirmLabel, tone: 'danger' },
      ]);
      return choice === 'confirm';
    },
    [presentDialog],
  );

  const closeDialog = useCallback((key: string): void => {
    const resolver = dialogResolverRef.current;
    dialogResolverRef.current = null;
    setDialogState(null);
    if (resolver) {
      resolver(key);
    }
  }, []);

  /**
   * Clears workspace state when authentication context changes or session is revoked.
   */
  const resetApplicationState = useCallback((): void => {
    setScreen('documents');
    setDocumentView('active');
    setDocuments([]);
    setTotalDocuments(0);
    setCurrentPage(1);
    setSearchText('');
    setActiveSearchQuery('');
    setSelectedDocumentId(null);
    setSelectedDocumentIds([]);
    setExportPathInput('');
    setTagFilter('');
    setTypeFilter('');
    setPathFilter('');
    setProcessedFrom('');
    setProcessedTo('');
    setKnownTags([]);
    setKnownPaths([]);
    setKnownTypes([]);
    setAppSettings(null);
    setSettingsSaveAction(null);
    setProcessingLogs([]);
    setProcessingLogError(null);
    setError(null);
  }, []);

  /**
   * Exchanges submitted credentials for a server-issued session and activates the app shell.
   */
  const handleLogin = useCallback(async (username: string, password: string): Promise<void> => {
    setIsAuthenticating(true);
    setAuthError(null);
    try {
      const payload = await loginWithPassword(username, password);
      setAuthUser(payload.user);
      setAuthPhase('authenticated');
      setError(null);
    } catch (caughtError) {
      const message = caughtError instanceof Error ? caughtError.message : 'Login failed';
      setAuthError(message);
      setAuthUser(null);
      setAuthPhase('unauthenticated');
      resetApplicationState();
    } finally {
      setIsAuthenticating(false);
    }
  }, [resetApplicationState]);

  /**
   * Revokes current session server-side when possible and always clears local auth state.
   */
  const handleLogout = useCallback(async (): Promise<void> => {
    setError(null);
    try {
      await logoutCurrentSession();
    } catch {}
    setAuthUser(null);
    setAuthError(null);
    setAuthPhase('unauthenticated');
    resetApplicationState();
  }, [resetApplicationState]);

  const loadCatalogs = useCallback(async (): Promise<void> => {
    const [tags, paths, types] = await Promise.all([listTags(true), listPaths(true), listTypes(true)]);
    setKnownTags(tags);
    setKnownPaths(paths);
    setKnownTypes(types);
  }, []);

  const loadDocuments = useCallback(async (options?: { silent?: boolean }): Promise<void> => {
    const silent = options?.silent ?? false;
    if (!silent) {
      setIsLoading(true);
      setError(null);
    }
    try {
      const offset = (currentPage - 1) * pageSize;
      const search = activeSearchQuery.trim();
      const filters = {
        pathFilter,
        tagFilter,
        typeFilter,
        processedFrom,
        processedTo,
      };
      const payload =
        search.length > 0
          ? await searchDocuments(search, {
              limit: pageSize,
              offset,
              onlyTrashed: documentView === 'trash',
              ...filters,
            })
          : await listDocuments({
              limit: pageSize,
              offset,
              onlyTrashed: documentView === 'trash',
              ...filters,
            });

      setDocuments(payload.items);
      setTotalDocuments(payload.total);
      if (payload.items.length === 0) {
        setSelectedDocumentId(null);
      } else if (!payload.items.some((item) => item.id === selectedDocumentId)) {
        setSelectedDocumentId(payload.items[0].id);
      }
      setSelectedDocumentIds((current) => current.filter((documentId) => payload.items.some((item) => item.id === documentId)));
    } catch (caughtError) {
      setError(caughtError instanceof Error ? caughtError.message : 'Failed to load documents');
    } finally {
      if (!silent) {
        setIsLoading(false);
      }
    }
  }, [
    activeSearchQuery,
    currentPage,
    documentView,
    pageSize,
    pathFilter,
    processedFrom,
    processedTo,
    selectedDocumentId,
    tagFilter,
    typeFilter,
  ]);

  const loadSettings = useCallback(async (): Promise<void> => {
    if (!isAdmin) {
      setAppSettings(null);
      return;
    }
    setError(null);
    try {
      const payload = await getAppSettings();
      setAppSettings(payload);
    } catch (caughtError) {
      setError(caughtError instanceof Error ? caughtError.message : 'Failed to load settings');
    }
  }, [isAdmin]);

  const loadProcessingTimeline = useCallback(async (options?: { silent?: boolean }): Promise<void> => {
    if (!isAdmin) {
      setProcessingLogs([]);
      setProcessingLogError(null);
      return;
    }
    const silent = options?.silent ?? false;
    if (!silent) {
      setIsLoadingLogs(true);
    }
    try {
      const payload = await listProcessingLogs({ limit: 180 });
      setProcessingLogs(payload.items);
      setProcessingLogError(null);
    } catch (caughtError) {
      setProcessingLogError(caughtError instanceof Error ? caughtError.message : 'Failed to load processing logs');
    } finally {
      if (!silent) {
        setIsLoadingLogs(false);
      }
    }
  }, [isAdmin]);

  useEffect(() => {
    const resolveSession = async (): Promise<void> => {
      try {
        const sessionPayload = await getCurrentAuthSession();
        setAuthUser(sessionPayload.user);
        setAuthError(null);
        setAuthPhase('authenticated');
      } catch {
        setAuthUser(null);
        setAuthPhase('unauthenticated');
        resetApplicationState();
      }
    };
    void resolveSession();
  }, [resetApplicationState]);

  useEffect(() => {
    if (authPhase !== 'authenticated') {
      return;
    }
    const bootstrap = async (): Promise<void> => {
      try {
        if (isAdmin) {
          await Promise.all([loadDocuments(), loadCatalogs(), loadSettings(), loadProcessingTimeline()]);
          return;
        }
        await Promise.all([loadDocuments(), loadCatalogs()]);
        setAppSettings(null);
        setProcessingLogs([]);
        setProcessingLogError(null);
      } catch (caughtError) {
        setError(caughtError instanceof Error ? caughtError.message : 'Failed to initialize application');
      }
    };
    void bootstrap();
  }, [authPhase, isAdmin, loadCatalogs, loadDocuments, loadProcessingTimeline, loadSettings]);

  useEffect(() => {
    setSelectedDocumentIds([]);
    setCurrentPage(1);
  }, [documentView, pageSize]);

  useEffect(() => {
    if (!isAdmin && screen === 'settings') {
      setScreen('documents');
    }
  }, [isAdmin, screen]);

  useEffect(() => {
    if (authPhase !== 'authenticated') {
      return;
    }
    if (screen !== 'documents') {
      return;
    }
    void loadDocuments();
  }, [authPhase, loadDocuments, screen]);

  useEffect(() => {
    if (authPhase !== 'authenticated') {
      return;
    }
    if (screen !== 'documents') {
      return;
    }
    const pollInterval = window.setInterval(() => {
      void loadDocuments({ silent: true });
    }, 3000);
    return () => window.clearInterval(pollInterval);
  }, [authPhase, loadDocuments, screen]);

  useEffect(() => {
    if (authPhase !== 'authenticated' || !isAdmin) {
      return;
    }
    if (screen !== 'documents') {
      return;
    }
    void loadProcessingTimeline();
    const pollInterval = window.setInterval(() => {
      void loadProcessingTimeline({ silent: true });
    }, 1500);
    return () => window.clearInterval(pollInterval);
  }, [authPhase, isAdmin, loadProcessingTimeline, screen]);

  const selectedDocument = useMemo(
    () => documents.find((document) => document.id === selectedDocumentId) ?? null,
    [documents, selectedDocumentId],
  );
  const totalPages = useMemo(() => Math.max(1, Math.ceil(totalDocuments / pageSize)), [pageSize, totalDocuments]);
  const allVisibleSelected = useMemo(() => documents.length > 0 && documents.every((document) => selectedDocumentIds.includes(document.id)), [documents, selectedDocumentIds]);
  const isProcessingActive = useMemo(() => documents.some((document) => document.status === 'queued'), [documents]);
  const typingAnimationEnabled = appSettings?.display?.log_typing_animation_enabled ?? true;
  const hasActiveSearch = Boolean(
    activeSearchQuery.trim() || tagFilter || typeFilter || pathFilter || processedFrom || processedTo,
  );

  const handleUpload = useCallback(async (files: File[]): Promise<void> => {
    if (files.length === 0) {
      return;
    }
    setIsUploading(true);
    setError(null);
    try {
      const uploadDefaults = appSettings?.upload_defaults ?? { logical_path: 'Inbox', tags: [] };
      const tagsCsv = uploadDefaults.tags.join(',');
      const firstAttempt = await uploadDocuments(files, {
        logicalPath: uploadDefaults.logical_path,
        tags: tagsCsv,
        conflictMode: 'ask',
      });

      if (firstAttempt.conflicts.length > 0) {
        const choice = await presentDialog(
          'Upload Conflicts Detected',
          `${firstAttempt.conflicts.length} file(s) already exist. Replace existing records or keep duplicates?`,
          [
            { key: 'duplicate', label: 'Keep Duplicates', tone: 'neutral' },
            { key: 'replace', label: 'Replace Existing', tone: 'warning' },
          ],
        );
        await uploadDocuments(files, {
          logicalPath: uploadDefaults.logical_path,
          tags: tagsCsv,
          conflictMode: choice === 'replace' ? 'replace' : 'duplicate',
        });
      }

      if (isAdmin) {
        await Promise.all([loadDocuments(), loadCatalogs(), loadProcessingTimeline()]);
      } else {
        await Promise.all([loadDocuments(), loadCatalogs()]);
      }
    } catch (caughtError) {
      setError(caughtError instanceof Error ? caughtError.message : 'Upload failed');
    } finally {
      setIsUploading(false);
    }
  }, [appSettings, isAdmin, loadCatalogs, loadDocuments, loadProcessingTimeline, presentDialog]);

  const handleSearch = useCallback(async (): Promise<void> => {
    setSelectedDocumentIds([]);
    setCurrentPage(1);
    setActiveSearchQuery(searchText.trim());
  }, [searchText]);

  const handleResetSearch = useCallback((): void => {
    setSearchText('');
    setActiveSearchQuery('');
    setTagFilter('');
    setTypeFilter('');
    setPathFilter('');
    setProcessedFrom('');
    setProcessedTo('');
    setCurrentPage(1);
    setSelectedDocumentIds([]);
  }, []);

  const handleDocumentUpdated = useCallback((updated: DmsDocument): void => {
    setDocuments((current) => {
      const shouldAppear = documentView === 'trash' ? updated.status === 'trashed' : updated.status !== 'trashed';
      if (!shouldAppear) {
        return current.filter((document) => document.id !== updated.id);
      }
      const exists = current.some((document) => document.id === updated.id);
      if (!exists) {
        return [updated, ...current];
      }
      return current.map((document) => (document.id === updated.id ? updated : document));
    });
    if (documentView === 'trash' && updated.status !== 'trashed') {
      setSelectedDocumentIds((current) => current.filter((id) => id !== updated.id));
      if (selectedDocumentId === updated.id) {
        setSelectedDocumentId(null);
      }
    }
    if (documentView === 'active' && updated.status === 'trashed') {
      setSelectedDocumentIds((current) => current.filter((id) => id !== updated.id));
      if (selectedDocumentId === updated.id) {
        setSelectedDocumentId(null);
      }
    }
    void loadCatalogs();
  }, [documentView, loadCatalogs, selectedDocumentId]);

  const handleDocumentDeleted = useCallback((documentId: string): void => {
    setDocuments((current) => current.filter((document) => document.id !== documentId));
    setSelectedDocumentIds((current) => current.filter((id) => id !== documentId));
    if (selectedDocumentId === documentId) {
      setSelectedDocumentId(null);
    }
    void loadCatalogs();
  }, [loadCatalogs, selectedDocumentId]);

  const handleToggleChecked = useCallback((documentId: string, checked: boolean): void => {
    setSelectedDocumentIds((current) => {
      if (checked && !current.includes(documentId)) {
        return [...current, documentId];
      }
      if (!checked) {
        return current.filter((item) => item !== documentId);
      }
      return current;
    });
  }, []);

  const handleToggleSelectAllVisible = useCallback((): void => {
    if (documents.length === 0) {
      return;
    }
    if (allVisibleSelected) {
      setSelectedDocumentIds([]);
      return;
    }
    setSelectedDocumentIds(documents.map((document) => document.id));
  }, [allVisibleSelected, documents]);

  const handleTrashSelected = useCallback(async (): Promise<void> => {
    if (selectedDocumentIds.length === 0) {
      return;
    }
    setIsRunningBulkAction(true);
    setError(null);
    try {
      await Promise.all(selectedDocumentIds.map((documentId) => trashDocument(documentId)));
      setSelectedDocumentIds([]);
      await Promise.all([loadDocuments(), loadCatalogs()]);
    } catch (caughtError) {
      setError(caughtError instanceof Error ? caughtError.message : 'Failed to trash selected documents');
    } finally {
      setIsRunningBulkAction(false);
    }
  }, [loadCatalogs, loadDocuments, selectedDocumentIds]);

  const handleTrashDocumentCard = useCallback(async (documentId: string): Promise<void> => {
    if (documentView === 'trash') {
      return;
    }
    setError(null);
    try {
      await trashDocument(documentId);
      setSelectedDocumentIds((current) => current.filter((id) => id !== documentId));
      if (selectedDocumentId === documentId) {
        setSelectedDocumentId(null);
      }
      await Promise.all([loadDocuments(), loadCatalogs()]);
    } catch (caughtError) {
      const message = caughtError instanceof Error ? caughtError.message : 'Failed to trash document';
      setError(message);
      throw caughtError instanceof Error ? caughtError : new Error(message);
    }
  }, [documentView, loadCatalogs, loadDocuments, selectedDocumentId]);

  const handleDeleteSelected = useCallback(async (): Promise<void> => {
    if (selectedDocumentIds.length === 0) {
      return;
    }
    const confirmed = await requestConfirmation(
      'Delete Selected Documents Permanently',
      'This removes selected documents and stored files permanently.',
      'Delete Permanently',
    );
    if (!confirmed) {
      return;
    }
    setIsRunningBulkAction(true);
    setError(null);
    try {
      await Promise.all(selectedDocumentIds.map((documentId) => deleteDocument(documentId)));
      setSelectedDocumentIds([]);
      await Promise.all([loadDocuments(), loadCatalogs()]);
    } catch (caughtError) {
      setError(caughtError instanceof Error ? caughtError.message : 'Failed to delete selected documents');
    } finally {
      setIsRunningBulkAction(false);
    }
  }, [loadCatalogs, loadDocuments, requestConfirmation, selectedDocumentIds]);

  const handleExportSelected = useCallback(async (): Promise<void> => {
    if (selectedDocumentIds.length === 0) {
      return;
    }
    setIsRunningBulkAction(true);
    setError(null);
    try {
      const result = await exportContentsMarkdown({
        document_ids: selectedDocumentIds,
        only_trashed: documentView === 'trash',
        include_trashed: false,
      });
      downloadBlobFile(result.blob, result.filename);
    } catch (caughtError) {
      setError(caughtError instanceof Error ? caughtError.message : 'Failed to export selected markdown files');
    } finally {
      setIsRunningBulkAction(false);
    }
  }, [documentView, selectedDocumentIds]);

  const handleExportPath = useCallback(async (): Promise<void> => {
    const trimmedPrefix = exportPathInput.trim();
    if (!trimmedPrefix) {
      setError('Enter a path prefix before exporting by path');
      return;
    }
    setIsRunningBulkAction(true);
    setError(null);
    try {
      const result = await exportContentsMarkdown({
        path_prefix: trimmedPrefix,
        only_trashed: documentView === 'trash',
        include_trashed: false,
      });
      downloadBlobFile(result.blob, result.filename);
    } catch (caughtError) {
      setError(caughtError instanceof Error ? caughtError.message : 'Failed to export path markdown files');
    } finally {
      setIsRunningBulkAction(false);
    }
  }, [documentView, exportPathInput]);

  const handleSaveSettings = useCallback(async (payload: AppSettingsUpdate): Promise<void> => {
    setIsSavingSettings(true);
    setError(null);
    try {
      const updated = await updateAppSettings(payload);
      setAppSettings(updated);
      await loadCatalogs();
    } catch (caughtError) {
      setError(caughtError instanceof Error ? caughtError.message : 'Failed to save settings');
      throw caughtError;
    } finally {
      setIsSavingSettings(false);
    }
  }, [loadCatalogs]);

  const handleSaveSettingsFromHeader = useCallback(async (): Promise<void> => {
    if (!settingsSaveAction) {
      setError('Settings are still loading');
      return;
    }
    await settingsSaveAction();
  }, [settingsSaveAction]);

  const handleRegisterSettingsSaveAction = useCallback((action: (() => Promise<void>) | null): void => {
    setSettingsSaveAction(() => action);
  }, []);

  const handleResetSettings = useCallback(async (): Promise<void> => {
    const confirmed = await requestConfirmation(
      'Reset Settings',
      'This resets all settings to defaults and overwrites current values.',
      'Reset Settings',
    );
    if (!confirmed) {
      return;
    }
    setIsSavingSettings(true);
    setError(null);
    try {
      const updated = await resetAppSettings();
      setAppSettings(updated);
      await loadCatalogs();
    } catch (caughtError) {
      setError(caughtError instanceof Error ? caughtError.message : 'Failed to reset settings');
    } finally {
      setIsSavingSettings(false);
    }
  }, [loadCatalogs, requestConfirmation]);

  const handleClearProcessingLogs = useCallback(async (): Promise<void> => {
    const confirmed = await requestConfirmation(
      'Clear Processing Log',
      'This clears the full diagnostics timeline.',
      'Clear Logs',
    );
    if (!confirmed) {
      return;
    }
    setIsClearingLogs(true);
    try {
      await clearProcessingLogs();
      await loadProcessingTimeline();
      setProcessingLogError(null);
    } catch (caughtError) {
      setProcessingLogError(caughtError instanceof Error ? caughtError.message : 'Failed to clear processing logs');
    } finally {
      setIsClearingLogs(false);
    }
  }, [loadProcessingTimeline, requestConfirmation]);

  const handleFilterPathFromCard = useCallback((pathValue: string): void => {
    setActiveSearchQuery('');
    setSearchText('');
    setTagFilter('');
    setTypeFilter('');
    setProcessedFrom('');
    setProcessedTo('');
    setPathFilter(pathValue);
    setCurrentPage(1);
  }, []);

  const handleFilterTagFromCard = useCallback((tagValue: string): void => {
    setActiveSearchQuery('');
    setSearchText('');
    setPathFilter('');
    setTypeFilter('');
    setProcessedFrom('');
    setProcessedTo('');
    setTagFilter(tagValue);
    setCurrentPage(1);
  }, []);

  if (authPhase === 'checking') {
    return (
      <main className="auth-shell">
        <section className="auth-card">
          <h1>LedgerDock</h1>
          <p>Checking current session...</p>
        </section>
      </main>
    );
  }

  if (authPhase !== 'authenticated') {
    return <LoginScreen error={authError} isSubmitting={isAuthenticating} onSubmit={handleLogin} />;
  }

  return (
    <main className="app-shell">
      <header className="topbar">
        <div className="topbar-inner">
          <div className="topbar-brand">
            <h1>LedgerDock</h1>
            <p>Document command deck for OCR, routing intelligence, and controlled metadata ops.</p>
            <p className="topbar-auth-status">
              <User className="topbar-user-icon" aria-hidden="true" />
              You are currently signed in as <span className="topbar-current-username">{authUser?.username}</span>
            </p>
          </div>
          <div className="topbar-controls">
            <div className="topbar-primary-row">
              <div className="topbar-nav-group">
                <button
                  type="button"
                  className={screen === 'documents' && documentView === 'active' ? 'active-view-button' : 'secondary-action'}
                  onClick={() => {
                    setScreen('documents');
                    setDocumentView('active');
                  }}
                >
                  Documents
                </button>
                <button
                  type="button"
                  className={screen === 'documents' && documentView === 'trash' ? 'active-view-button' : 'secondary-action'}
                  onClick={() => {
                    setScreen('documents');
                    setDocumentView('trash');
                  }}
                >
                  Trash
                </button>
                {isAdmin && (
                  <button
                    type="button"
                    className={screen === 'settings' ? 'active-view-button' : 'secondary-action'}
                    onClick={() => setScreen('settings')}
                  >
                    Settings
                  </button>
                )}
              </div>
              <button
                type="button"
                className="secondary-action topbar-icon-action"
                onClick={() => void handleLogout()}
                aria-label="Sign out"
              >
                <LogOut className="topbar-signout-icon" aria-hidden="true" />
              </button>
            </div>

            {screen === 'documents' && (
              <div className="topbar-document-group">
                <UploadSurface onUploadRequested={handleUpload} isUploading={isUploading} variant="inline" />
              </div>
            )}

            {screen === 'settings' && isAdmin && (
              <div className="topbar-settings-group">
                <button type="button" className="secondary-action" onClick={() => void handleResetSettings()} disabled={isSavingSettings}>
                  Reset To Defaults
                </button>
                <button type="button" onClick={() => void handleSaveSettingsFromHeader()} disabled={isSavingSettings || !settingsSaveAction}>
                  {isSavingSettings ? 'Saving Settings...' : 'Save Settings'}
                </button>
              </div>
            )}
          </div>
        </div>
      </header>

      {error && <p className="error-banner">{error}</p>}

      {screen === 'settings' && isAdmin && (
        <SettingsScreen
          settings={appSettings}
          isSaving={isSavingSettings}
          knownTags={knownTags}
          knownPaths={knownPaths}
          onSave={handleSaveSettings}
          onRegisterSaveAction={handleRegisterSettingsSaveAction}
        />
      )}

      {screen === 'documents' && (
        <>
          <section className="layout-grid">
            <div>
              <div className="panel-header document-panel-header">
                <div className="document-panel-title-row">
                  <h2>{documentView === 'trash' ? 'Trashed Documents' : 'Documents'}</h2>
                  <p>{isLoading ? 'Loading...' : `${totalDocuments} document(s)`}</p>
                </div>
                <SearchFiltersBar
                  searchText={searchText}
                  onSearchTextChange={setSearchText}
                  onSearchSubmit={() => void handleSearch()}
                  onReset={handleResetSearch}
                  hasActiveSearch={hasActiveSearch}
                  knownTags={knownTags}
                  knownPaths={knownPaths}
                  knownTypes={knownTypes}
                  tagFilter={tagFilter}
                  onTagFilterChange={(value) => {
                    setTagFilter(value);
                    setCurrentPage(1);
                  }}
                  typeFilter={typeFilter}
                  onTypeFilterChange={(value) => {
                    setTypeFilter(value);
                    setCurrentPage(1);
                  }}
                  pathFilter={pathFilter}
                  onPathFilterChange={(value) => {
                    setPathFilter(value);
                    setCurrentPage(1);
                  }}
                  processedFrom={processedFrom}
                  onProcessedFromChange={(value) => {
                    setProcessedFrom(value);
                    setCurrentPage(1);
                  }}
                  processedTo={processedTo}
                  onProcessedToChange={(value) => {
                    setProcessedTo(value);
                    setCurrentPage(1);
                  }}
                  isLoading={isLoading}
                />
                <div className="document-toolbar-row">
                  <div className="document-toolbar-selection">
                    <span className="small">Select:</span>
                    <button type="button" className="secondary-action" onClick={handleToggleSelectAllVisible} disabled={documents.length === 0}>
                      {allVisibleSelected ? 'Unselect Page' : 'Select Page'}
                    </button>
                    <span className="small">Selected {selectedDocumentIds.length}</span>
                    {documentView !== 'trash' && (
                      <button type="button" className="warning-action" onClick={() => void handleTrashSelected()} disabled={isRunningBulkAction || selectedDocumentIds.length === 0}>
                        Move To Trash
                      </button>
                    )}
                    {documentView === 'trash' && (
                      <button type="button" className="danger-action" onClick={() => void handleDeleteSelected()} disabled={isRunningBulkAction || selectedDocumentIds.length === 0}>
                        Delete Permanently
                      </button>
                    )}
                    <button type="button" className="secondary-action" onClick={() => void handleExportSelected()} disabled={isRunningBulkAction || selectedDocumentIds.length === 0}>
                      Export Selected MD
                    </button>
                  </div>
                  <div className="document-toolbar-export-path">
                    <PathInput value={exportPathInput} onChange={setExportPathInput} placeholder="Export by path prefix" suggestions={knownPaths} />
                    <button type="button" className="secondary-action" onClick={() => void handleExportPath()} disabled={isRunningBulkAction}>
                      Export Path MD
                    </button>
                  </div>
                </div>
              </div>
              <div className="document-pagination-strip">
                <div className="document-toolbar-pagination compact-pagination">
                  <button type="button" className="secondary-action" onClick={() => setCurrentPage(1)} disabled={isLoading || currentPage <= 1}>
                    First
                  </button>
                  <button type="button" className="secondary-action" onClick={() => setCurrentPage((current) => Math.max(1, current - 1))} disabled={isLoading || currentPage <= 1}>
                    Prev
                  </button>
                  <span className="small">Page {currentPage} / {totalPages}</span>
                  <button type="button" className="secondary-action" onClick={() => setCurrentPage((current) => Math.min(totalPages, current + 1))} disabled={isLoading || currentPage >= totalPages}>
                    Next
                  </button>
                  <button type="button" className="secondary-action" onClick={() => setCurrentPage(totalPages)} disabled={isLoading || currentPage >= totalPages}>
                    Last
                  </button>
                </div>
              </div>
              <DocumentGrid
                documents={documents}
                selectedDocumentId={selectedDocumentId}
                selectedDocumentIds={selectedDocumentIds}
                isTrashView={documentView === 'trash'}
                onSelect={(document) => setSelectedDocumentId(document.id)}
                onToggleChecked={handleToggleChecked}
                onTrashDocument={handleTrashDocumentCard}
                onFilterPath={handleFilterPathFromCard}
                onFilterTag={handleFilterTagFromCard}
              />
            </div>
            <DocumentViewer
              document={selectedDocument}
              isTrashView={documentView === 'trash'}
              existingTags={knownTags}
              existingPaths={knownPaths}
              onDocumentUpdated={handleDocumentUpdated}
              onDocumentDeleted={handleDocumentDeleted}
              requestConfirmation={requestConfirmation}
            />
          </section>
          {isAdmin && processingLogError && <p className="error-banner">{processingLogError}</p>}
          {isAdmin && (
            <ProcessingLogPanel
              entries={processingLogs}
              isLoading={isLoadingLogs}
              isClearing={isClearingLogs}
              selectedDocumentId={selectedDocumentId}
              isProcessingActive={isProcessingActive}
              typingAnimationEnabled={typingAnimationEnabled}
              onClear={() => void handleClearProcessingLogs()}
            />
          )}
        </>
      )}

      <ActionModal
        isOpen={dialogState !== null}
        title={dialogState?.title ?? ''}
        message={dialogState?.message ?? ''}
        options={dialogState?.options ?? []}
        onSelect={closeDialog}
        onDismiss={() => closeDialog('cancel')}
      />
    </main>
  );
}
