/**
 * scripts/generate-docs/lib/sidebar-builder.ts
 *
 * Reads `docs-src/_data/sidebar.json`, validates that every referenced page
 * exists in `docs-src/*.md`, and returns a per-page enriched copy with the
 * `active` flag injected on the current page entry.
 */
import { readFileSync } from 'node:fs';
import { join } from 'node:path';
import type { LocalisedString } from './markdown-parser';

const SIDEBAR_PATH = join(__dirname, '..', '..', '..', 'docs-src', '_data', 'sidebar.json');

export interface SidebarItem {
  page: string;
  icon: string;
  label: LocalisedString;
  active?: boolean;
  /** Optional nested entries rendered indented below the parent. */
  children?: SidebarItem[];
}

export interface SidebarSection {
  title: LocalisedString;
  items: SidebarItem[];
}

export interface Sidebar {
  sections: SidebarSection[];
}

let cached: Sidebar | null = null;

function loadSidebar(): Sidebar {
  if (cached) return cached;
  const raw = readFileSync(SIDEBAR_PATH, 'utf-8');
  cached = JSON.parse(raw) as Sidebar;
  return cached;
}

/**
 * Throws if any sidebar entry points to a page slug that wasn't found among
 * the parsed pages — catches "added link to sidebar but never to docs-src".
 * Recurses into `children`.
 */
export function validateSidebar(knownSlugs: string[]): void {
  const sidebar = loadSidebar();
  const known = new Set(knownSlugs);
  const missing: string[] = [];
  const visit = (item: SidebarItem): void => {
    if (!known.has(item.page)) missing.push(item.page);
    item.children?.forEach(visit);
  };
  for (const section of sidebar.sections) section.items.forEach(visit);
  if (missing.length) {
    throw new Error(
      `sidebar.json references pages that have no docs-src/<slug>.md: ${missing.join(', ')}`
    );
  }
}

/**
 * Returns a deep-cloned sidebar with `active: true` set on the item (or nested
 * child) whose `page` matches the current page slug. Cloning keeps each page
 * render independent.
 */
export function buildSidebarForPage(currentSlug: string): Sidebar {
  const sidebar = loadSidebar();
  const cloneItem = (item: SidebarItem): SidebarItem => ({
    ...item,
    active: item.page === currentSlug,
    children: item.children?.map(cloneItem),
  });
  return {
    sections: sidebar.sections.map((section) => ({
      title: section.title,
      items: section.items.map(cloneItem),
    })),
  };
}
