/** Relative path from repo/workspace root (no leading slash). */
export function toRelativePath(nodeId, rootId) {
  if (nodeId === rootId) return null;
  if (!nodeId.startsWith(rootId)) return nodeId;
  return nodeId.slice(rootId.length);
}

export function toNodeId(rootId, relativePath) {
  return `${rootId}${relativePath}`;
}

export function getRevisionPaths(entry) {
  return entry.changes.map((c) => c.path);
}

/** All file relative paths under a folder selection (or every file when root is selected). */
export function collectFilePaths(nodes, rootId, selectedIds) {
  const paths = new Set();

  function walk(node) {
    if (node.type === 'file') {
      paths.add(toRelativePath(node.id, rootId));
      return;
    }
    node.children?.forEach(walk);
  }

  function walkToSelected(node) {
    if (selectedIds.has(node.id)) {
      walk(node);
      return;
    }
    node.children?.forEach(walkToSelected);
  }

  for (const node of nodes) {
    walkToSelected(node);
  }

  return paths;
}

export function filterRevisions(revisionLog, selectedIds, rootId, treeNodes) {
  if (!selectedIds?.size) return revisionLog;

  const selectedRelative = [...selectedIds].map((id) => toRelativePath(id, rootId));
  const isRootOnly = selectedIds.size === 1 && selectedIds.has(rootId);

  if (isRootOnly) return revisionLog;

  const fileScope = collectFilePaths(treeNodes, rootId, selectedIds);

  return revisionLog.filter((entry) =>
    getRevisionPaths(entry).some((filePath) => {
      if (fileScope.has(filePath)) return true;
      return selectedRelative.some((sel) => {
        if (sel == null) return true;
        if (sel === filePath) return true;
        return filePath.startsWith(`${sel}/`);
      });
    })
  );
}

export function revisionCountForFile(revisionLog, relativePath) {
  return revisionLog.filter((entry) =>
    entry.changes.some((c) => c.path === relativePath)
  ).length;
}

export function formatChangeType(change) {
  if (change === 'added') return 'Added';
  if (change === 'deleted') return 'Deleted';
  return 'Edited';
}
