import type { AnyExtension } from '@ablogcms/block-editor/tiptap/core';
import type { Tiptap } from '@ablogcms/block-editor/tiptap';
import type { BlockDefinition } from '@ablogcms/block-editor/types';
import { getBlockDefinitionRegistry, getBlockExtensionRegistry } from '@ablogcms/plugins/core';

/**
 * unit-editor / block-editor 双方のマウント経路で使う共通ロジック。プラグインが
 * `ctx.blockEditor.registerExtension` / `registerBlockDefinition` で登録した「Tiptap ランタイムを
 * 受け取って値を返すファクトリ」を実際の tiptap で評価する。
 *
 * 呼び出し側（各 mount 関数）は、この関数をモジュールトップレベルではなく
 * 関数本体（ACMS.Ready 経由で呼ばれる時点、かつブロックエディターのチャンクがロードされ
 * tiptap が手に入った時点）で呼ぶこと（features/unit-editor/unit-definitions.ts と同じ登録タイミング制約）。
 *
 * ファクトリが throw した場合はそのエントリだけスキップし console.error でログする。
 * 1 プラグインの不具合でエディター全体を止めないため。
 */

export function getBlockExtensions(tiptap: Tiptap): AnyExtension[] {
  const registry = getBlockExtensionRegistry();
  return Object.entries(registry.getAll()).flatMap(([name, factory]) => {
    try {
      const result = factory(tiptap);
      return Array.isArray(result) ? result : [result];
    } catch (err) {
      console.error(`[block-editor] registerExtension("${name}") のファクトリが例外を投げました。`, err);
      return [];
    }
  });
}

export function getBlockDefinitions(tiptap: Tiptap): Record<string, BlockDefinition> {
  const registry = getBlockDefinitionRegistry();
  const result: Record<string, BlockDefinition> = {};
  for (const [name, factory] of Object.entries(registry.getAll())) {
    try {
      result[name] = factory(tiptap);
    } catch (err) {
      console.error(`[block-editor] registerBlockDefinition("${name}") のファクトリが例外を投げました。`, err);
    }
  }
  return result;
}
