/**
 * Registre unique pour étendre l'admin sans modifier le core.
 *
 * Trois types d'extensions :
 *   - widget : une tuile du tableau de bord. Côté serveur on enregistre un fetcher
 *              (registerWidgetFetcher), côté client le Composant (registerWidget).
 *   - navItem : une entrée de la sidebar admin (section optionnelle pour grouper).
 *   - page : un composant rendu sous /admin/<slug>.
 *
 * Les Maps sont stockées sur `globalThis` via `Symbol.for` pour survivre :
 *   1. au hot-reload de Next.js dev (sinon les enregistrements disparaissent).
 *   2. à la double-instanciation du fichier — l'instrumentation hook tourne en
 *      Node natif (require ESM), tandis que les Server Components passent par
 *      le bundle Turbopack/Webpack. Sans `globalThis`, les nav items poussés
 *      par `register-server.js` au boot ne seraient pas visibles côté Server
 *      Component qui rend la sidebar — la sidebar resterait vide.
 */

const REGISTRY_KEY = Symbol.for('__ZEN_ADMIN_REGISTRY__');
if (!globalThis[REGISTRY_KEY]) {
  globalThis[REGISTRY_KEY] = {
    widgetFetchers:   new Map(), // id -> async () => data
    widgetComponents: new Map(), // id -> { Component, order, permission }
    navItems:         new Map(), // id -> { id, label, icon, href, basePath, order, sectionId, position, permission }
    navSections:      new Map(), // id -> { id, title, icon, order }
    pages:            new Map(), // slug -> { slug, Component, title?, breadcrumbLabel? }
  };
}
const { widgetFetchers, widgetComponents, navItems, navSections, pages } = globalThis[REGISTRY_KEY];

// ---- Widgets ---------------------------------------------------------------

export function registerWidgetFetcher(id, fetcher) {
  widgetFetchers.set(id, fetcher);
}

export function registerWidget({ id, Component, order = 0, permission }) {
  widgetComponents.set(id, { Component, order, permission });
}

export function getWidgets() {
  return [...widgetComponents.entries()]
    .map(([id, v]) => ({ id, ...v }))
    .sort((a, b) => a.order - b.order);
}

// Un fetcher qui échoue n'empêche pas les autres de produire leur donnée.
export async function collectWidgetData() {
  const entries = [...widgetFetchers.entries()];
  const results = await Promise.allSettled(
    entries.map(async ([id, fetch]) => [id, await fetch()])
  );
  const out = {};
  for (const r of results) {
    if (r.status === 'fulfilled') {
      const [id, data] = r.value;
      out[id] = data;
    }
  }
  return out;
}

// ---- Navigation ------------------------------------------------------------

export function registerNavSection({ id, title, icon, order = 0 }) {
  navSections.set(id, { id, title, icon, order });
}

export function registerNavItem({ id, label, icon, href, basePath, order = 0, sectionId = 'main', position, permission }) {
  navItems.set(id, { id, label, icon, href, basePath, order, sectionId, position, permission });
}

export function getNavSections() {
  return [...navSections.values()].sort((a, b) => a.order - b.order);
}

export function getNavItems() {
  return [...navItems.values()].sort((a, b) => a.order - b.order);
}

// ---- Pages -----------------------------------------------------------------

export function registerPage({ slug, Component, title, breadcrumbLabel }) {
  pages.set(slug, { slug, Component, title, breadcrumbLabel });
}

export function getPage(slug) {
  return pages.get(slug);
}

export function getPages() {
  return [...pages.values()];
}
