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

'use strict';

const crypto = require( 'crypto' );

/**
 * Generates a random ID with a single segment. If a prefix is provided, it will be prepended to the ID.
 *
 * The `gen-` prefix is always used to easier extract the generated IDs from the output.
 *
 * @param [prefix] Optional prefix to add to the ID
 * @param [maskable=true] Whether the ID should be replaceable by regenerateRandomIds.
 * @return The generated ID with optional prefix
 */
function randomId( prefix, maskable = true ) {
	const shortId = crypto.randomBytes( 3 ).toString( 'hex' ).substring( 0, 5 );

	let id = prefix ? `${ prefix }-${ shortId }` : shortId;

	if ( maskable ) {
		id = `gen-${ id }`;
	}

	return id;
};

/**
 * Regenerates random IDs in a string.
 *
 * It finds all occurrences of IDs generated by `randomId()` and replaces them with new random IDs.
 * If an ID is repeated in the input string, it will be replaced with the same new ID.
 * It preserves the prefix of the original ID.
 *
 * @param str The string to process.
 * @returns The string with regenerated IDs.
 */
function regenerateRandomIds( str ) {
	const idCache = new Map();
	const idRegex = /(gen-(?:[a-zA-Z0-9]+-)*[a-f0-9]{5})/g;

	return str.replace( idRegex, oldId => {
		if ( idCache.has( oldId ) ) {
			return idCache.get( oldId );
		}

		// Everything after 'gen-'.
		const idContent = oldId.substring( 4 );
		const parts = idContent.split( '-' );

		// The ID has 1 segment at the end. If there are more parts, it means a prefix is present.
		const prefix = parts.length > 1 ? parts.slice( 0, -1 ).join( '-' ) : undefined;
		const newId = randomId( prefix );

		idCache.set( oldId, newId );

		return newId;
	} );
}

module.exports = {
	randomId,
	regenerateRandomIds
};
