import React, { useState, useEffect } from 'react';
import { FileObject } from './api/server/files';
import { Dialog } from '@/components/elements/dialog';
import { Button } from '@/components/elements/button/index';
import GreyRowBox from '@/components/elements/GreyRowBox';
import FileIcon from './FileIcon';

interface DirectoryPickerProps {
    open: boolean;
    onClose: () => void;
    onConfirm: (path: string) => void;
    fileTree: Record<string, FileObject[]>;
    currentPath: string;
    title?: string;
    onLoadDirectory: (path: string) => Promise<FileObject[]>;
    defaultPath?: string;
}

const cx = (...parts: Array<string | false | null | undefined>) => parts.filter(Boolean).join(' ');

const Chevron: React.FC<{ expanded: boolean; loading?: boolean }> = ({ expanded, loading }) => {
    if (loading) {
        return (
            <svg className='h-4 w-4 shrink-0 animate-spin text-neutral-400' fill='none' viewBox='0 0 24 24'>
                <circle className='opacity-25' cx='12' cy='12' r='10' stroke='currentColor' strokeWidth='4' />
                <path className='opacity-75' fill='currentColor' d='M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z' />
            </svg>
        );
    }

    return (
        <svg
            className={cx('h-4 w-4 shrink-0 text-neutral-400 transition-transform', expanded && 'rotate-90')}
            fill='none'
            stroke='currentColor'
            viewBox='0 0 24 24'
        >
            <path strokeLinecap='round' strokeLinejoin='round' strokeWidth={2} d='M9 5l7 7-7 7' />
        </svg>
    );
};

const DirectoryPicker: React.FC<DirectoryPickerProps> = ({
    open,
    onClose,
    onConfirm,
    fileTree,
    currentPath,
    title = "Select Destination",
    onLoadDirectory,
    defaultPath
}) => {
    const [selectedPath, setSelectedPath] = useState(currentPath);
    const [expandedFolders, setExpandedFolders] = useState<Set<string>>(new Set(['/']));
    const [loadingFolders, setLoadingFolders] = useState<Set<string>>(new Set());

    useEffect(() => {
        if (open) {
            setSelectedPath(defaultPath ?? currentPath);
        }
    }, [open, currentPath, defaultPath]);

    if (!open) {
        return null;
    }

    const toggleFolder = async (path: string) => {
        const newExpanded = new Set(expandedFolders);
        if (newExpanded.has(path)) {
            newExpanded.delete(path);
            setExpandedFolders(newExpanded);
        } else {
            newExpanded.add(path);
            setExpandedFolders(newExpanded);

            if (!fileTree[path]) {
                setLoadingFolders(prev => new Set(prev).add(path));
                try {
                    await onLoadDirectory(path);
                } finally {
                    setLoadingFolders(prev => {
                        const next = new Set(prev);
                        next.delete(path);
                        return next;
                    });
                }
            }
        }
    };

    const renderFolderRow = (folderName: string, path: string, depth: number, loading = false) => {
        const isExpanded = expandedFolders.has(path);
        const isSelected = selectedPath === path;

        return (
            <GreyRowBox
                key={path}
                className={cx(
                    'w-full !items-center gap-2 !px-3 !py-2 transition-colors',
                    isSelected
                        ? 'border-neutral-500 bg-neutral-800 text-neutral-100 shadow-inner'
                        : 'border-transparent bg-transparent text-neutral-300 hover:bg-neutral-700 hover:text-neutral-100'
                )}
                $hoverable={false}
            >
                <button
                    type='button'
                    className='flex h-5 w-5 shrink-0 items-center justify-center rounded text-neutral-400 hover:bg-neutral-700 hover:text-neutral-100'
                    style={{ marginLeft: depth * 14 }}
                    onClick={(e) => {
                        e.preventDefault();
                        e.stopPropagation();
                        void toggleFolder(path);
                    }}
                    aria-label={isExpanded ? `Collapse ${folderName}` : `Expand ${folderName}`}
                >
                    <Chevron expanded={isExpanded} loading={loading} />
                </button>
                <button
                    type='button'
                    className='flex min-w-0 flex-1 items-center gap-2 text-left focus:outline-none'
                    onClick={(e) => {
                        e.preventDefault();
                        e.stopPropagation();
                        setSelectedPath(path);
                    }}
                >
                    <FileIcon filename={folderName} isFolder isOpen={isExpanded} />
                    <span className='min-w-0 flex-1 truncate text-sm font-semibold'>{folderName}</span>
                </button>
            </GreyRowBox>
        );
    };

    const renderFolderTree = (path: string, depth = 0): React.ReactNode[] => {
        const files = fileTree[path] || [];
        const folders = files.filter(file => !file.isFile);
        const elements: React.ReactNode[] = [];

        folders.forEach(folder => {
            const fullPath = path === '/' ? `/${folder.name}` : `${path}/${folder.name}`;
            const isExpanded = expandedFolders.has(fullPath);
            const isLoading = loadingFolders.has(fullPath);

            elements.push(renderFolderRow(folder.name, fullPath, depth, isLoading));

            if (isExpanded) {
                elements.push(...renderFolderTree(fullPath, depth + 1));
            }
        });

        return elements;
    };

    return (
        <Dialog open={open} onClose={onClose} title={title}>
            <div className='space-y-4'>
                <GreyRowBox className='!flex-col !items-stretch gap-1 !px-4 !py-3' $hoverable={false}>
                    <span className='text-xs font-medium text-neutral-400'>Selected destination</span>
                    <span className='break-all font-mono text-sm text-neutral-100'>{selectedPath}</span>
                </GreyRowBox>

                <GreyRowBox className='!flex-col !items-stretch !p-2' $hoverable={false}>
                    <div className='max-h-96 space-y-1 overflow-y-auto pr-1'>
                        {renderFolderRow('Root Directory', '/', 0)}
                        {renderFolderTree('/', 1)}
                    </div>
                </GreyRowBox>
            </div>
            <Dialog.Footer>
                <Button.Text type='button' onClick={onClose}>
                    Cancel
                </Button.Text>
                <Button
                    type='button'
                    onClick={(e) => {
                        e.preventDefault();
                        onConfirm(selectedPath);
                    }}
                    disabled={selectedPath === currentPath}
                >
                    Move Here
                </Button>
            </Dialog.Footer>
        </Dialog>
    );
};

export default DirectoryPicker;
