import { jsxs, jsx } from 'react/jsx-runtime';
import React__default, { useCallback, useState, useMemo } from 'react';
import { motion, AnimatePresence, useReducedMotion } from 'motion/react';
import { cn } from '../../../utils/cn.js';
import { treeTheme } from './Tree.theme.js';
import { Checkbox } from '../../forms/Checkbox/Checkbox.js';
import { ChevronRightIcon, DocumentIcon } from '@heroicons/react/24/outline';
import { getReducedMotionVariants, treeNodeVariants, expandIconVariants, childNodeVariants, childrenStagger } from './Tree.animations.js';

// Simplified selection utilities (merged from Tree.utils.ts)
const getDescendantIds = (node) => {
    const descendants = [];
    const traverse = (currentNode) => {
        if (currentNode.children) {
            currentNode.children.forEach(child => {
                descendants.push(child.id);
                traverse(child);
            });
        }
    };
    traverse(node);
    return descendants;
};
const calculateSelection = (nodeId, selectedKeys, data) => {
    // Find the node in the tree
    const findNode = (nodes, id) => {
        for (const node of nodes) {
            if (node.id === id)
                return node;
            if (node.children) {
                const found = findNode(node.children, id);
                if (found)
                    return found;
            }
        }
        return null;
    };
    const node = findNode(data, nodeId);
    if (!node)
        return { selectedKeys, indeterminateKeys: [] };
    const isCurrentlySelected = selectedKeys.includes(nodeId);
    let newSelectedKeys = [...selectedKeys];
    if (isCurrentlySelected) {
        // Deselecting: remove this node and all its descendants
        const descendantIds = getDescendantIds(node);
        newSelectedKeys = newSelectedKeys.filter(id => id !== nodeId && !descendantIds.includes(id));
    }
    else {
        // Selecting: add this node and all its descendants
        const descendantIds = getDescendantIds(node);
        newSelectedKeys.push(nodeId, ...descendantIds);
        newSelectedKeys = Array.from(new Set(newSelectedKeys));
    }
    // Calculate indeterminate states (simplified)
    const indeterminateKeys = [];
    const calculateIndeterminate = (nodes) => {
        nodes.forEach(node => {
            if (node.children && node.children.length > 0) {
                const childrenIds = node.children.map(child => child.id);
                const selectedChildren = childrenIds.filter(id => newSelectedKeys.includes(id));
                // Node is indeterminate if some (but not all) children are selected
                if (selectedChildren.length > 0 && selectedChildren.length < childrenIds.length && !newSelectedKeys.includes(node.id)) {
                    indeterminateKeys.push(node.id);
                }
                calculateIndeterminate(node.children);
            }
        });
    };
    calculateIndeterminate(data);
    return {
        selectedKeys: newSelectedKeys,
        indeterminateKeys
    };
};
const InternalTreeNode = React__default.memo(({ node, level, expanded, selected, isIndeterminate, selectable, checkable, hierarchicalSelection, expandable, expandedKeysSet, selectedKeysSet, indeterminateKeysSet, onNodeClick, onToggleExpand, theme, className, shouldReduceMotion, }) => {
    var _a;
    const hasChildren = node.children && node.children.length > 0;
    const isExpandable = expandable && hasChildren;
    // Get appropriate animation variants based on reduced motion preference
    const nodeVariants = shouldReduceMotion ? getReducedMotionVariants(treeNodeVariants) : treeNodeVariants;
    const iconVariants = shouldReduceMotion ? getReducedMotionVariants(expandIconVariants) : expandIconVariants;
    const childVariants = shouldReduceMotion ? getReducedMotionVariants(childNodeVariants) : childNodeVariants;
    const handleNodeClick = useCallback((e) => {
        e.stopPropagation();
        if (node.disabled)
            return;
        if (selectable) {
            onNodeClick(node);
        }
    }, [node, selectable, onNodeClick]);
    const handleExpandClick = useCallback((e) => {
        e.stopPropagation();
        if (isExpandable && !node.disabled) {
            onToggleExpand(node);
        }
    }, [isExpandable, node, onToggleExpand]);
    const handleKeyDown = (e) => {
        if (node.disabled)
            return;
        switch (e.key) {
            case 'Enter':
            case ' ':
                e.preventDefault();
                if (selectable) {
                    onNodeClick(node);
                }
                break;
            case 'ArrowRight':
                if (isExpandable && !expanded) {
                    e.preventDefault();
                    onToggleExpand(node);
                }
                break;
            case 'ArrowLeft':
                if (isExpandable && expanded) {
                    e.preventDefault();
                    onToggleExpand(node);
                }
                break;
        }
    };
    const nodeStyle = cn(theme.nodeStyle, {
        'opacity-50 cursor-not-allowed': node.disabled,
        'cursor-pointer': (selectable || (hasChildren && expandable)) && !node.disabled,
    }, className);
    const labelStyle = cn(theme.labelStyle, {
        'text-[var(--color-text-muted)]': node.disabled,
    });
    return (jsxs("div", { children: [jsxs("div", { className: nodeStyle, style: { paddingLeft: `calc(${level} * ${theme.indentSize} + 0.25rem)` }, onClick: handleNodeClick, onKeyDown: handleKeyDown, tabIndex: node.disabled ? -1 : 0, role: "treeitem", "aria-expanded": isExpandable ? expanded : false, "aria-selected": selectable ? selected : undefined, "aria-disabled": node.disabled, children: [isExpandable ? (jsx(motion.span, { className: cn(theme.expandIconStyle), variants: iconVariants, initial: "collapsed", animate: expanded ? "expanded" : "collapsed", onClick: handleExpandClick, role: "button", "aria-label": expanded ? 'Collapse' : 'Expand', tabIndex: -1, children: jsx(ChevronRightIcon, { className: "size-4", strokeWidth: 2 }) })) : (jsx("span", { className: "w-4 mr-1" })), checkable && (jsx(Checkbox, { size: 'sm', id: `tree-checkbox-${node.id}`, name: `tree-checkbox-${node.id}`, value: node.id, checked: selected, indeterminate: hierarchicalSelection && isIndeterminate, onChange: () => onNodeClick(node), state: node.disabled ? "disabled" : "default", className: "flex-shrink-0", onClick: (e) => e.stopPropagation() })), (node.icon || !isExpandable) && (jsx("span", { className: cn(theme.iconStyle), children: node.icon || jsx(DocumentIcon, { className: "w-4 h-4" }) })), jsx("span", { className: labelStyle, title: node.label, children: node.label })] }), hasChildren && (jsx(AnimatePresence, { initial: false, children: expanded && (jsx(motion.div, { variants: nodeVariants, initial: "collapsed", animate: "expanded", exit: "collapsed", style: {
                        overflow: 'hidden',
                        transformOrigin: 'top'
                    }, transition: shouldReduceMotion ? { duration: 0.01 } : childrenStagger, children: (_a = node.children) === null || _a === void 0 ? void 0 : _a.map((childNode, index) => (jsx(motion.div, { variants: childVariants, initial: "hidden", animate: "visible", exit: "hidden", custom: index, children: jsx(InternalTreeNode, { node: childNode, level: level + 1, expanded: expandedKeysSet.has(childNode.id), selected: selectedKeysSet.has(childNode.id), isIndeterminate: indeterminateKeysSet.has(childNode.id), selectable: selectable, checkable: checkable, hierarchicalSelection: hierarchicalSelection, expandable: expandable, expandedKeysSet: expandedKeysSet, selectedKeysSet: selectedKeysSet, indeterminateKeysSet: indeterminateKeysSet, onNodeClick: onNodeClick, onToggleExpand: onToggleExpand, theme: theme, shouldReduceMotion: shouldReduceMotion }) }, childNode.id))) }, `${node.id}-children`)) }))] }));
});
const TreeRoot = React__default.forwardRef(({ data, selectable = false, checkable = false, hierarchicalSelection, expandable = true, defaultExpandedKeys = [], defaultSelectedKeys = [], onSelectionChange, onExpand, className, theme: customTheme = {}, ...htmlProps }, ref) => {
    var _a;
    // Auto-enable hierarchical selection when checkboxes are used, unless explicitly overridden
    const enableHierarchicalSelection = hierarchicalSelection !== null && hierarchicalSelection !== void 0 ? hierarchicalSelection : checkable;
    const shouldReduceMotion = (_a = useReducedMotion()) !== null && _a !== void 0 ? _a : false;
    const theme = {
        ...treeTheme,
        ...customTheme,
    };
    // Simplified state management
    const [expandedKeys, setExpandedKeys] = useState(defaultExpandedKeys);
    const [selectedKeys, setSelectedKeys] = useState(defaultSelectedKeys);
    const [indeterminateKeys, setIndeterminateKeys] = useState([]);
    const expandedKeysSet = useMemo(() => new Set(expandedKeys), [expandedKeys]);
    const selectedKeysSet = useMemo(() => new Set(selectedKeys), [selectedKeys]);
    const indeterminateKeysSet = useMemo(() => new Set(indeterminateKeys), [indeterminateKeys]);
    // Handle node selection
    const handleNodeSelect = useCallback((node) => {
        if (!selectable || node.disabled)
            return;
        if (enableHierarchicalSelection && checkable) {
            // Hierarchical selection mode
            const result = calculateSelection(node.id, selectedKeys, data);
            setSelectedKeys(result.selectedKeys);
            setIndeterminateKeys(result.indeterminateKeys);
            // Call callback with simplified signature
            onSelectionChange === null || onSelectionChange === void 0 ? void 0 : onSelectionChange(result.selectedKeys, node, result.indeterminateKeys);
        }
        else {
            // Simple selection mode
            let newSelectedKeys;
            if (checkable) {
                // Multi-selection mode
                if (selectedKeys.includes(node.id)) {
                    newSelectedKeys = selectedKeys.filter(key => key !== node.id);
                }
                else {
                    newSelectedKeys = [...selectedKeys, node.id];
                }
            }
            else {
                // Single selection mode
                newSelectedKeys = selectedKeys.includes(node.id) ? [] : [node.id];
            }
            setSelectedKeys(newSelectedKeys);
            onSelectionChange === null || onSelectionChange === void 0 ? void 0 : onSelectionChange(newSelectedKeys, node);
        }
    }, [selectedKeys, data, selectable, checkable, enableHierarchicalSelection, onSelectionChange]);
    // Handle node expand/collapse
    const handleNodeToggleExpand = useCallback((node) => {
        if (!expandable || node.disabled)
            return;
        const isExpanded = expandedKeys.includes(node.id);
        let newExpandedKeys;
        if (isExpanded) {
            newExpandedKeys = expandedKeys.filter(key => key !== node.id);
        }
        else {
            newExpandedKeys = [...expandedKeys, node.id];
        }
        setExpandedKeys(newExpandedKeys);
        onExpand === null || onExpand === void 0 ? void 0 : onExpand(newExpandedKeys, node, !isExpanded);
    }, [expandedKeys, expandable, onExpand]);
    return (jsx("div", { ref: ref, className: cn(theme.baseStyle, 'tree-container', className), role: "tree", "aria-multiselectable": checkable, ...htmlProps, children: data.map((node) => (jsx(InternalTreeNode, { node: node, level: 0, expanded: expandedKeysSet.has(node.id), selected: selectedKeysSet.has(node.id), isIndeterminate: indeterminateKeysSet.has(node.id), selectable: selectable, checkable: checkable, hierarchicalSelection: enableHierarchicalSelection, expandable: expandable, expandedKeysSet: expandedKeysSet, selectedKeysSet: selectedKeysSet, indeterminateKeysSet: indeterminateKeysSet, onNodeClick: handleNodeSelect, onToggleExpand: handleNodeToggleExpand, theme: theme, shouldReduceMotion: shouldReduceMotion }, node.id))) }));
});
TreeRoot.displayName = 'Tree';
// Simplified compound component
const Tree = TreeRoot;

export { Tree };
