/**
 * Plugin menu contribution resolution (ticket #43, F3, carnet §7.1/§7.2).
 *
 * Pure functions over a {@link PluginRuntimeRegistry} snapshot — no React, so
 * they're trivially unit-testable. `ProjectsView` (the menu bar owner) calls
 * these to build the extra `MenuBarMenu`/`MenuBarItem` entries it splices in
 * between/into the native menus.
 */

import type { MenuTargetId, ResolvedPluginMenuItem } from "@/domain";
import { evaluateWhen, type PluginRuntimeRegistry, type WhenContext } from "@/plugins/runtime";

export interface ResolvedTopLevelMenu {
  id: `plugin:${string}`;
  pluginId: string;
  label: string;
  icon?: string;
  order: number;
}

/**
 * Top-level plugin menus, sorted by `order` then plugin display name then
 * label (carnet §7.1) — rendered between `Panneaux` and `Paramètres`.
 */
export function resolveTopLevelMenus(registry: PluginRuntimeRegistry): ResolvedTopLevelMenu[] {
  return registry
    .topLevelMenus()
    .map(({ pluginId, pluginDisplayName, menu }) => ({
      id: `plugin:${menu.id}` as const,
      pluginId,
      pluginDisplayName,
      label: menu.label,
      icon: menu.icon,
      order: menu.order ?? 0,
    }))
    .sort(
      (a, b) =>
        a.order - b.order ||
        a.pluginDisplayName.localeCompare(b.pluginDisplayName) ||
        a.label.localeCompare(b.label),
    );
}

/**
 * Menu items contributed into one target menu (native `panels`/`settings` or a
 * plugin's own top-level menu, `plugin:<menuId>`), `when`-evaluated and sorted
 * by `order` then plugin display name then label (carnet §7.2). A disabled
 * plugin contributes nothing (its entries are simply absent from the
 * registry, carnet §1.3) — this function has nothing extra to filter for that.
 */
export function resolveMenuItems(
  registry: PluginRuntimeRegistry,
  targetMenuId: MenuTargetId,
  whenCtx: WhenContext,
): ResolvedPluginMenuItem[] {
  return registry
    .menuItems()
    .filter(({ item }) => item.targetMenuId === targetMenuId)
    .map(({ pluginId, pluginDisplayName, item }) => {
      const result = evaluateWhen(item.when, whenCtx);
      return {
        id: item.id,
        pluginId,
        pluginDisplayName,
        targetMenuId: item.targetMenuId,
        label: item.label,
        command: item.command,
        enabled: result.ok ? result.value : false,
        disabledReason: result.ok ? undefined : result.reason,
        groupLabel: pluginDisplayName,
        order: item.order ?? 0,
        iconUrl: item.icon,
      } satisfies ResolvedPluginMenuItem;
    })
    .sort(
      (a, b) =>
        a.order - b.order ||
        a.pluginDisplayName.localeCompare(b.pluginDisplayName) ||
        a.label.localeCompare(b.label),
    );
}
