import * as React from 'react';
import { ChevronRight, ChevronDown } from 'lucide-react';
import { cn } from '../../shared/utils';
import { useTreeView, type TreeNode } from './use-tree-view';

interface TreeViewProps extends React.HTMLAttributes<HTMLDivElement> {
  data: TreeNode[];
  /** Called when a node is clicked or activated via keyboard. */
  onNodeClick?: (node: TreeNode) => void;
  /** Called when a node becomes the selected item. Prefer this over `onNodeClick` for selection logic. */
  onNodeSelect?: (node: TreeNode) => void;
  defaultExpanded?: string[];
  /** Controlled selected node ID. When provided, selection state is managed externally. */
  selectedNodeId?: string;
  /** Accessible label for the tree widget. */
  ariaLabel?: string;
}

/**
 * Hierarchical tree navigation component.
 *
 * @description
 * Renders a nested tree structure for browsing hierarchical data such as file
 * systems, category trees, or organizational charts. Nodes can be expanded
 * and collapsed independently. Supports custom icons per node, controlled
 * selection, and full WAI-ARIA keyboard navigation.
 *
 * Headless logic is available via `useTreeView` for custom tree UIs.
 *
 * @ai-rules
 * 1. Each `TreeNode` must have a unique `id`.
 * 2. Leaf nodes (no `children`) do not render expand arrows.
 * 3. Use `onNodeSelect` for selection and `onNodeClick` for any click side-effect.
 * 4. Pass `selectedNodeId` to control selection externally.
 * 5. Keyboard: Arrow Up/Down navigate siblings, Arrow Right expands / enters child, Arrow Left collapses / goes to parent, Home/End jump to first/last visible node.
 */
const TreeView = React.forwardRef<HTMLDivElement, TreeViewProps>(
  (
    {
      className,
      data,
      onNodeClick,
      onNodeSelect,
      defaultExpanded = [],
      selectedNodeId,
      ariaLabel,
      ...props
    },
    ref
  ) => {
    const { expanded, effectiveSelectedId, getNodeRef, toggleExpand, handleSelect, handleKeyDown } =
      useTreeView({ data, defaultExpanded, selectedNodeId, onNodeClick, onNodeSelect });

    const focusableId = effectiveSelectedId ?? data[0]?.id;

    return (
      <div
        ref={ref}
        className={cn('w-full', className)}
        role="tree"
        aria-label={ariaLabel ?? 'Navegação em árvore'}
        {...props}
      >
        {data.map(node => (
          <TreeNodeComponent
            key={node.id}
            node={node}
            level={0}
            expanded={expanded}
            selectedId={effectiveSelectedId}
            focusableId={focusableId}
            onToggle={toggleExpand}
            onSelect={handleSelect}
            onKeyDown={handleKeyDown}
            getNodeRef={getNodeRef}
          />
        ))}
      </div>
    );
  }
);
TreeView.displayName = 'TreeView';

interface TreeNodeComponentProps {
  node: TreeNode;
  level: number;
  expanded: Set<string>;
  selectedId: string | undefined;
  focusableId: string | undefined;
  onToggle: (nodeId: string) => void;
  onSelect: (node: TreeNode) => void;
  onKeyDown: (e: React.KeyboardEvent, node: TreeNode) => void;
  getNodeRef: (nodeId: string) => (el: HTMLButtonElement | null) => void;
}

const TreeNodeComponent: React.FC<TreeNodeComponentProps> = ({
  node,
  level,
  expanded,
  selectedId,
  focusableId,
  onToggle,
  onSelect,
  onKeyDown,
  getNodeRef,
}) => {
  const hasChildren = !!node.children?.length;
  const isExpanded = expanded.has(node.id);
  const isSelected = node.id === selectedId;

  const handleClick = () => {
    if (hasChildren) onToggle(node.id);
    onSelect(node);
  };

  return (
    <div role="none">
      <button
        ref={getNodeRef(node.id)}
        role="treeitem"
        aria-expanded={hasChildren ? isExpanded : undefined}
        aria-selected={isSelected}
        tabIndex={node.id === focusableId ? 0 : -1}
        onClick={handleClick}
        onKeyDown={e => onKeyDown(e, node)}
        className={cn(
          'flex w-full items-center gap-2 rounded-[var(--radius)] px-2 py-1.5 text-left transition-colors',
          'hover:bg-muted focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1',
          isSelected && 'bg-primary/10 text-primary font-medium'
        )}
        style={{ paddingLeft: `${level * 1.5 + 0.5}rem` }}
      >
        {hasChildren ? (
          <span className="flex-shrink-0 text-muted-foreground">
            {isExpanded ? (
              <ChevronDown className="h-4 w-4" />
            ) : (
              <ChevronRight className="h-4 w-4" />
            )}
          </span>
        ) : (
          <span className="w-4 flex-shrink-0" aria-hidden="true" />
        )}
        {node.icon && <span className="flex-shrink-0 text-muted-foreground">{node.icon}</span>}
        <span className="flex-1 text-foreground">{node.label}</span>
      </button>
      {hasChildren && isExpanded && (
        <div role="group">
          {node.children!.map(child => (
            <TreeNodeComponent
              key={child.id}
              node={child}
              level={level + 1}
              expanded={expanded}
              selectedId={selectedId}
              focusableId={focusableId}
              onToggle={onToggle}
              onSelect={onSelect}
              onKeyDown={onKeyDown}
              getNodeRef={getNodeRef}
            />
          ))}
        </div>
      )}
    </div>
  );
};

export { TreeView };
export type { TreeViewProps };
export type { TreeNode } from './use-tree-view';
