import { useCallback, useMemo } from 'react';
import { useDocumentSelection } from './useDocumentSelection';

type RowKey = string;

interface SelectionEntry {
  rowKey?: RowKey;
  [key: string]: unknown;
}

interface WorkspaceSelectionOptions {
  resolveDocumentRowKey?: (id: string | number) => RowKey | null | undefined;
  resolveFolderRowKey?: (id: string | number) => RowKey | null | undefined;
  isDocumentRowKey?: (key: RowKey | SelectionEntry) => boolean;
  isFolderRowKey?: (key: RowKey | SelectionEntry) => boolean;
  getRowId?: (key: RowKey | SelectionEntry) => string | number | null;
  onInspectDocument?: (id: string | number) => void;
  onInspectFolder?: (id: string | number) => void;
}

const identity = <T,>(value: T) => value;

export const useWorkspaceSelection = ({
  resolveDocumentRowKey,
  resolveFolderRowKey,
  isDocumentRowKey = () => false,
  isFolderRowKey = () => false,
  getRowId = () => null,
  onInspectDocument = identity,
  onInspectFolder = identity,
}: WorkspaceSelectionOptions = {}) => {
  const selection = useDocumentSelection({
    resolveDocumentRowKey,
    resolveFolderRowKey,
    isDocumentRowKey,
    isFolderRowKey,
    getRowId,
  });

  const {
    selectedEntries,
    setSelectedEntries,
    selectionOrder,
    setSelectionOrder,
    selectionOrderRef,
    selectionAnchorRef,
    selectionInitializedRef,
    focusedDocumentId,
    setFocusedDocumentId,
    focusedRowKey,
    setFocusedRowKey,
    applySelection,
    clearSelection,
    handleEntrySelection,
    promoteSelectionOrder,
    configureSelectionEnvironment,
  } = selection;

  const selectedDocumentIds = useMemo(
    () =>
      selectedEntries
        .filter((entry) => isDocumentRowKey(entry))
        .map((entry) => getRowId(entry))
        .filter(Boolean),
    [selectedEntries, isDocumentRowKey, getRowId],
  );

  const selectedFolderIds = useMemo(
    () =>
      selectedEntries
        .filter((entry) => isFolderRowKey(entry))
        .map((entry) => getRowId(entry))
        .filter(Boolean),
    [selectedEntries, isFolderRowKey, getRowId],
  );

  const selectEntry = useCallback(
    (entry: SelectionEntry | string | null, event?: unknown) => {
      const rowKey = typeof entry === 'string'
        ? entry
        : entry?.rowKey ?? null;
      if (!rowKey) return;
      handleEntrySelection(rowKey, event);
    },
    [handleEntrySelection],
  );

  const inspectDocument = useCallback(
    (documentId?: string | number | null) => {
      if (!documentId) return;
      onInspectDocument(documentId);
    },
    [onInspectDocument],
  );

  const inspectFolder = useCallback(
    (folderId?: string | number | null) => {
      if (!folderId) return;
      onInspectFolder(folderId);
    },
    [onInspectFolder],
  );

  return {
    selectedEntries,
    selectedDocumentIds,
    selectedFolderIds,
    selectionOrder,
    selectionOrderRef,
    selectionAnchorRef,
    selectionInitializedRef,
    focusedDocumentId,
    setFocusedDocumentId,
    focusedRowKey,
    setFocusedRowKey,
    applySelection,
    clearSelection,
    handleEntrySelection: selectEntry,
    promoteSelectionOrder,
    configureSelectionEnvironment,
    setSelectedEntries,
    setSelectionOrder,
    inspectDocument,
    inspectFolder,
  };
};

export default useWorkspaceSelection;
