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;
    viewMode?: string;
    scrollRef?: React.RefObject<HTMLElement | null>;
}

export const useDocumentsNavigation = ({
    entries,
    onFolderSelect,
    onPreview,
    viewMode,
    scrollRef,
}: UseDocumentsNavigationProps) => {
    const {
        selectedEntries,
        focusedEntryKey,
        setFocusedEntryKey,
        handleEntrySelection,
        applySelection,
    } = 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 getGridColumns = useCallback(() => {
        if (!scrollRef?.current) return 1;
        const grid = scrollRef.current.querySelector('.documents-grid');
        if (!grid) return 1;
        const style = window.getComputedStyle(grid);
        const templateColumns = style.gridTemplateColumns;
        if (!templateColumns) return 1;
        return templateColumns.split(' ').length;
    }, [scrollRef]);

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

            if (!navigableRows.length) {
                return;
            }

            // Allow default scrolling for Home/End if not preventing default
            if (key !== 'Home' && key !== 'End') {
                event.preventDefault();
            } else {
                // Prevent default only if we are handling selection move, otherwise let browser scroll
                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' || key === 'ArrowLeft')
                        ? 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) {
                    event.preventDefault();
                    // Do not call handleEntrySelection here, as it resets selection if multiple items are selected.
                    // Space/Enter should just trigger the action (Preview/Open) on the focused item
                    // without modifying the selection state.

                    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;
            const isGrid = viewMode === 'grid';
            const columns = isGrid ? getGridColumns() : 1;

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

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

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

            setFocusedEntryKey(targetRow.key);

            if (shiftKey) {
                // Additive selection for Shift+Arrow (Finder style)
                const newSelection = Array.from(new Set([...selectedEntries, targetRow.key]));
                applySelection(newSelection, { anchor: targetRow.key, interactedKeys: [targetRow.key] });
            } else {
                handleEntrySelection(targetRow.key, {
                    shiftKey,
                    preventDefault: () => { },
                });
            }
        },
        [
            focusedEntryKey,
            getEntryByKey,
            navigableEntryKeys,
            navigableRows,
            onFolderSelect,
            selectedEntries,
            onPreview,
            handleEntrySelection,
            setFocusedEntryKey,
            viewMode,
            getGridColumns,
            applySelection,
        ],
    );

    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,
    };
};
