import { logger } from '../../utils/logger';
import * as fs from 'fs';
import * as path from 'path';

export interface BizPlugin {
  name: string;
  version: string;
  description: string;
  onLoad(): Promise<void>;
  onUnload(): Promise<void>;
  hooks: Record<string, (payload: any) => Promise<any>>;
}

/**
 * [ARCH_OPT_01] 轻量级业务插件动态加载 (Lightweight Plugin Architecture)
 * @description 核心逻辑：解耦核心引擎与具体业务逻辑。
 * 支持通过扫描特定目录动态加载业务插件（如：特定平台的刊登逻辑、
 * 特定租户的特殊定价规则）。利用钩子（Hook）机制实现对核心流程的非侵入式扩展。
 */
export class PluginManager {
  private static plugins: Map<string, BizPlugin> = new Map();
  private static readonly PLUGIN_DIR = path.join(__dirname, '../../plugins');

  /**
   * 扫描并加载所有插件
   */
  static async loadPlugins() {
    if (!fs.existsSync(this.PLUGIN_DIR)) {
      fs.mkdirSync(this.PLUGIN_DIR, { recursive: true });
    }

    const files = fs.readdirSync(this.PLUGIN_DIR);
    for (const file of files) {
      if (file.endsWith('.plugin.ts') || file.endsWith('.plugin.js')) {
        try {
          const pluginModule = require(path.join(this.PLUGIN_DIR, file));
          const plugin: BizPlugin = new pluginModule.default();
          
          await plugin.onLoad();
          this.plugins.set(plugin.name, plugin);
          logger.info(`[PluginManager] Loaded plugin: ${plugin.name} v${plugin.version}`);
        } catch (err: any) {
          logger.error(`[PluginManager] Failed to load plugin ${file}: ${err.message}`);
        }
      }
    }
  }

  /**
   * 触发业务钩子
   */
  static async triggerHook(hookName: string, payload: any): Promise<any> {
    let currentPayload = payload;
    for (const plugin of this.plugins.values()) {
      if (plugin.hooks[hookName]) {
        try {
          currentPayload = await plugin.hooks[hookName](currentPayload);
        } catch (err: any) {
          logger.error(`[PluginManager] Plugin ${plugin.name} hook ${hookName} failed: ${err.message}`);
        }
      }
    }
    return currentPayload;
  }

  /**
   * 卸载插件
   */
  static async unloadPlugin(name: string) {
    const plugin = this.plugins.get(name);
    if (plugin) {
      await plugin.onUnload();
      this.plugins.delete(name);
      logger.info(`[PluginManager] Unloaded plugin: ${name}`);
    }
  }
}
