import type { MarkdownHeading } from 'astro';
import { PAGE_TITLE_ID } from '../constants';

export interface TocItem extends MarkdownHeading {
	children: TocItem[];
}

interface TocOpts {
	minHeadingLevel: number;
	maxHeadingLevel: number;
	title: string;
}

/** Convert the flat headings array generated by Astro into a nested tree structure. */
export function generateToC(
	headings: MarkdownHeading[],
	{ minHeadingLevel, maxHeadingLevel, title }: TocOpts
) {
	headings = headings.filter(({ depth }) => depth >= minHeadingLevel && depth <= maxHeadingLevel);
	const toc: Array<TocItem> = [{ depth: 2, slug: PAGE_TITLE_ID, text: title, children: [] }];
	for (const heading of headings) injectChild(toc, { ...heading, children: [] });
	return toc;
}

/** Inject a ToC entry as deep in the tree as its `depth` property requires. */
function injectChild(items: TocItem[], item: TocItem): void {
	const lastItem = items.at(-1);
	if (!lastItem || lastItem.depth >= item.depth) {
		items.push(item);
	} else {
		return injectChild(lastItem.children, item);
	}
}
