/**
 * @license Copyright (c) 2017-2025, CKSource Holding sp. z o.o. All rights reserved.
 * For licensing, see LICENSE.md.
 */

'use strict';

const upath = require( 'upath' );
const importModule = require( '../helpers/import-module' );

/**
 * This function executes all hooks of the specified type for each config passed in the configs array.
 * Each hook should be a path to desired function. Hooks object in the config should look like so:
 *
 * "hooks": {
 *     "beforeHexo": [
 *         "../path/to/function_one.js",
 *         "../path/to/function_two.js"
 *     ],
 *     "afterHexo": [
 *         "../path/to/function_three.js"
 *     ]
 * }
 *
 * @param {Array} configs Array of all the configurations that might contain hooks to execute.
 * @param {'beforeHexo'|'afterHexo'} hookName Name of a hook to execute.
 * @returns {Promise}
 */
module.exports = async function executeHooks( configs, hookName ) {
	try {
		for ( const config of configs ) {
			if ( !config.hooks || !config.hooks[ hookName ] ) {
				continue;
			}

			for ( const scriptPath of config.hooks[ hookName ] ) {
				await processSingleHook( upath.dirname( config.__configPath ), scriptPath );
			}
		}

		return Promise.resolve();
	} catch ( error ) {
		console.error( `The "${ hookName }" hook pointing to the "${ error._filePath }" file ended with an error.`, error.message );

		// Re-throwing the error as we want to break the build process.
		throw error;
	}
};

/**
 * @param {String} configPath
 * @param {String} scriptPath
 * @return {Promise}
 */
async function processSingleHook( configPath, scriptPath ) {
	const callbackAbsolutePath = upath.join( configPath, scriptPath );

	try {
		const callback = await importModule( callbackAbsolutePath );

		await callback();
	} catch ( error ) {
		// Store a path to the executed file.
		error._filePath = scriptPath;

		// Rejecting the promise allows catching it later.
		return Promise.reject( error );
	}
}
