import Logger from './log/Logger.js';
import FilePipe from './file/FilePipe.js';
import ModelCaller from './api/ModelCaller.js';
import Options from './api/Options.js';

// 【逃生通道】创建一个纯净的 Console 对象，绕过任何潜在的劫持
const getSafeConsole = () => {
    try {
        if (window._amilySafeConsole) return window._amilySafeConsole;
        
        const iframe = document.createElement('iframe');
        iframe.style.display = 'none';
        document.body.appendChild(iframe);
        const safe = iframe.contentWindow.console;
        // document.body.removeChild(iframe); // 保持 iframe 以维持 console 引用有效
        window._amilySafeConsole = safe;
        return safe;
    } catch (e) {
        return window.console; // Fallback
    }
};

class Amily2Bus {
    constructor() {
        this.safeConsole = getSafeConsole();

        // 1. 初始化 Logger
        /** @type {Logger} */
        this.Logger = new Logger(this.safeConsole);
        /** @type {FilePipe} */
        this.FilePipe = new FilePipe();

        // 2. 依赖注入 (Dependency Injection)
        // 创建一个 Logger 代理适配器传给 ModelCaller
        const loggerDelegate = {
            log: (type, message, origin, plugin) => {
                // 回调 Bus 的 Logger 实例
                this.Logger.process(plugin || 'Global', origin || 'Model', type, message);
            }
        };

        // ModelCaller 不再包含 Bus，只包含 logger 代理
        /** @type {ModelCaller} */
        this.ModelCaller = new ModelCaller(loggerDelegate);

        // 存储上下文引用（严格锁：每个插件名仅限一次成功注册）
        this.registry = new Map();
        // 存储公开的联动接口（联动模块）
        this.publicRegistry = new Map();

        this.safeConsole.log('[Amily2Bus] Core Initialized (Decoupled Architecture).');

        // 3. 自动注册并锁定 PUBLIC 命名空间
        this._initPublicNamespace();
    }

    /**
     * 初始化系统保留的 PUBLIC 模块
     * 用于提供系统级信息的联动查询，防止 PUBLIC 命名被滥用
     */
    _initPublicNamespace() {
        try {
            // 这里利用 register 的机制，直接抢占 'PUBLIC' 并加上严格锁
            const sysCtx = this.register('PUBLIC');

            // 暴露系统级能力给 query('PUBLIC')
            sysCtx.expose({
                description: 'Amily2 System Public Interface',
                version: '2.0.0-Core',

                // 允许查询当前有哪些插件暴露了公共接口
                getAvailableModules: () => {
                    return Array.from(this.publicRegistry.keys());
                },

                // 允许查询当前所有已注册（被锁定的）插件名
                getRegisteredPlugins: () => {
                    return Array.from(this.registry.keys());
                },

                // 简单的系统状态检查
                ping: () => 'pong'
            });

            // 内部记录一条初始化日志
            sysCtx.log('System', 'info', 'PUBLIC namespace reserved and strictly locked.');

        } catch (e) {
            this.safeConsole.error('[Amily2Bus] CRITICAL: Failed to init PUBLIC namespace.', e);
        }
    }
    /**
     * 直接记录系统级日志 (Global Scope)
     * 支持手动指定来源，方便终端调试或非插件环境调用
     * @param {string} type 日志级别 (debug, info, warn, error)
     * @param {string} message 消息内容
     * @param {string} [origin='Bus' 来源模块，默认为 'Bus'
     * @param {string} [plugin='Global'] 来源插件/命名空间，调试时可指定如 'Console'
     */
    log(type, message, origin = 'Bus', plugin = 'Global') {
        if (this.Logger) {
            this.Logger.process(plugin, origin, type, message);
        }
    }
    /**
     * 注册插件并获取专属上下文 (严格锁机制)
     * @param {string} pluginName 插件名称
     * @returns {Object} 包含该插件专属 API 的上下文对象
     */
    register(pluginName) {
        if (!pluginName || typeof pluginName !== 'string') {
            throw new Error('[Amily2Bus] Invalid plugin name.');
        }

        if (this.registry.has(pluginName)) {
            const errorMsg = `[Amily2Bus] Security Error: Plugin '${pluginName}' is already registered and locked.`;
            this.safeConsole.error(errorMsg);
            throw new Error(errorMsg);
        }

        // 返回该插件专属的 API 上下文 (Capability Token)
        const context = {
            // 1. 日志能力 (绑定了身份的日志接口)
            log: (origin, type, message) => this.Logger.log(pluginName, origin, type, message),

            // 2. 文件能力 (绑定了身份的文件接口)
            file: {
                read: (path) => {
                    return this.FilePipe ? this.FilePipe.read(pluginName, path) : null;
                },
                write: (path, data) => {
                    return this.FilePipe ? this.FilePipe.write(pluginName, path, data) : false;
                }
            },

            // 3. 网络能力 (ModelCaller)
            model: {
                // 暴露 Options 类，方便插件直接 new context.model.Options() 或使用 builder
                Options: Options,
                // 插件调用时，Bus 负责将 pluginName 传给无状态的 ModelCaller
                call: (messages, options) => this.ModelCaller.call(pluginName, messages, options)
            },

            /**
             * 将本插件的能力暴露给公共查询池，实现插件间联动
             * @param {Object} apiMethods
             */
            expose: (apiMethods) => {
                if (typeof apiMethods !== 'object') throw new Error('Exposed API must be an object');
                this.publicRegistry.set(pluginName, Object.freeze(apiMethods));
                this.log('info', `Module exposed to public registry.`, 'Bus', pluginName);
            }
        };

        this.registry.set(pluginName, context);
        this.safeConsole.log(`[Amily2Bus] Plugin registered: ${pluginName}`);
        return context;
    }

    /**
     * 联动查询：获取其他插件通过 expose 暴露的能力
     * @param {string} pluginName 目标插件名称
     * @returns {Object|null}
     */
    query(pluginName) {
        return this.publicRegistry.get(pluginName) || null;
    }
}
// 挂载全局单例
if (!window.Amily2Bus) {
    window.Amily2Bus = new Amily2Bus();
}
export function initializeAmilyBus() {
    if (!(window.Amily2Bus instanceof Amily2Bus)) {
        window.Amily2Bus = new Amily2Bus();
        console.log('[Amily2] Amily2Bus 已成功初始化并附加到 window 对象');
    }
}

