import type { DragEvent as ReactDragEvent, MouseEvent as ReactMouseEvent } from "react";
import { ExplorerTree, type ExplorerTreeNodeContext } from "@govoplan/core-webui";
import type { FolderNode } from "../types";
import { normalizeFolder, treeNodeKey } from "../utils/fileManagerUtils";

type FileActionTarget = { spaceId: string; folderPath: string };

export function FolderTree({
  nodes,
  activeSpaceId,
  spaceId,
  currentFolder,
  dropTargetKey = "",
  expandedKeys,
  onOpen,
  onToggle,
  onContextMenu,
  onDragOverTarget,
  onDropOnTarget,
  onClearDropState,
  onRequestDragExpand,
  onDragStartFolder,
  onDragEndFolder,
  dragDropEnabled = true,
  contextMenuEnabled = true,
  disabled,
  depth = 1
}: {
  nodes: FolderNode[];
  activeSpaceId: string;
  spaceId: string;
  currentFolder: string;
  dropTargetKey?: string;
  expandedKeys: Set<string>;
  onOpen: (spaceId: string, path: string) => void;
  onToggle: (spaceId: string, path: string) => void;
  onContextMenu?: (event: ReactMouseEvent<HTMLElement>, spaceId: string, path: string) => void;
  onDragOverTarget?: (event: ReactDragEvent<HTMLElement>, target: FileActionTarget) => void;
  onDropOnTarget?: (event: ReactDragEvent<HTMLElement>, target: FileActionTarget) => Promise<void>;
  onClearDropState?: () => void;
  onRequestDragExpand?: (spaceId: string, path: string) => void;
  onDragStartFolder?: (spaceId: string, path: string, event: ReactDragEvent<HTMLElement>) => void;
  onDragEndFolder?: () => void;
  dragDropEnabled?: boolean;
  contextMenuEnabled?: boolean;
  disabled?: boolean;
  depth?: number;
}) {
  return (
    <ExplorerTree
      nodes={nodes}
      getNodeId={(node) => treeNodeKey(spaceId, node.path)}
      getNodeLabel={(node) => node.name}
      getNodeChildren={(node) => node.children}
      activeId={activeSpaceId === spaceId ? treeNodeKey(spaceId, currentFolder) : ""}
      expandedIds={expandedKeys}
      onOpen={(node) => onOpen(spaceId, node.path)}
      onToggle={(node) => onToggle(spaceId, node.path)}
      disabled={disabled}
      depth={depth}
      getNodeWrapClassName={(node) => {
        const target = { spaceId, folderPath: node.path };
        return dragDropEnabled && dropTargetKey === `${target.spaceId}:${normalizeFolder(target.folderPath)}` ? "is-drop-target" : undefined;
      }}
      getNodeWrapStyle={(_node, context: ExplorerTreeNodeContext) => ({ paddingLeft: `${Math.min(context.depth * 14, 56)}px` })}
      getNodeDraggable={() => dragDropEnabled && !disabled}
      onContextMenu={contextMenuEnabled && onContextMenu ? (event, node) => onContextMenu(event, spaceId, node.path) : undefined}
      onDragStart={dragDropEnabled && onDragStartFolder ? (event, node) => onDragStartFolder(spaceId, node.path, event) : undefined}
      onDragEnd={dragDropEnabled && onDragEndFolder ? () => onDragEndFolder() : undefined}
      onDragOver={dragDropEnabled && onDragOverTarget ? (event, node, context) => {
        const target = { spaceId, folderPath: node.path };
        onDragOverTarget(event, target);
        if (context.hasChildren && !context.expanded) onRequestDragExpand?.(spaceId, node.path);
      } : undefined}
      onDragLeave={dragDropEnabled && onClearDropState ? () => onClearDropState() : undefined}
      onDrop={dragDropEnabled && onDropOnTarget ? (event, node) => void onDropOnTarget(event, { spaceId, folderPath: node.path }) : undefined}
    />
  );
}
