import React, { useCallback, useMemo } from 'react';
import { type FileObject } from '../api/server/files';
import VirtualList from './VirtualList';

interface Props {
    currentPath: string;
    files: FileObject[];
    sortBy: 'name' | 'size' | 'date' | 'type';
    sortDirection: 'asc' | 'desc';
    parentPath: string;
    containerRef: React.RefObject<HTMLElement>;
    renderParentRow?: () => React.ReactNode;
    renderRow: (file: FileObject, fullPath: string, isLastChild: boolean) => React.ReactNode;
    selectedFile?: string | null;
    selectedFiles?: string[];
    draggedPaths?: Set<string>;
    isDragging?: boolean;
    showFileCheckboxes?: boolean;
    emptyMessage?: string;
}

const ITEM_HEIGHT = 28;

interface FlatItem {
    type: 'parent' | 'file';
    file?: FileObject;
    fullPath: string;
    isLastChild: boolean;
}

const BrowseList: React.FC<Props> = ({
    currentPath,
    files,
    sortBy,
    sortDirection,
    parentPath,
    containerRef,
    renderParentRow,
    renderRow,
    selectedFile,
    selectedFiles,
    draggedPaths,
    isDragging,
    showFileCheckboxes,
    emptyMessage = 'This folder is empty',
}) => {
    const hasParentRow = currentPath !== '/' && !!renderParentRow;

    const sorted = useMemo(() => {
        const filteredFiles = files.filter(file => file.name !== '.trash-bin');
        return [...filteredFiles].sort((a, b) => {
            if (a.isFile !== b.isFile) {
                return a.isFile ? 1 : -1;
            }
            let comparison = 0;
            switch (sortBy) {
                case 'name':
                    comparison = a.name.localeCompare(b.name);
                    break;
                case 'size':
                    comparison = (a.size || 0) - (b.size || 0);
                    break;
                case 'date':
                    const aDate = a.modifiedAt ? new Date(a.modifiedAt).getTime() : 0;
                    const bDate = b.modifiedAt ? new Date(b.modifiedAt).getTime() : 0;
                    comparison = aDate - bDate;
                    break;
                case 'type':
                    const aExt = a.name.split('.').pop() || '';
                    const bExt = b.name.split('.').pop() || '';
                    comparison = aExt.localeCompare(bExt);
                    break;
            }
            return sortDirection === 'asc' ? comparison : -comparison;
        });
    }, [files, sortBy, sortDirection]);

    const flatItems = useMemo(() => {
        const items: FlatItem[] = [];

        if (hasParentRow) {
            items.push({ type: 'parent', fullPath: parentPath, isLastChild: false });
        }

        sorted.forEach((file, index) => {
            const fullPath = currentPath === '/' ? `/${file.name}` : `${currentPath}/${file.name}`;
            items.push({
                type: 'file',
                file,
                fullPath,
                isLastChild: index === sorted.length - 1,
            });
        });
        
        return items;
    }, [hasParentRow, parentPath, sorted, currentPath]);

    const selectedFilesSet = useMemo(() => new Set(selectedFiles ?? []), [selectedFiles]);

    const renderItem = useCallback((item: FlatItem) => {
        if (item.type === 'parent') {
            return renderParentRow ? renderParentRow() : null;
        }
        if (item.fullPath && draggedPaths?.has(item.fullPath)) {
            return null;
        }
        return item.file ? renderRow(item.file, item.fullPath, item.isLastChild) : null;
    }, [draggedPaths, renderParentRow, renderRow]);

    if (sorted.length === 0) {
        return (
            <>
                {hasParentRow && renderParentRow ? renderParentRow() : null}
                <div className="flex flex-col items-center justify-center text-center py-10 text-neutral-300">
                    <svg className="w-14 h-14 mb-3 opacity-50" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                        <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z" />
                    </svg>
                    <p className="text-sm">{emptyMessage}</p>
                </div>
            </>
        );
    }

    return (
        <VirtualList
            items={flatItems}
            itemHeight={ITEM_HEIGHT}
            containerRef={containerRef}
            renderItem={renderItem}
            getItemKey={(item) => item.fullPath}
            getItemState={(item) => [
                selectedFile === item.fullPath ? 'selected' : 'idle',
                selectedFilesSet.has(item.fullPath) ? 'checked' : 'unchecked',
                draggedPaths?.has(item.fullPath) ? 'dragged' : 'rest',
                showFileCheckboxes ? 'checkboxes' : 'plain',
            ].join(':')}
            overscan={10}
            debugName="BrowseList"
            selectedFile={selectedFile}
            selectedFiles={selectedFiles}
            draggedPaths={draggedPaths}
            isDragging={isDragging}
        />
    );
};

export default BrowseList;
