import React, { useState, useEffect, useCallback } from 'react';
import { Box, Text, useInput } from 'ink';
import fs from 'fs';
import path from 'path';

const h = React.createElement;

// Helper to sort: folders first
const sortFiles = (files, dirPath) => {
    return files.sort((a, b) => {
        const pathA = path.join(dirPath, a);
        const pathB = path.join(dirPath, b);
        try {
            const statA = fs.statSync(pathA);
            const statB = fs.statSync(pathB);
            if (statA.isDirectory() && !statB.isDirectory()) return -1;
            if (!statA.isDirectory() && statB.isDirectory()) return 1;
            return a.localeCompare(b);
        } catch (e) {
            return 0;
        }
    });
};

const FileTree = ({
    rootPath,
    onSelect,
    selectedFiles = new Set(),
    isActive = false,
    height = 20,
    width = 30
}) => {
    const [expanded, setExpanded] = useState(new Set([rootPath])); // Expanded folders
    const [cursor, setCursor] = useState(rootPath); // Currently highlighted path
    const [flatList, setFlatList] = useState([]); // Computed flat list for rendering (calc'd from expanded)

    // Ignore list
    const IGNORE_DIRS = new Set(['.git', 'node_modules', '.opencode', 'dist', 'build', 'coverage']);

    // Rebuild flat list when expanded changes
    // Returns array of { path, name, isDir, depth, isExpanded, hasChildren }
    const buildFlatList = useCallback(() => {
        const list = [];

        const traverse = (currentPath, depth) => {
            if (depth > 10) return; // Safety

            const name = path.basename(currentPath) || (currentPath === rootPath ? '/' : currentPath);
            let isDir = false;
            try {
                isDir = fs.statSync(currentPath).isDirectory();
            } catch (e) { return; }

            const isExpanded = expanded.has(currentPath);

            list.push({
                path: currentPath,
                name: name,
                isDir: isDir,
                depth: depth,
                isExpanded: isExpanded
            });

            if (isDir && isExpanded) {
                try {
                    const children = fs.readdirSync(currentPath).filter(f => !IGNORE_DIRS.has(f) && !f.startsWith('.'));
                    const sorted = sortFiles(children, currentPath);
                    for (const child of sorted) {
                        traverse(path.join(currentPath, child), depth + 1);
                    }
                } catch (e) {
                    // Permission error or file delete race condition
                }
            }
        };

        traverse(rootPath, 0);
        return list;
    }, [expanded, rootPath]);

    useEffect(() => {
        setFlatList(buildFlatList());
    }, [buildFlatList]);

    useInput((input, key) => {
        if (!isActive) return;

        const currentIndex = flatList.findIndex(item => item.path === cursor);

        if (key.downArrow) {
            const nextIndex = Math.min(flatList.length - 1, currentIndex + 1);
            setCursor(flatList[nextIndex].path);
        }

        if (key.upArrow) {
            const prevIndex = Math.max(0, currentIndex - 1);
            setCursor(flatList[prevIndex].path);
        }

        if (key.rightArrow || key.return) {
            const item = flatList[currentIndex];
            if (item && item.isDir) {
                if (!expanded.has(item.path)) {
                    setExpanded(prev => new Set([...prev, item.path]));
                }
            }
        }

        if (key.leftArrow) {
            const item = flatList[currentIndex];
            if (item && item.isDir && expanded.has(item.path)) {
                const newExpanded = new Set(expanded);
                newExpanded.delete(item.path);
                setExpanded(newExpanded);
            } else {
                // Determine parent path to jump up
                const parentPath = path.dirname(item.path);
                if (parentPath && parentPath.length >= rootPath.length) {
                    setCursor(parentPath);
                }
            }
        }

        if (input === ' ') {
            const item = flatList[currentIndex];
            if (item && !item.isDir) {
                // Toggle selection
                if (onSelect) {
                    onSelect(item.path);
                }
            }
        }
    });

    // Calculate viewport based on cursor
    const cursorIndex = flatList.findIndex(item => item.path === cursor);
    // Ensure height is valid number
    const safeHeight = Math.max(5, height || 20);
    const renderStart = Math.max(0, Math.min(cursorIndex - Math.floor(safeHeight / 2), flatList.length - safeHeight));
    const renderEnd = Math.min(flatList.length, renderStart + safeHeight);

    const visibleItems = flatList.slice(renderStart, renderEnd);

    return h(Box, { flexDirection: 'column', width: width, height: safeHeight },
        visibleItems.map((item) => {
            const isSelected = selectedFiles.has(item.path);
            const isCursor = item.path === cursor;

            // Indentation
            const indent = '  '.repeat(Math.max(0, item.depth));

            // Icon
            let icon = item.isDir
                ? (item.isExpanded ? '▼ ' : '▶ ')
                : (isSelected ? '[x] ' : '[ ] ');

            // Color logic
            let color = 'white';
            if (item.isDir) color = 'cyan';
            if (isSelected) color = 'green';

            // Cursor style
            const bg = isCursor ? 'blue' : undefined;
            const textColor = isCursor ? 'white' : color;

            return h(Box, { key: item.path, width: '100%' },
                h(Text, {
                    backgroundColor: bg,
                    color: textColor,
                    wrap: 'truncate'
                }, `${indent}${icon}${item.name}`)
            );
        })
    );
};

export default FileTree;
