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

'use strict';

const { cloneDeep } = require( 'lodash' );
const { stringify } = require( 'javascript-stringify' );
const fs = require( 'fs' );
const upath = require( 'upath' );

const defaultScriptTemplate = fs.readFileSync( upath.join( __dirname, 'templates', 'scripts', 'default.js' ), 'utf-8' );
const groupScriptTemplate = fs.readFileSync( upath.join( __dirname, 'templates', 'scripts', 'group.js' ), 'utf-8' );
const rootScriptTemplate = fs.readFileSync( upath.join( __dirname, 'templates', 'scripts', 'root.js' ), 'utf-8' );

module.exports = ( searchConfig, {
	groups = [],
	slug = '',
	customRanking = []
} = {} ) => {
	if ( !searchConfig ) {
		return null;
	}

	const dConfig = cloneDeep( searchConfig );
	dConfig.customRanking = dConfig.customRanking || [];
	const customRankingAll = Array.from( new Set( customRanking.concat( dConfig.customRanking ) ) );
	delete dConfig.customRanking;

	const options = {
		inputSelector: '#docsearch_input',
		algoliaOptions: {
			hitsPerPage: 250,
			attributesToRetrieve: '*'
		}
	};

	const docSearchConfig = Object.assign(
		{},
		dConfig,
		options,
		{
			isEnabled: Boolean( dConfig.apiKey && dConfig.indexName ),
			css: 'https://cdn.jsdelivr.net/docsearch.js/1/docsearch.min.css',
			js: 'https://cdn.jsdelivr.net/docsearch.js/2/docsearch.min.js'
		}
	);
	const innerConfig = Object.assign(
		{},
		dConfig,
		options
	);

	docSearchConfig.scripts = {
		defaultScript: [
			'<script type="text/javascript">',
			`docsearch(${ stringify( innerConfig ) });`,
			'</script>'
		].join( '\n' )
	};

	const transformDataFunctions = getTransformDataFns( groups, slug );

	if ( transformDataFunctions ) {
		for ( const tag of Object.keys( transformDataFunctions ) ) {
			const innerConfigStr = stringify( innerConfig ).replace( /^{|}$/g, '' );

			docSearchConfig.scripts[ tag ] = [
				'<script type="text/javascript">',
				'docsearch({',
				`${ innerConfigStr },`,
				`transformData: ${ transformDataFunctions[ tag ] }`,
				'});',
				'</script>'
			].join( '\n' );
		}
	}

	docSearchConfig.getCustomRanking = pagePath => {
		if ( !customRankingAll.length ) {
			return null;
		}

		const rankingDataOfPage = customRankingAll.find( data => {
			return data.url && pagePath.includes( data.url );
		} );

		return rankingDataOfPage ? rankingDataOfPage.rank : null;
	};

	return docSearchConfig;
};

function getTransformDataFns( groups, slug ) {
	const functions = {
		rootScript: fillTemplate( rootScriptTemplate.toString() )
	};

	if ( !Array.isArray( groups ) || groups.length === 0 ) {
		return functions;
	}

	const tags = `${ groups.map( group => `${ group.slug }` ).join( '\', \'' ) }`;

	for ( const group of groups ) {
		const groupSlug = group.slug;

		functions[ groupSlug ] = fillTemplate( groupScriptTemplate.toString(), { tags, slug, groupSlug } );
	}

	functions.defaultScript = fillTemplate( defaultScriptTemplate.toString(), { tags, slug } );

	return functions;
}

function fillTemplate( template, data ) {
	let updatedTemplate = template.replace( /^function [\S]+\( hits \)/, 'function( hits )' );

	for ( const key in data ) {
		const pattern = new RegExp( `{{{ ${ key } }}}`, 'g' );

		updatedTemplate = updatedTemplate.replace( pattern, data[ key ] );
	}

	return updatedTemplate.replace( /\n\s*/g, '' );
}
