'use client';

import { useCallback, useRef } from 'react';
import { cn } from '@djangocfg/ui-core/lib';

import { TreeProvider, useTreeContext } from './context/TreeContext';
import { TreeContent } from './components/TreeContent';
import { TreeSearchInput } from './components/TreeSearchInput';
import { appearanceToStyle } from './data/appearance';
import { useTreeKeyboard } from './hooks/useTreeKeyboard';
import { useTreeTypeAhead } from './hooks/useTreeTypeAhead';
import type { TreeRootProps } from './types';

/**
 * High-level entry point. Wraps Provider + (optional) search bar + content.
 *
 * For full control, compose with <TreeProvider>, <TreeContent>,
 * <TreeSearchInput>, <TreeRow>, etc. directly from `@djangocfg/ui-tools/tree`.
 */
function TreeRoot<T>(props: TreeRootProps<T>) {
  const {
    data,
    getItemName,
    loadChildren,
    selectionMode,
    initialExpandedIds,
    initialSelectedIds,
    indent,
    appearance,
    onSelectionChange,
    onExpansionChange,
    onActivate,
    enableSearch = false,
    enableTypeAhead = true,
    showIndentGuides = false,
    renderRow,
    renderIcon,
    renderLabel,
    renderActions,
    renderContextMenu,
    labels,
    persistKey,
    persistSelection = false,
    className,
    style,
  } = props;

  return (
    <TreeProvider<T>
      data={data}
      getItemName={getItemName}
      loadChildren={loadChildren}
      selectionMode={selectionMode}
      initialExpandedIds={initialExpandedIds}
      initialSelectedIds={initialSelectedIds}
      indent={indent}
      appearance={appearance}
      onSelectionChange={onSelectionChange}
      onExpansionChange={onExpansionChange}
      onActivate={onActivate}
      enableSearch={enableSearch}
      showIndentGuides={showIndentGuides}
      renderIcon={renderIcon}
      renderLabel={renderLabel}
      renderActions={renderActions}
      renderContextMenu={renderContextMenu}
      labels={labels}
      persistKey={persistKey}
      persistSelection={persistSelection}
    >
      <TreeRootShell<T>
        className={className}
        style={style}
        enableSearch={enableSearch}
        enableTypeAhead={enableTypeAhead}
        renderRow={renderRow}
      />
    </TreeProvider>
  );
}

interface TreeRootShellProps<T> {
  className?: string;
  style?: React.CSSProperties;
  enableSearch: boolean;
  enableTypeAhead: boolean;
  renderRow?: TreeRootProps<T>['renderRow'];
}

function TreeRootShell<T>({
  className,
  style,
  enableSearch,
  enableTypeAhead,
  renderRow,
}: TreeRootShellProps<T>) {
  const containerRef = useRef<HTMLDivElement>(null);
  const ctx = useTreeContext<T>();

  // Keyboard navigation (↑↓ ←→ Home/End Enter Esc) — scoped via callback ref.
  const { ref: keyboardRef } = useTreeKeyboard<T>({
    rows: ctx.flatRows,
    focusedId: ctx.focused,
    onFocus: ctx.setFocus,
    onSelect: ctx.select,
    onActivate: (id) => {
      const row = ctx.flatRows.find((r) => r.node.id === id);
      if (row) ctx.activate(row.node);
    },
    onExpand: ctx.expand,
    onCollapse: ctx.collapse,
    onClearSelection: ctx.clearSelection,
  });

  const setContainerRef = useCallback(
    (instance: HTMLDivElement | null) => {
      containerRef.current = instance;
      keyboardRef(instance);
    },
    [keyboardRef],
  );

  // Type-ahead jump.
  const onTypeAheadMatch = useCallback(
    (id: string) => {
      ctx.setFocus(id);
      // Scroll the row into view if it has rendered.
      const el = containerRef.current?.querySelector<HTMLElement>(
        `[data-tree-row][data-id="${CSS.escape(id)}"]`,
      );
      el?.scrollIntoView({ block: 'nearest' });
    },
    [ctx],
  );

  useTreeTypeAhead<T>({
    rows: ctx.flatRows,
    getItemName: ctx.getItemName,
    containerRef,
    onMatch: onTypeAheadMatch,
    enabled: enableTypeAhead,
  });

  return (
    <div
      ref={setContainerRef}
      tabIndex={0}
      className={cn(
        'group/tree flex h-full w-full flex-col gap-2 outline-none',
        className,
      )}
      style={{ ...appearanceToStyle(ctx.appearance), ...style }}
      data-tree-root=""
    >
      {enableSearch ? <TreeSearchInput className="mx-2 mt-2" /> : null}
      <div className="min-h-0 flex-1 overflow-auto px-1">
        <TreeContent<T>>{renderRow}</TreeContent>
      </div>
    </div>
  );
}

export default TreeRoot;
export { TreeRoot };
