/**
 * ZEN Initialization
 *
 * Wires core feature dependencies into the API router.
 * This is the composition root — the only place that connects features to core.
 *
 * @example
 * // instrumentation.js
 * export async function register() {
 *   if (process.env.NEXT_RUNTIME === 'nodejs') {
 *     const { initializeZen } = await import('@zen/core');
 *     await initializeZen();
 *   }
 * }
 */

import { configureRouter, registerFeatureRoutes, clearRouterConfig, clearFeatureRoutes } from '@zen/core/api';
import { registerStoragePolicies, clearStorageConfig } from '@zen/core/storage';
import { validateSession } from '../../features/auth/session.js';
import { routes as authRoutes } from '../../features/auth/api.js';
import { routes as mediaRoutes } from '../../features/media/routes.server.js';
import { MEDIA_PERMISSION_DEFINITIONS } from '../../features/media/permissions.js';
import { storageAccessPolicies } from '../../features/auth/storage-policies.js';
import { PERMISSION_DEFINITIONS } from '../../core/users/constants.js';
import { registerPermissions, clearRegisteredPermissions } from '../../core/users/permissions-registry.js';
import { registerModules, validateModuleEnvVars } from '../../core/modules/discover.server.js';
import { getRegisteredModules, clearRegisteredModules } from '../../core/modules/registry.js';
import { done, warn } from './logger.js';

const ZEN_INIT_KEY = Symbol.for('__ZEN_INITIALIZED__');

/**
 * @param {object} [options]
 * @param {Array<{ name: string, exports: object }>} [options.modules]
 *   Manifeste de modules statique généré par `npx zen-modules sync` dans le
 *   projet consommateur. Le top-level await dans le manifeste a déjà déclenché
 *   `exports.register()` au moment de son import — initializeZen() se contente
 *   d'enregistrer chaque module dans le registre interne pour que `getRegisteredModules`
 *   retourne les bons objets côté serveur.
 */
export async function initializeZen({ modules = [] } = {}) {
  if (typeof window !== 'undefined') {
    return { skipped: true, reason: 'client-side' };
  }

  if (globalThis[ZEN_INIT_KEY]) {
    warn('ZEN: already initialized, skipping');
    return { skipped: true, reason: 'already-initialized' };
  }

  globalThis[ZEN_INIT_KEY] = true;

  configureRouter({ resolveSession: validateSession });
  registerFeatureRoutes(authRoutes);
  registerFeatureRoutes(mediaRoutes);
  registerStoragePolicies(storageAccessPolicies);
  registerPermissions(PERMISSION_DEFINITIONS);
  registerPermissions(MEDIA_PERMISSION_DEFINITIONS);

  // Activation des modules @zen/module-* via le manifeste statique fourni.
  registerModules(modules);
  const registered = getRegisteredModules();
  validateModuleEnvVars(registered);
  for (const mod of registered) {
    if (Array.isArray(mod.manifest?.permissions)) {
      registerPermissions(mod.manifest.permissions);
    }
  }

  done('ZEN: ready');

  return {};
}

export function resetZenInitialization() {
  globalThis[ZEN_INIT_KEY] = false;
  clearRouterConfig();
  clearFeatureRoutes();
  clearStorageConfig();
  clearRegisteredPermissions();
  clearRegisteredModules();
  warn('ZEN: initialization reset');
}
