/**
 * Extension Manager
 * 扩展管理器 - 聚合所有扩展，构建 Schema 和插件
 *
 * 参考：apps/outline/shared/editor/lib/ExtensionManager.ts
 */

import { Schema } from 'prosemirror-model';
import { keymap } from 'prosemirror-keymap';
import { inputRules as createInputRules } from 'prosemirror-inputrules';
import type {
  Plugin,
  Command,
  InputRule,
  NodeSpec,
  MarkSpec,
  SlashMenuItem,
  ToolbarItem,
} from './types';
import { Extension, NodeExtension, MarkExtension } from './Extension';

export interface ExtensionManagerOptions {
  /** 扩展实例数组 */
  extensions: Extension[];
}

export class ExtensionManager {
  private extensions: Extension[];
  private _schema: Schema | null = null;

  constructor(options: ExtensionManagerOptions) {
    this.extensions = options.extensions;
    this.initExtensions();
  }

  // ============================================================================
  // 初始化
  // ============================================================================

  private initExtensions(): void {
    for (const extension of this.extensions) {
      extension.onInit?.();
    }
  }

  // ============================================================================
  // Schema 构建
  // ============================================================================

  /**
   * 获取聚合的 ProseMirror Schema
   */
  get schema(): Schema {
    if (this._schema) {
      return this._schema;
    }

    const nodes: Record<string, NodeSpec> = {};
    const marks: Record<string, MarkSpec> = {};

    for (const extension of this.extensions) {
      if (extension instanceof NodeExtension && extension.schema) {
        nodes[extension.name] = extension.schema;
      } else if (extension instanceof MarkExtension && extension.schema) {
        marks[extension.name] = extension.schema;
      }
    }

    this._schema = new Schema({ nodes, marks });
    return this._schema;
  }

  // ============================================================================
  // 插件收集
  // ============================================================================

  /**
   * 获取所有扩展的插件
   */
  get plugins(): Plugin[] {
    const schema = this.schema;
    const plugins: Plugin[] = [];

    // 1. 收集各扩展的插件
    for (const extension of this.extensions) {
      const extensionPlugins = extension.plugins(schema);
      plugins.push(...extensionPlugins);
    }

    // 2. 添加输入规则插件
    const inputRulesPlugin = this.createInputRulesPlugin();
    if (inputRulesPlugin) {
      plugins.push(inputRulesPlugin);
    }

    // 3. 添加快捷键插件
    const keymapPlugin = this.createKeymapPlugin();
    if (keymapPlugin) {
      plugins.push(keymapPlugin);
    }

    return plugins;
  }

  /**
   * 创建输入规则插件
   */
  private createInputRulesPlugin(): Plugin | null {
    const schema = this.schema;
    const rules: InputRule[] = [];

    for (const extension of this.extensions) {
      const extensionRules = extension.inputRules(schema);
      rules.push(...extensionRules);
    }

    if (rules.length === 0) {
      return null;
    }

    return createInputRules({ rules });
  }

  /**
   * 创建快捷键插件
   */
  private createKeymapPlugin(): Plugin | null {
    const schema = this.schema;
    const keys: Record<string, Command> = {};

    for (const extension of this.extensions) {
      const extensionKeys = extension.keys(schema);
      Object.assign(keys, extensionKeys);
    }

    if (Object.keys(keys).length === 0) {
      return null;
    }

    return keymap(keys);
  }

  // ============================================================================
  // 菜单收集
  // ============================================================================

  /**
   * 获取所有斜杠菜单项
   */
  get slashMenuItems(): SlashMenuItem[] {
    const schema = this.schema;
    const items: SlashMenuItem[] = [];

    for (const extension of this.extensions) {
      const extensionItems = extension.slashMenuItems(schema);
      items.push(...extensionItems);
    }

    // 按优先级排序
    return items.sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
  }

  /**
   * 获取所有工具栏项
   */
  get toolbarItems(): ToolbarItem[] {
    const schema = this.schema;
    const items: ToolbarItem[] = [];

    for (const extension of this.extensions) {
      const extensionItems = extension.toolbarItems(schema);
      items.push(...extensionItems);
    }

    // 按优先级排序
    return items.sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
  }

  // ============================================================================
  // 工具方法
  // ============================================================================

  /**
   * 根据名称获取扩展
   */
  getExtension<T extends Extension>(name: string): T | undefined {
    return this.extensions.find((ext) => ext.name === name) as T | undefined;
  }

  /**
   * 获取所有节点扩展
   */
  get nodeExtensions(): NodeExtension[] {
    return this.extensions.filter((ext) => ext instanceof NodeExtension) as NodeExtension[];
  }

  /**
   * 获取所有标记扩展
   */
  get markExtensions(): MarkExtension[] {
    return this.extensions.filter((ext) => ext instanceof MarkExtension) as MarkExtension[];
  }

  // ============================================================================
  // 生命周期
  // ============================================================================

  /**
   * 销毁管理器，清理所有扩展
   */
  destroy(): void {
    for (const extension of this.extensions) {
      extension.onDestroy?.();
    }
    this.extensions = [];
    this._schema = null;
  }
}

// ============================================================================
// 工厂函数
// ============================================================================

/**
 * 创建扩展管理器
 */
export function createExtensionManager(extensions: Extension[]): ExtensionManager {
  return new ExtensionManager({ extensions });
}
