import type { FileTreeRow } from "@/lib/file-tree/types";

export function inferDropTargetDocId(targetRow: FileTreeRow | null): string | null {
  if (!targetRow) return null;
  return targetRow.docId ?? null;
}

export type ParentEdge = { id: string; parentId: string | null };

export function buildParentById(edges: ParentEdge[]): Map<string, string | null> {
  const map = new Map<string, string | null>();
  edges.forEach((edge) => {
    map.set(edge.id, edge.parentId ?? null);
  });
  return map;
}

export function isAncestorOf(
  ancestorId: string,
  nodeId: string,
  parentById: Map<string, string | null>,
): boolean {
  let current: string | null | undefined = nodeId;
  while (current) {
    const parent = parentById.get(current);
    if (!parent) return false;
    if (parent === ancestorId) return true;
    current = parent;
  }
  return false;
}

export function filterTopLevelDocIds(
  docIds: string[],
  parentById: Map<string, string | null>,
): string[] {
  const unique = Array.from(new Set(docIds));
  const selected = new Set(unique);
  return unique.filter((id) => {
    let current: string | null | undefined = id;
    while (current) {
      const parent = parentById.get(current);
      if (!parent) return true;
      if (selected.has(parent)) return false;
      current = parent;
    }
    return true;
  });
}

export function isInvalidDocDrop(args: {
  sourceDocIds: string[];
  targetParentId: string | null;
  parentById: Map<string, string | null>;
}): boolean {
  const { sourceDocIds, targetParentId, parentById } = args;
  if (!targetParentId) return false;
  const sources = new Set(sourceDocIds);
  if (sources.has(targetParentId)) return true;
  for (const sourceId of sources) {
    if (isAncestorOf(sourceId, targetParentId, parentById)) return true;
  }
  return false;
}

