/*
    ! /server/actions.js
    ? Dynamic action loader for Socket.IO events using a recursive file system scan.
*/

// % imports
import fs from 'fs';
import path from 'path';
import { fileURLToPath, pathToFileURL } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

// % Target directory where the actual action files reside
const actionsDir = path.join(__dirname, '..', 'actions');

// $ debug-output
console.info('[Paths] Actions:', actionsDir);

/*
    $ Recursive function to load action files and build a flat map for direct dot-notation access
    = Maps all JavaScript files inside the actions directory into a flat key-value structure (e.g. 'chat.message').

    ^ Usage in WebSocket (Socket.io) Handlers:
    ?? import actions from './actions/index.js';
    ? Example: "socket.on('chat.message', (data) => actions['chat.message'](socket, data));"
    ? Example: "socket.on('system.ping', () => actions['system.ping'](socket));"
*/

async function loadActions(dir = actionsDir, baseDir = actionsDir, actionsObj = {}) {
    const entries = fs.readdirSync(dir, { withFileTypes: true });

    for (const entry of entries) {
        const fullPath = path.join(dir, entry.name);

        if (entry.isDirectory()) {
            // ~ Pass the main object (actionsObj) further down recursively
            await loadActions(fullPath, baseDir, actionsObj);
        } else if (entry.isFile() && entry.name !== 'index.js' && !entry.name.startsWith('.') && entry.name.endsWith('.js')) {
            // ~ Calculate the relative path from the root directory
            const relativePath = path.relative(baseDir, fullPath);
            const parts = relativePath.split(path.sep).map(p => p.replace(/\.js$/, ''));

            // ~ Import the module
            const fileUrl = pathToFileURL(fullPath).href;
            const module = await import(fileUrl);

            // ~ Map the module directly as a flat string key (e.g. "chat.message") into the main object
            const eventName = parts.join('.');
            actionsObj[eventName] = module.default || module;
        }
    }
    return actionsObj;
}

// $ Initialize asynchronously and export the loaded actions object
const actions = await loadActions();
export default actions;