import type { Dispatch, MutableRefObject, SetStateAction } from 'react';
import type { DocumentId, FolderId as FolderIdentifier } from '../../types/identifiers';
import type { Document } from '../../types/documents';

type FolderId = FolderIdentifier | 'root';

export interface FolderNode {
    id: FolderId;
    parentId?: FolderId;
    children: FolderId[];
    hasChildren?: boolean;
    name?: string;
    expanded?: boolean;
    loaded?: boolean;
}

export interface Tag {
    id: DocumentId;
    label: string;
    color?: string | null;
}

interface TagManager {
    normalizeLabel: (label: string) => string;
    buildPayload: (args: { label: string }) => Record<string, unknown>;
}

type DocumentCacheMapper = (
    doc: Document | null,
) => Document | null;

type MapDocumentCaches = (mapper: DocumentCacheMapper) => void;

type UpdateDocumentCaches = (
    documentId: DocumentId,
    updater: DocumentCacheMapper,
) => void;



type RemoveDocumentsFromCaches = (documentIds: DocumentId[]) => void;

type CloseDocumentPreview = () => void;

export interface DocumentsState {
    documentLookup: Map<DocumentId, Document>;
    setDocuments: Dispatch<SetStateAction<Document[]>>;
    setSearchResultIds: Dispatch<SetStateAction<DocumentId[] | null>>;
    removeDocumentsFromCaches: RemoveDocumentsFromCaches;
    updateDocumentCaches: UpdateDocumentCaches;
    mapDocumentCaches: MapDocumentCaches;
    extractDocumentFromResponse?: (payload: unknown) => Document | null;
    ingestDocuments?: (docs: unknown[]) => { canonical: Document[]; changed: boolean };
}

export interface FolderState {
    folderNodes: Map<FolderId, FolderNode>;
    setFolderNodes: Dispatch<SetStateAction<Map<FolderId, FolderNode>>>;
    selectedFolder: FolderId;
    setSelectedFolder: Dispatch<SetStateAction<FolderId>>;
    folderLabelMap: Map<FolderId, string>;
    setCreatingFolder?: (value: boolean) => void;
}

export interface SelectionState {
    setSelectedEntries: Dispatch<SetStateAction<string[]>>;
    setSelectionOrder: Dispatch<SetStateAction<string[]>>;
    selectionOrderRef: MutableRefObject<string[] | null>;
    selectionAnchorRef: MutableRefObject<string | null>;
    setFocusedDocumentId: Dispatch<SetStateAction<DocumentId | null>>;
    focusedDocumentId: DocumentId | null;
    setFocusedEntryKey: Dispatch<SetStateAction<string | null>>;
    focusedEntryKey: string | null;
}

export interface TagsState {
    tags: Tag[];
    tagLookupById: Map<DocumentId, Tag>;
    refreshTags: () => Promise<void>;
    tagManager: TagManager;
}

export interface ActionsState {
    closeDocumentPreview: CloseDocumentPreview;
    handleFileDrop?: (dataTransfer: DataTransfer, folderId: FolderId) => Promise<void> | void;
    moveDocumentsToFolder?: (docIds: FolderId[], folderId: FolderId) => Promise<void>;
}

export interface DragState {
    draggedDocumentIds: FolderId[];
    draggedFolderId: FolderId | null;
    setDraggedDocumentIds: (ids: FolderId[]) => void;
    setDraggedFolderId: (id: FolderId | null) => void;
}
