'use client';

import { Loader2 } from 'lucide-react';
import { cn } from '@djangocfg/ui-core/lib';

import { useTreeContext } from '../context/TreeContext';
import { radiusClass, rowStateClasses } from '../data/appearance';
import type { FlatRow, TreeRowRenderProps } from '../types';
import { TreeChevron } from './TreeChevron';
import { TreeIcon } from './TreeIcon';
import { TreeIndentGuides } from './TreeIndentGuides';
import { TreeLabel } from './TreeLabel';

export interface TreeRowProps<T> {
  row: FlatRow<T>;
  className?: string;
}

export function TreeRow<T>({ row, className }: TreeRowProps<T>) {
  const ctx = useTreeContext<T>();
  const {
    appearance,
    showIndentGuides,
    selected,
    focused,
    matchingIds,
    select,
    toggle,
    setFocus,
    activate,
    getItemName,
    renderIcon,
    renderLabel,
    renderActions,
    renderContextMenu,
  } = ctx;

  const { node, level, isFolder, isExpanded, isLoading } = row;
  const isSelected = selected.has(node.id);
  const isFocused = focused === node.id;
  const isMatchingSearch = matchingIds.has(node.id);

  const slot: TreeRowRenderProps<T> = {
    node,
    level,
    isSelected,
    isExpanded,
    isFocused,
    isFolder,
    isLoading,
    isMatchingSearch,
  };

  const handleActivate = () => {
    if (node.disabled) return;
    setFocus(node.id);
    select(node.id);
    if (isFolder) toggle(node.id);
    else activate(node);
  };

  const handleClick = (e: React.MouseEvent<HTMLDivElement>) => {
    handleActivate();
    e.currentTarget.scrollIntoView?.({ block: 'nearest' });
  };

  const handleDoubleClick = () => {
    if (node.disabled) return;
    if (!isFolder) activate(node);
  };

  const trigger = (
    <div
      role="treeitem"
      aria-level={level + 1}
      aria-expanded={isFolder ? isExpanded : undefined}
      aria-selected={isSelected || undefined}
      aria-current={isSelected ? 'true' : undefined}
      aria-disabled={node.disabled || undefined}
      data-tree-row=""
      data-id={node.id}
      data-selected={isSelected ? 'true' : undefined}
      data-focused={isFocused && !isSelected ? 'true' : undefined}
      data-folder={isFolder || undefined}
      data-expanded={isExpanded || undefined}
      tabIndex={isFocused ? 0 : -1}
      style={{
        paddingLeft: 6 + level * appearance.indent,
        height: 'var(--tree-row-height)',
        gap: 'var(--tree-gap)',
      }}
      onClick={handleClick}
      onDoubleClick={handleDoubleClick}
      onFocus={() => setFocus(node.id)}
      className={cn(
        'group/row relative flex w-full select-none items-center pr-2 text-left',
        'transition-colors outline-none',
        node.disabled ? 'cursor-not-allowed' : 'cursor-pointer',
        radiusClass(appearance),
        rowStateClasses(appearance),
        'focus-visible:ring-1 focus-visible:ring-ring/50',
        isMatchingSearch && 'ring-1 ring-primary/30',
        node.disabled && 'opacity-50',
        className,
      )}
    >
      {/* Active-row left indicator (VSCode style) */}
      {appearance.showActiveIndicator && isSelected ? (
        <span
          aria-hidden
          className={cn(
            'absolute left-0 top-1 bottom-1 w-0.5 rounded-r-full',
            'bg-foreground/30 group-focus-within/tree:bg-primary',
          )}
        />
      ) : null}

      {showIndentGuides && level > 0 ? (
        <TreeIndentGuides level={level} indent={appearance.indent} />
      ) : null}

      <TreeChevron isExpanded={isExpanded} isFolder={isFolder} />

      {isLoading ? (
        <Loader2
          aria-hidden
          strokeWidth={appearance.iconStrokeWidth}
          style={{ width: 'var(--tree-icon-size)', height: 'var(--tree-icon-size)' }}
          className="shrink-0 animate-spin text-muted-foreground/70"
        />
      ) : renderIcon ? (
        renderIcon(slot)
      ) : (
        <TreeIcon isFolder={isFolder} isExpanded={isExpanded} />
      )}

      <span
        className="flex min-w-0 flex-1 items-center"
        style={{ gap: 'var(--tree-gap)' }}
      >
        {renderLabel ? (
          renderLabel(slot)
        ) : (
          <TreeLabel isMatchingSearch={isMatchingSearch}>{getItemName(node)}</TreeLabel>
        )}
      </span>

      {renderActions ? (
        <span
          className="ml-auto flex shrink-0 items-center gap-1 opacity-0 transition-opacity group-hover/row:opacity-100 group-focus-within/row:opacity-100"
          onClick={(e) => e.stopPropagation()}
        >
          {renderActions(slot)}
        </span>
      ) : null}
    </div>
  );

  if (renderContextMenu) {
    return <>{renderContextMenu(slot, trigger)}</>;
  }
  return trigger;
}
