import { useEffect, useState, type ReactNode } from 'react';
import { EditorExtensionsProvider, type EditorExtensionsValue } from '@ablogcms/block-editor/editor-extensions';

type BlockEditorExtensionsProviderChildren = ReactNode | ((value: EditorExtensionsValue | null) => ReactNode);

/**
 * unit-editor 経由（unit-editor / inplace-editor / config-editor の block-editor ユニット定義）で
 * プラグイン拡張（`registerExtension` / `registerBlockDefinition`）を BlockEditor へ横流しする。
 * `BlockEditorSettingsProvider`（EditorSettings の Context 注入）と同じ理由・同じパターンで、
 * unit-editor パッケージ自体はレジストリ解決を持ち込まず、コア側のこの Provider が担う。
 *
 * Tiptap ランタイムの取得は動的 import（`webpackChunkName: "block-editor"`）にし、admin.js 初期
 * バンドルに Tiptap を巻き込まない（mount-block-editor.tsx と同じ設計）。解決が終わるまでは
 * `EditorExtensionsProvider` に `null` を渡す。子孫（`BlockEditorUnitContent` 等）は `null` の間
 * BlockEditor をレンダーしない前提のため、拡張が反映されないまま初期化される事故を避けられる。
 *
 * `children` は通常の ReactNode に加え、`(value) => ReactNode` の render-prop 形式も受け付ける。
 * `BlockEditorSettingsProvider` の `blockDefinitions` prop へ、ここで解決した値をそのまま渡したい
 * 呼び出し側（`mount-unit-*.tsx`）が、2 つの Provider の親子関係を跨いで値を受け渡すために使う。
 */
function BlockEditorExtensionsProvider({ children }: { children: BlockEditorExtensionsProviderChildren }) {
  const [value, setValue] = useState<EditorExtensionsValue | null>(null);

  useEffect(() => {
    let canceled = false;
    Promise.all([
      import(/* webpackChunkName: "block-editor" */ '@ablogcms/block-editor/tiptap'),
      import(/* webpackChunkName: "block-editor" */ '../block-definitions'),
    ])
      .then(([{ tiptap }, { getBlockExtensions, getBlockDefinitions }]) => {
        if (canceled) {
          return;
        }
        setValue({
          extensions: getBlockExtensions(tiptap),
          blockDefinitions: getBlockDefinitions(tiptap),
        });
      })
      .catch((err) => {
        if (canceled) {
          return;
        }
        // チャンクロード失敗・ファクトリ例外でこの機能だけを止め、呼び出し側（BlockEditor 全体）まで
        // 巻き込まないための意図的なログ。value は null のまま残るため子孫は BlockEditor をレンダーしない。

        console.error(
          '[block-editor] プラグイン拡張（registerExtension/registerBlockDefinition）の解決に失敗しました。',
          err
        );
      });
    return () => {
      canceled = true;
    };
  }, []);

  return (
    <EditorExtensionsProvider value={value}>
      {typeof children === 'function' ? children(value) : children}
    </EditorExtensionsProvider>
  );
}

export default BlockEditorExtensionsProvider;
