"use strict";
/**
 * Server-side Plugin Initialization
 *
 * This module provides utilities for loading and registering plugins
 * for the test executor. Plugins can be:
 * 1. Registered manually via registerServerPlugin()
 * 2. Discovered automatically from a plugins folder via discoverPlugins()
 */
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.setPluginsDirectory = setPluginsDirectory;
exports.getPluginsDirectory = getPluginsDirectory;
exports.registerServerPlugin = registerServerPlugin;
exports.registerServerPlugins = registerServerPlugins;
exports.discoverPlugins = discoverPlugins;
exports.loadPlugin = loadPlugin;
exports.loadTestFilePlugins = loadTestFilePlugins;
exports.loadAllPlugins = loadAllPlugins;
exports.initializeServerPlugins = initializeServerPlugins;
exports.getServerPlugins = getServerPlugins;
exports.isPluginLoaded = isPluginLoaded;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const jiti_1 = require("jiti");
const core_1 = require("../core");
// Create jiti instance for loading TypeScript plugins at runtime
// Configure it to resolve modules from the user's working directory
const jiti = (0, jiti_1.createJiti)(__filename, {
    interopDefault: true,
    moduleCache: false,
    alias: {
        // Allow plugins to import from 'testblocks' even if they use old relative paths
        '../../src/core': path.join(__dirname, '..', 'core'),
        '../src/core': path.join(__dirname, '..', 'core'),
        './src/core': path.join(__dirname, '..', 'core'),
    },
});
// Track initialization
let pluginsInitialized = false;
// List of registered plugins
const registeredPlugins = new Map();
// Plugins directory (can be overridden)
let pluginsDirectory = path.join(process.cwd(), 'plugins');
/**
 * Set the plugins directory path
 */
function setPluginsDirectory(dir) {
    pluginsDirectory = path.isAbsolute(dir) ? dir : path.join(process.cwd(), dir);
    console.log(`Plugins directory set to: ${pluginsDirectory}`);
}
/**
 * Get the current plugins directory
 */
function getPluginsDirectory() {
    return pluginsDirectory;
}
/**
 * Register a plugin for server-side use
 * This registers the plugin's blocks with the core block registry
 */
function registerServerPlugin(plugin) {
    if (registeredPlugins.has(plugin.name)) {
        console.log(`Plugin already registered: ${plugin.name}`);
        return;
    }
    try {
        (0, core_1.registerPlugin)(plugin);
        registeredPlugins.set(plugin.name, plugin);
        console.log(`Registered plugin: ${plugin.name}`);
    }
    catch (error) {
        console.error(`Failed to register plugin "${plugin.name}":`, error);
        throw error;
    }
}
/**
 * Register multiple plugins at once
 */
function registerServerPlugins(plugins) {
    for (const plugin of plugins) {
        registerServerPlugin(plugin);
    }
}
/**
 * Discover and list available plugins from the plugins directory
 * Returns plugin file names (without extension)
 */
function discoverPlugins() {
    if (!fs.existsSync(pluginsDirectory)) {
        console.log(`Plugins directory not found: ${pluginsDirectory}`);
        return [];
    }
    const files = fs.readdirSync(pluginsDirectory);
    const plugins = [];
    for (const file of files) {
        // Look for .js or compiled .js files (not .d.ts)
        if ((file.endsWith('.js') || file.endsWith('.ts')) && !file.endsWith('.d.ts')) {
            const pluginName = file.replace(/\.(js|ts)$/, '');
            if (pluginName !== 'index') {
                plugins.push(pluginName);
            }
        }
    }
    console.log(`Discovered ${plugins.length} plugin(s): ${plugins.join(', ')}`);
    return plugins;
}
/**
 * Load a specific plugin by name from the plugins directory
 */
async function loadPlugin(pluginName) {
    // Check if already loaded
    if (registeredPlugins.has(pluginName)) {
        return registeredPlugins.get(pluginName);
    }
    const jsPath = path.join(pluginsDirectory, `${pluginName}.js`);
    const tsPath = path.join(pluginsDirectory, `${pluginName}.ts`);
    let pluginPath = null;
    let isTypeScript = false;
    if (fs.existsSync(jsPath)) {
        pluginPath = jsPath;
    }
    else if (fs.existsSync(tsPath)) {
        pluginPath = tsPath;
        isTypeScript = true;
    }
    if (!pluginPath) {
        console.error(`Plugin not found: ${pluginName} (looked in ${pluginsDirectory})`);
        return null;
    }
    try {
        console.log(`Loading plugin: ${pluginName} from ${pluginPath}`);
        // Use jiti for TypeScript files, dynamic import for JavaScript
        let module;
        if (isTypeScript) {
            module = jiti(pluginPath);
        }
        else {
            module = await Promise.resolve(`${pluginPath}`).then(s => __importStar(require(s)));
        }
        // Look for default export or named export matching plugin name
        const plugin = module.default ||
            module[pluginName.replace(/-./g, x => x[1].toUpperCase()) + 'Plugin'] ||
            module[pluginName.replace(/-/g, '') + 'Plugin'] ||
            Object.values(module).find((exp) => typeof exp === 'object' && exp !== null && 'name' in exp && 'blocks' in exp);
        if (!plugin) {
            console.error(`No valid plugin export found in ${pluginPath}`);
            return null;
        }
        registerServerPlugin(plugin);
        return plugin;
    }
    catch (error) {
        console.error(`Failed to load plugin ${pluginName}:`, error);
        return null;
    }
}
/**
 * Load plugins specified in a test file
 */
async function loadTestFilePlugins(pluginNames) {
    for (const name of pluginNames) {
        await loadPlugin(name);
    }
}
/**
 * Load all discovered plugins from the plugins directory
 */
async function loadAllPlugins() {
    const pluginNames = discoverPlugins();
    await loadTestFilePlugins(pluginNames);
}
/**
 * Initialize server plugins (call after all plugins are registered)
 */
function initializeServerPlugins() {
    if (pluginsInitialized) {
        return;
    }
    pluginsInitialized = true;
    console.log(`Server plugins initialized: ${registeredPlugins.size} plugin(s) loaded`);
}
/**
 * Get all registered server plugins
 */
function getServerPlugins() {
    return Array.from(registeredPlugins.values());
}
/**
 * Check if a plugin is registered
 */
function isPluginLoaded(pluginName) {
    return registeredPlugins.has(pluginName);
}
