import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import {
  ViewListIcon,
  ViewGridIcon,
  IconFileStack,
  RefreshIcon,
  MinusVerticalIcon,
  InfoIcon,
  FoldersIcon,
  FoldersOffIcon,
  SortAscendingLettersIcon,
  SortDescendingLettersIcon,
} from '../ui/icons';
import QuickAddMenu from '../ui/QuickAddMenu';
import BreadcrumbTrail from '../ui/BreadcrumbTrail';
import createWorkspaceSurfaceConfig from './workspaceHeader';
import DetailPanel from '../detail/DetailPanel';
import DocumentsGrid from './DocumentsGrid';
import DocumentsList from './DocumentsList';
import { isTagTransferEvent } from './tagTransfer';
import SelectionFloatingActions from './SelectionFloatingActions';
import PreviewZoomOverlay from '../detail/PreviewZoomOverlay';
import { useAssetNavigator } from '../hooks/useAssetNavigator';
import { isPointerModifierEvent, isPrimaryPointerEvent } from './useEntryPointer';

const DEFAULT_GRID_ICON_SIZE = 144;

const EntryType = {
  folder: 'folder',
  document: 'document',
};

const SORT_OPTIONS = [
  { value: 'title', label: 'Title' },
  { value: 'issued_at', label: 'Issued date' },
  { value: 'created_at', label: 'Added' },
  { value: 'updated_at', label: 'Updated date' },
];

const SORT_LABEL_LOOKUP = SORT_OPTIONS.reduce((accumulator, option) => {
  const next = accumulator;
  next[option.value] = option.label;
  return next;
}, {});

const DocumentsPanel = ({
  currentFolderName,
  breadcrumbs,
  onRefresh,
  subfolders,
  documents,
  searchResults,
  isFilterActive = false,
  onFolderSelect,
  onFolderDrop,
  onFolderDragOver,
  onFolderDragLeave,
  onFolderDragStart,
  onFolderDragEnd,
  draggedFolderId,
  onFolderRename,
  selectedFolderIds = [],
  selectedDocumentIds = [],
  focusedRowKey,
  draggingDocumentIds = [],
  onDocumentDragStart,
  onDocumentDragEnd,
  onDocumentRename,
  onEntryPointer = null,
  onEntrySelection = null,
  onInspectDocument = null,
  tagLookupById,
  activeCorrespondentIds = [],
  onFocusedRowChange,
  ensureAssetUrl = null,
  getDocumentAsset = () => null,
  onTagClick,
  onCorrespondentClick,
  isSearchLoading = false,
  onDocumentTagDrop,
  viewMode = 'list',
  onViewModeChange,
  onClearSelection,
  selectedEntries = [],
  showHeader = true,
}) => {
  const showingSearchResults = searchResults !== null;
  const rows = showingSearchResults ? searchResults : documents;

  const entries = useMemo(() => {
    const list = [];
    if (!showingSearchResults) {
      subfolders.forEach((folder) => {
        if (!folder || !folder.id) {
          return;
        }
        list.push({ type: EntryType.folder, id: folder.id, key: `folder:${folder.id}`, folder });
      });
    }
    rows.forEach((doc) => {
      if (!doc || !doc.id) {
        return;
      }
      list.push({ type: EntryType.document, id: doc.id, key: `document:${doc.id}`, document: doc });
    });
    return list;
  }, [showingSearchResults, subfolders, rows]);

  const selectedSet = useMemo(
    () => new Set(selectedDocumentIds),
    [selectedDocumentIds],
  );
  const selectedFolderSet = useMemo(
    () => new Set(selectedFolderIds || []),
    [selectedFolderIds],
  );
  const draggingSet = useMemo(
    () => new Set(draggingDocumentIds || []),
    [draggingDocumentIds],
  );
  const activeCorrespondentIdSet = useMemo(
    () => new Set(activeCorrespondentIds || []),
    [activeCorrespondentIds],
  );
  const scrollRef = useRef(null);
  const suppressDocumentClickRef = useRef(false);
  const [, forceVisibilityTick] = useState(0);
  const lastScrollNodeRef = useRef(null);
  const assignScrollRef = useCallback((node) => {
    if (lastScrollNodeRef.current === node) {
      return;
    }
    lastScrollNodeRef.current = node;
    scrollRef.current = node;
    if (node) {
      forceVisibilityTick((value) => value + 1);
    }
  }, []);
  const isGridView = viewMode === 'grid';
  const isDeskView = viewMode === 'desk';

  const [previewDocId, setPreviewDocId] = useState(null);

  const previewDoc = useMemo(() => {
    if (!previewDocId) {
      return null;
    }
    return rows.find((doc) => doc?.id === previewDocId) || null;
  }, [previewDocId, rows]);

  useEffect(() => {
    if (previewDocId && !previewDoc) {
      setPreviewDocId(null);
    }
  }, [previewDocId, previewDoc]);

  const previewNavigator = useAssetNavigator({
    document: previewDoc,
    assetType: 'preview',
    ensureAssetUrl,
    getAsset: getDocumentAsset,
    prefetch: 3,
  });

  const {
    currentUrl: previewUrl,
    canGoPrev: previewCanGoPrev,
    canGoNext: previewCanGoNext,
    goPrev: previewGoPrev,
    goNext: previewGoNext,
  } = previewNavigator;

  const previewDisplay = useMemo(() => {
    if (!previewDoc || !previewUrl) {
      return null;
    }
    return {
      url: previewUrl,
      alt: previewDoc.title,
      canGoPrev: Boolean(previewCanGoPrev),
      canGoNext: Boolean(previewCanGoNext),
      goPrev: previewGoPrev,
      goNext: previewGoNext,
    };
  }, [previewDoc, previewUrl, previewCanGoPrev, previewCanGoNext, previewGoPrev, previewGoNext]);

  const closePreviewOverlay = useCallback(() => {
    setPreviewDocId(null);
  }, []);

  const handleDocumentPreviewZoom = useCallback(
    (doc) => {
      if (!doc || !doc.id) {
        return;
      }
      const previewAsset = typeof getDocumentAsset === 'function' ? getDocumentAsset(doc, 'preview') : null;
      if (!previewAsset) {
        return;
      }
      setPreviewDocId(doc.id);
    },
    [getDocumentAsset],
  );

  const handleDocumentActivate = useCallback(
    (doc, event) => {
      if (event) {
        if (typeof event.preventDefault === 'function') {
          event.preventDefault();
        }
        if (typeof event.stopPropagation === 'function') {
          event.stopPropagation();
        }
      }
      handleDocumentPreviewZoom(doc);
    },
    [handleDocumentPreviewZoom],
  );

  const selectedRowKeySet = useMemo(() => new Set(selectedEntries || []), [selectedEntries]);
  const navigableRows = useMemo(
    () => entries.map((entry) => ({ key: entry.key, type: entry.type, id: entry.id })),
    [entries],
  );
  const navigableRowKeys = useMemo(() => navigableRows.map((row) => row.key), [navigableRows]);

  const getEntryByKey = useCallback(
    (rowKey) => entries.find((entry) => entry.key === rowKey) || null,
    [entries],
  );

  const handlePanelFocus = useCallback(() => {
    let resolvedKey = null;

    if (focusedRowKey && navigableRowKeys.includes(focusedRowKey)) {
      resolvedKey = focusedRowKey;
    }

    if (!resolvedKey) {
      for (let index = selectedEntries.length - 1; index >= 0; index -= 1) {
        const candidate = selectedEntries[index];
        if (navigableRowKeys.includes(candidate)) {
          resolvedKey = candidate;
          break;
        }
      }
    }

    if (!resolvedKey && navigableRows.length) {
      resolvedKey = navigableRows[0].key;
    }

    if (!resolvedKey) {
      return;
    }

    onFocusedRowChange?.(resolvedKey);

    if (!selectedRowKeySet.has(resolvedKey) && typeof onEntrySelection === 'function') {
      onEntrySelection(resolvedKey, {
        shiftKey: false,
        preventDefault: () => {},
      });
    }
  }, [
    focusedRowKey,
    navigableRowKeys,
    navigableRows,
    onEntrySelection,
    onFocusedRowChange,
    selectedEntries,
    selectedRowKeySet,
  ]);

  const handlePanelKeyDown = useCallback(
    (event) => {
      const { key, shiftKey } = event;
      const triggers = ['ArrowUp', 'ArrowDown', 'Home', 'End', 'Enter', ' ', 'Space', 'Spacebar'];
      if (!triggers.includes(key)) {
        return;
      }

      if (!navigableRows.length) {
        return;
      }

      event.preventDefault();

      let activeKey =
        focusedRowKey && navigableRowKeys.includes(focusedRowKey)
          ? focusedRowKey
          : null;

      if (!activeKey) {
        if (selectedEntries.length) {
          for (let index = selectedEntries.length - 1; index >= 0; index -= 1) {
            const candidate = selectedEntries[index];
            if (navigableRowKeys.includes(candidate)) {
              activeKey = candidate;
              break;
            }
          }
        }

        if (!activeKey) {
          activeKey = key === 'ArrowUp' ? navigableRowKeys[navigableRowKeys.length - 1] : navigableRowKeys[0];
        }
      }

      const currentIndex = navigableRowKeys.indexOf(activeKey);
      const activeRow = currentIndex === -1 ? null : navigableRows[currentIndex];

      if (key === 'Enter' || key === ' ' || key === 'Space' || key === 'Spacebar') {
        if (activeRow) {
          onEntrySelection?.(activeRow.key, event);
          if (activeRow.type === EntryType.folder) {
            onFolderSelect?.(activeRow.id);
          } else {
            const entry = getEntryByKey(activeRow.key);
            if (entry?.document) {
              handleDocumentActivate(entry.document, event);
              onInspectDocument?.(entry.document.id, event);
            }
          }
        }
        return;
      }

      let nextIndex = currentIndex;
      if (key === 'ArrowDown') {
        nextIndex = currentIndex === -1 ? 0 : Math.min(currentIndex + 1, navigableRows.length - 1);
      } else if (key === 'ArrowUp') {
        nextIndex = currentIndex === -1 ? navigableRows.length - 1 : Math.max(currentIndex - 1, 0);
      } else if (key === 'Home') {
        nextIndex = 0;
      } else if (key === 'End') {
        nextIndex = navigableRows.length - 1;
      }

      if (nextIndex === -1 || nextIndex >= navigableRows.length) {
        return;
      }

      const targetRow = navigableRows[nextIndex];
      if (!targetRow) {
        return;
      }

      onFocusedRowChange?.(targetRow.key);
      onEntrySelection?.(targetRow.key, {
        shiftKey,
        preventDefault: () => {},
      });
    },
    [
      focusedRowKey,
      getEntryByKey,
      handleDocumentActivate,
      navigableRowKeys,
      navigableRows,
      onEntrySelection,
      onFocusedRowChange,
      onFolderSelect,
      onInspectDocument,
      selectedEntries,
    ],
  );

  const isListView = viewMode === 'list';
  const gridIconSize = DEFAULT_GRID_ICON_SIZE;
  const handleSetViewMode = useCallback(
    (nextMode) => {
      if (!onViewModeChange) {
        return;
      }
      onViewModeChange(nextMode);
      if (scrollRef.current) {
        scrollRef.current.scrollTop = 0;
      }
    },
    [onViewModeChange],
  );
  useEffect(() => {
    if (scrollRef.current) {
      scrollRef.current.scrollTop = 0;
    }
  }, [viewMode]);
  const isTagDragEvent = useCallback((event) => isTagTransferEvent(event), []);
  const ensureFocusedRowVisible = useCallback(() => {
    if (!focusedRowKey) return;
    const container = scrollRef.current;
    if (!container) return;
    let selector = null;
    if (focusedRowKey.startsWith('document:')) {
      selector = `#document-row-${focusedRowKey.slice('document:'.length)}`;
    } else if (focusedRowKey.startsWith('folder:')) {
      selector = `#folder-row-${focusedRowKey.slice('folder:'.length)}`;
    }
    if (!selector) {
      return;
    }
    const row = container.querySelector(selector);
    if (!row || !container.contains(row)) {
      return;
    }

    const header = container.querySelector('thead');
    const headerHeight = header ? header.getBoundingClientRect().height : 0;
    const rowTop = row.offsetTop;
    const rowBottom = rowTop + row.offsetHeight;
    const visibleTop = container.scrollTop + headerHeight;
    const visibleBottom = container.scrollTop + container.clientHeight;

    if (rowTop < visibleTop) {
      container.scrollTop = Math.max(rowTop - headerHeight, 0);
      return;
    }

    if (rowBottom > visibleBottom) {
      const nextScrollTop = rowBottom - container.clientHeight;
      container.scrollTop = Math.max(nextScrollTop, 0);
    }
  }, [focusedRowKey]);

  useEffect(() => {
    ensureFocusedRowVisible();
  }, [ensureFocusedRowVisible]);

  const activeDescendantId = useMemo(() => {
    if (!focusedRowKey) return undefined;
    if (focusedRowKey.startsWith('document:')) {
      return `document-row-${focusedRowKey.slice('document:'.length)}`;
    }
    if (focusedRowKey.startsWith('folder:')) {
      return `folder-row-${focusedRowKey.slice('folder:'.length)}`;
    }
    return undefined;
  }, [focusedRowKey]);

  const handleDocumentTagDragOver = useCallback(
    (event) => {
      if (!isTagDragEvent(event)) {
        return;
      }
      event.preventDefault();
      event.dataTransfer.dropEffect = 'copy';
      event.currentTarget.classList.add('tag-drop-target');
    },
    [isTagDragEvent],
  );

  const handleDocumentTagDragLeave = useCallback(
    (event) => {
      if (!isTagDragEvent(event)) {
        return;
      }
      if (event.relatedTarget && event.currentTarget.contains(event.relatedTarget)) {
        return;
      }
      event.currentTarget.classList.remove('tag-drop-target');
    },
    [isTagDragEvent],
  );

  const handleDocumentTagDrop = useCallback(
    (event, documentId) => {
      if (!isTagDragEvent(event)) {
        return;
      }
      event.preventDefault();
      event.stopPropagation();
      event.currentTarget.classList.remove('tag-drop-target');
      const payload =
        event.dataTransfer.getData('application/x-papercrate-tag') ||
        event.dataTransfer.getData('text/papercrate-tag');
      if (!payload) {
        return;
      }
      try {
        const parsed = JSON.parse(payload);
        if (parsed?.id && onDocumentTagDrop) {
          onDocumentTagDrop(documentId, parsed);
        }
      } catch (error) {
        console.warn('[documents] Failed to parse tag drop payload', error);
      }
    },
    [isTagDragEvent, onDocumentTagDrop],
  );

  const handleDocumentClick = useCallback(
    (doc, event) => {
      if (!doc || suppressDocumentClickRef.current) {
        return;
      }

      if (typeof onEntryPointer === 'function') {
        onEntryPointer(
          { type: EntryType.document, id: doc.id, key: `document:${doc.id}`, document: doc },
          event,
        );
      }

      if (
        typeof onInspectDocument === 'function'
        && !isPointerModifierEvent(event)
        && isPrimaryPointerEvent(event)
      ) {
        onInspectDocument(doc.id, event);
      }
    },
    [onEntryPointer, onInspectDocument],
  );

  const handleFolderClick = useCallback(
    (folder, event) => {
      if (!folder) {
        return;
      }

      if (typeof onEntryPointer === 'function') {
        onEntryPointer(
          { type: EntryType.folder, id: folder.id, key: `folder:${folder.id}`, folder },
          event,
        );
      }

      if (
        !isPointerModifierEvent(event)
        && isPrimaryPointerEvent(event)
        && scrollRef.current
      ) {
        scrollRef.current.focus({ preventScroll: true });
        onFocusedRowChange?.(`folder:${folder.id}`);
      }
    },
    [onEntryPointer, onFocusedRowChange],
  );

  const handleDocumentDragStartLocal = useCallback(
    (event, doc) => {
      suppressDocumentClickRef.current = true;
      onDocumentDragStart?.(event, doc);
    },
    [onDocumentDragStart],
  );

  const handleDocumentDragEndLocal = useCallback(
    (event) => {
      onDocumentDragEnd?.(event);
      requestAnimationFrame(() => {
        suppressDocumentClickRef.current = false;
      });
    },
    [onDocumentDragEnd],
  );

  const hasDocumentEntries = useMemo(
    () => entries.some((entry) => entry.type === EntryType.document),
    [entries],
  );
  const showTableRows = entries.length > 0;
  const showDefaultEmptyState = !showingSearchResults && !isFilterActive && entries.length === 0;
  const showListSearchEmptyState = showingSearchResults && !hasDocumentEntries && !isGridView && !isSearchLoading;
  const showGridSearchEmptyState = isGridView && showingSearchResults && !hasDocumentEntries && !isSearchLoading;
  const breadcrumbEntries = useMemo(() => (Array.isArray(breadcrumbs) ? breadcrumbs.filter(Boolean) : []), [breadcrumbs]);
  const trailEntries = useMemo(() => {
    if (!breadcrumbEntries.length) {
      return [{ id: 'current-folder', label: currentFolderName }];
    }
    const lastIndex = breadcrumbEntries.length - 1;
    return breadcrumbEntries.map((crumb, index) => ({
      id: crumb.id ?? index,
      label: crumb.name ?? crumb.label ?? crumb.title ?? '',
      onClick: index < lastIndex && onFolderSelect
        ? () => onFolderSelect(crumb.id)
        : null,
    }));
  }, [breadcrumbEntries, currentFolderName, onFolderSelect]);

  return (
    <>
      <section
      className={`documents-panel documents-panel--view-${isGridView ? 'grid' : 'list'}`}
    >
      {showHeader ? (
        <div className="panel-section__header">
          <div className="panel-section__titles">
            <h2 className="documents-panel__title">
              <BreadcrumbTrail
                entries={trailEntries}
                className="documents-panel__breadcrumbs"
                separator="/"
              />
            </h2>
            {showingSearchResults && (
              <div className="panel-section__subtitle">Search results</div>
            )}
          </div>
          <div className="header-actions">
            <div className="view-toggle" role="group" aria-label="Change view">
              <button
                type="button"
                className={`view-toggle__button${isListView ? ' active' : ''}`}
                onClick={() => handleSetViewMode('list')}
                aria-pressed={isListView}
                title="List view"
              >
                <ViewListIcon className="view-toggle__icon" size={18} />
              </button>
              <button
                type="button"
                className={`view-toggle__button${isGridView ? ' active' : ''}`}
                onClick={() => handleSetViewMode('grid')}
                aria-pressed={isGridView}
                title="Icons view"
              >
                <ViewGridIcon className="view-toggle__icon" size={18} />
              </button>
              <button
                type="button"
                className={`view-toggle__button${isDeskView ? ' active' : ''}`}
                onClick={() => handleSetViewMode('desk')}
                aria-pressed={isDeskView}
                title="Desk view"
              >
                <IconFileStack className="view-toggle__icon" size={18} />
              </button>
            </div>
            <button className="secondary" onClick={onRefresh}>
              Refresh
            </button>
          </div>
        </div>
      ) : null}
      {showDefaultEmptyState ? (
        <div className="panel-section__body">
          <div className="empty-state">
            Drop files anywhere or onto a folder to upload documents.
          </div>
        </div>
      ) : showGridSearchEmptyState ? (
        <div className="panel-section__body">
          <div className="empty-state empty-state--global">
            No documents match the current filters.
          </div>
        </div>
      ) : showListSearchEmptyState ? (
        <div className="panel-section__body">
          <div className="empty-state">No documents match the current filters.</div>
        </div>
      ) : (
        <div className="panel-section__body">
          <div
            ref={assignScrollRef}
            className="documents-scroll"
            tabIndex={0}
            onFocus={(event) => {
              if (event.target === scrollRef.current) {
                handlePanelFocus();
              }
            }}
            onKeyDown={(event) => {
              if (event.target !== scrollRef.current) {
                return;
              }
              handlePanelKeyDown(event);
            }}
            onClick={(event) => {
              if (event.target === event.currentTarget) {
                onClearSelection?.();
              }
            }}
            aria-activedescendant={isGridView ? undefined : activeDescendantId}
          >
            {isGridView ? (
              <DocumentsGrid
                entries={entries}
                selectedDocumentIdsSet={selectedSet}
                selectedFolderIdsSet={selectedFolderSet}
                draggingDocumentIdsSet={draggingSet}
                draggedFolderId={draggedFolderId}
                onFolderClick={handleFolderClick}
                onFolderSelect={onFolderSelect}
                onFolderDragOver={onFolderDragOver}
                onFolderDragLeave={onFolderDragLeave}
                onFolderDrop={onFolderDrop}
                onFolderDragStart={onFolderDragStart}
                onFolderDragEnd={onFolderDragEnd}
                onDocumentClick={handleDocumentClick}
                onDocumentActivate={handleDocumentActivate}
                onDocumentDragStart={handleDocumentDragStartLocal}
                onDocumentDragEnd={handleDocumentDragEndLocal}
                onDocumentTagDragOver={handleDocumentTagDragOver}
                onDocumentTagDragLeave={handleDocumentTagDragLeave}
                onDocumentTagDrop={handleDocumentTagDrop}
                ensureAssetUrl={ensureAssetUrl}
                getDocumentAsset={getDocumentAsset}
                gridIconSize={gridIconSize}
                tagLookupById={tagLookupById}
                onTagClick={onTagClick}
                scrollRef={scrollRef}
                onCorrespondentClick={onCorrespondentClick}
                activeCorrespondentIdSet={activeCorrespondentIdSet}
                onClearSelection={onClearSelection}
                onDocumentRename={onDocumentRename}
                onFolderRename={onFolderRename}
              />
            ) : !showTableRows ? null : (
              <DocumentsList
                entries={entries}
                focusedRowKey={focusedRowKey}
                selectedDocumentIdsSet={selectedSet}
                selectedFolderIdsSet={selectedFolderSet}
                draggingDocumentIdsSet={draggingSet}
                draggedFolderId={draggedFolderId}
                ensureAssetUrl={ensureAssetUrl}
                getDocumentAsset={getDocumentAsset}
                onFolderClick={handleFolderClick}
                onFolderSelect={onFolderSelect}
                onFolderDragOver={onFolderDragOver}
                onFolderDragLeave={onFolderDragLeave}
                onFolderDrop={onFolderDrop}
                onFolderDragStart={onFolderDragStart}
                onFolderDragEnd={onFolderDragEnd}
                onFolderRename={onFolderRename}
                onDocumentClick={handleDocumentClick}
                onDocumentActivate={handleDocumentActivate}
                onDocumentDragStart={handleDocumentDragStartLocal}
                onDocumentDragEnd={handleDocumentDragEndLocal}
                onDocumentTagDragOver={handleDocumentTagDragOver}
                onDocumentTagDragLeave={handleDocumentTagDragLeave}
                onDocumentTagDrop={handleDocumentTagDrop}
                onDocumentRename={onDocumentRename}
                tagLookupById={tagLookupById}
                onTagClick={onTagClick}
                onCorrespondentClick={onCorrespondentClick}
                activeCorrespondentIdSet={activeCorrespondentIdSet}
                scrollRef={scrollRef}
                onClearSelection={onClearSelection}
              />
            )}
          </div>
        </div>
      )}
    </section>
      <PreviewZoomOverlay
        open={Boolean(previewDocId)}
        display={previewDisplay}
        onClose={closePreviewOverlay}
      />
    </>
  );
};

export default DocumentsPanel;

const SortFieldQuickMenu = ({ sortField, onChange }) => {
  const currentOption = useMemo(
    () => SORT_OPTIONS.find((option) => option.value === sortField) || SORT_OPTIONS[0],
    [sortField],
  );

  const options = useMemo(
    () => SORT_OPTIONS.map((option) => ({ id: option.value, label: option.label })),
    [],
  );

  const handleSelect = useCallback(
    (value, option) => {
      if (typeof onChange !== 'function') {
        return;
      }
      const nextValue = option?.id || option?.original?.id || value;
      if (nextValue) {
        onChange(nextValue);
      }
    },
    [onChange],
  );

  const label = currentOption?.label || SORT_LABEL_LOOKUP[currentOption?.value] || 'Title';

  return (
    <QuickAddMenu
      className="documents-sort__quickmenu"
      options={options}
      onSelectOption={handleSelect}
      triggerClassName="view-toggle__button documents-sort__trigger quick-add__trigger"
      triggerContent={(
        <span className="documents-sort__trigger-content">
          <span className="documents-sort__label">{label}</span>
        </span>
      )}
      triggerAriaLabel={`Sort by ${label}`}
      triggerTitle={`Sort by ${label}`}
      placeholder="Select sort field"
      menuMinWidth={200}
      align="start"
      positionStrategy="absolute"
    />
  );
};

export const createDocumentsTableHeaderActions = ({
  viewMode,
  onViewModeChange,
  onRefresh,
  onShowDeskHelp = null,
  sortField = 'title',
  onSortFieldChange = null,
  sortDirection = 'asc',
  onSortDirectionToggle = null,
  isFilterActive = false,
  includeDescendants = true,
  onToggleIncludeDescendants = null,
}) => {
  const isListView = viewMode === 'list';
  const isGridView = viewMode === 'grid';
  const isDeskView = viewMode === 'desk';

  const sortDirectionIsDesc = sortDirection === 'desc';
  const sortDirectionTitle = sortDirectionIsDesc
    ? 'Sorting Z → A. Click to switch to ascending.'
    : 'Sorting A → Z. Click to switch to descending.';
  const includeDescendantsToggle = isFilterActive && typeof onToggleIncludeDescendants === 'function'
    ? (
        <button
          type="button"
          className="icon-button documents-toolbar__toggle"
          onClick={onToggleIncludeDescendants}
          aria-pressed={!includeDescendants}
          aria-label={includeDescendants ? 'Include subfolders' : 'Limit to current folder'}
          title={includeDescendants
            ? 'Including subfolders. Click to limit the search to the current folder.'
            : 'Limiting to the current folder. Click to include subfolders again.'}
        >
          {includeDescendants ? <FoldersIcon /> : <FoldersOffIcon />}
        </button>
      )
    : null;

  const sortControls = typeof onSortFieldChange === 'function'
    ? (
        <div className="documents-actions__sort-group">
          <SortFieldQuickMenu sortField={sortField} onChange={onSortFieldChange} />
          {typeof onSortDirectionToggle === 'function' ? (
            <button
              type="button"
              className="icon-button documents-toolbar__toggle documents-sort__direction"
              onClick={onSortDirectionToggle}
              aria-pressed={sortDirectionIsDesc}
              aria-label={sortDirectionIsDesc ? 'Sort descending' : 'Sort ascending'}
              title={sortDirectionTitle}
            >
              {sortDirectionIsDesc ? (
                <SortDescendingLettersIcon size={18} />
              ) : (
                <SortAscendingLettersIcon size={18} />
              )}
            </button>
          ) : null}
        </div>
      )
    : null;

  return (
    <>
      {isDeskView && typeof onShowDeskHelp === 'function' ? (
        <>
          <button
            type="button"
            className="icon-button"
            onClick={onShowDeskHelp}
            aria-label="Show desk view tips"
            title="Show desk view tips"
          >
            <InfoIcon />
          </button>
          <span className="main-content__actions-divider" aria-hidden="true">
            <MinusVerticalIcon />
          </span>
        </>
      ) : null}
      {includeDescendantsToggle ? (
        <>
          {includeDescendantsToggle}
          <span className="main-content__actions-divider" aria-hidden="true">
            <MinusVerticalIcon />
          </span>
        </>
      ) : null}
      {sortControls ? (
        <>
          {sortControls}
          <span className="main-content__actions-divider" aria-hidden="true">
            <MinusVerticalIcon />
          </span>
        </>
      ) : null}
      <div className="view-toggle" role="group" aria-label="Change view">
        <button
          type="button"
          className={`view-toggle__button${isListView ? ' active' : ''}`}
          onClick={() => onViewModeChange?.('list')}
          aria-pressed={isListView}
          title="List view"
        >
          <ViewListIcon className="view-toggle__icon" size={18} />
        </button>
        <button
          type="button"
          className={`view-toggle__button${isGridView ? ' active' : ''}`}
          onClick={() => onViewModeChange?.('grid')}
          aria-pressed={isGridView}
          title="Icons view"
        >
          <ViewGridIcon className="view-toggle__icon" size={18} />
        </button>
        <button
          type="button"
          className={`view-toggle__button${isDeskView ? ' active' : ''}`}
          onClick={() => onViewModeChange?.('desk')}
          aria-pressed={isDeskView}
          title="Desk view"
        >
          <IconFileStack className="view-toggle__icon" size={18} />
        </button>
      </div>
      <span className="main-content__actions-divider" aria-hidden="true">
        <MinusVerticalIcon />
      </span>
      <button
        type="button"
        className="icon-button"
        onClick={onRefresh}
        aria-label="Refresh"
        title="Refresh"
      >
        <RefreshIcon />
      </button>
    </>
  );
};

export const createDocumentsSurface = ({
  tableProps,
  parentBreadcrumb,
  onNavigateParent,
  renderSidebarToggle,
  detailProps,
  detailOpen = false,
}) => {
  const {
    currentFolderName,
    breadcrumbs,
    searchResults,
    isFilterActive,
    viewMode,
    onViewModeChange,
    onRefresh,
    sortField,
    sortDirection,
    onSortFieldChange,
    onSortDirectionToggle,
    selectedDocumentIds,
    selectedFolderIds,
    onDeleteSelection,
    onClearSelection,
    tags,
    correspondents,
    documentLookup,
    tagLookupById,
    onBulkTagAdd,
    onBulkTagRemove,
    onBulkCorrespondentAdd,
    onBulkCorrespondentRemove,
    onBulkReanalyze,
    folderOptions,
    onMoveDocumentsToFolder,
    searchIncludeDescendants,
    onToggleSearchIncludeDescendants,
  } = tableProps;

  const title = Array.isArray(searchResults) ? 'Search results' : currentFolderName;
  const subtitle = Array.isArray(searchResults)
    ? `${searchResults.length} matching document${searchResults.length === 1 ? '' : 's'}`
    : null;


  const documentSelectionCount = Array.isArray(selectedDocumentIds) ? selectedDocumentIds.length : 0;
  const folderSelectionCount = Array.isArray(selectedFolderIds) ? selectedFolderIds.length : 0;
  const selectionCount = documentSelectionCount + folderSelectionCount;

  const actions = createDocumentsTableHeaderActions({
    viewMode,
    onViewModeChange,
    onRefresh,
    sortField,
    onSortFieldChange,
    sortDirection,
    onSortDirectionToggle,
    isFilterActive,
    includeDescendants: searchIncludeDescendants,
    onToggleIncludeDescendants: onToggleSearchIncludeDescendants,
  });

  const floatingActions = selectionCount > 0
    ? (
        <SelectionFloatingActions
          selectionCount={selectionCount}
          selectedDocumentIds={selectedDocumentIds}
          selectedFolderIds={selectedFolderIds}
          documentLookup={documentLookup}
          tags={tags}
          tagLookupById={tagLookupById}
          correspondents={correspondents}
          onBulkTagAdd={onBulkTagAdd}
          onBulkTagRemove={onBulkTagRemove}
          onBulkCorrespondentAdd={onBulkCorrespondentAdd}
          onBulkCorrespondentRemove={onBulkCorrespondentRemove}
          onBulkReanalyze={onBulkReanalyze}
          onDeleteSelection={onDeleteSelection}
          onClearSelection={onClearSelection}
          folderOptions={folderOptions}
          onMoveDocumentsToFolder={onMoveDocumentsToFolder}
        />
      )
    : null;


  const sidebarToggle = renderSidebarToggle ? renderSidebarToggle() : null;
  const detail = detailOpen && detailProps ? <DetailPanel {...detailProps} /> : null;

  const surfaceConfig = createWorkspaceSurfaceConfig({
    key: 'documents',
    variant: 'documents',
    title,
    subtitle,
    sidebarToggle,
    parentBreadcrumb,
    onNavigateParent,
    actions,
    breadcrumbs,
    selectionLabel: null,
    floatingActions,
    content: <DocumentsPanel {...tableProps} showHeader={false} />,
    detail,
  });

  return surfaceConfig;
};
