import React, { useCallback, useMemo } from 'react';
import type { DocumentsListEntry } from '../../types/documents';
import { useWorkspaceSelectionContext } from '../../app/WorkspaceSelectionContext';

interface UseDocumentsNavigationProps {
    entries: DocumentsListEntry[];
    onFolderSelect?: (folderId: string) => void;
    onPreview?: (doc: any) => void;
}

export const useDocumentsNavigation = ({
    entries,
    onFolderSelect,
    onPreview,
}: UseDocumentsNavigationProps) => {
    const {
        selectedEntries,
        focusedEntryKey,
        setFocusedEntryKey,
        handleEntrySelection,
    } = useWorkspaceSelectionContext();

    const navigableRows = useMemo(
        () => entries.map((entry) => ({ key: entry.key, type: entry.type, id: entry.id })),
        [entries],
    );
    const navigableEntryKeys = useMemo(() => navigableRows.map((row) => row.key), [navigableRows]);

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

    const handleKeyDown = useCallback(
        (event: React.KeyboardEvent) => {
            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 =
                focusedEntryKey && navigableEntryKeys.includes(focusedEntryKey)
                    ? focusedEntryKey
                    : null;

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

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

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

            if (key === 'Enter' || key === ' ' || key === 'Space' || key === 'Spacebar') {
                if (activeRow) {
                    handleEntrySelection(activeRow.key, event);
                    if (activeRow.type === 'folder') {
                        onFolderSelect?.(activeRow.id as string);
                    } else {
                        const entry = getEntryByKey(activeRow.key);
                        // @ts-ignore
                        if (entry?.document) {
                            // @ts-ignore
                            onPreview?.(entry.document);
                        }
                    }
                }
                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;
            }

            setFocusedEntryKey(targetRow.key);
            handleEntrySelection(targetRow.key, {
                shiftKey,
                preventDefault: () => { },
            });
        },
        [
            focusedEntryKey,
            getEntryByKey,
            navigableEntryKeys,
            navigableRows,
            onFolderSelect,
            selectedEntries,
            onPreview,
            handleEntrySelection,
            setFocusedEntryKey,
        ],
    );

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

        if (focusedEntryKey && navigableEntryKeys.includes(focusedEntryKey)) {
            resolvedKey = focusedEntryKey;
        }

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

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

        if (!resolvedKey) {
            return;
        }

        setFocusedEntryKey(resolvedKey);
    }, [
        focusedEntryKey,
        navigableEntryKeys,
        navigableRows,
        setFocusedEntryKey,
        selectedEntries,
    ]);

    return {
        handleKeyDown,
        handleFocus,
    };
};
