import { addVirtualImports } from '@withstudiocms/internal_helpers/astro-integration';
import createPathResolver from '@withstudiocms/internal_helpers/pathResolver';
import { convertToSafeString } from '@withstudiocms/internal_helpers/utils';
import type { AstroIntegration } from 'astro';

/**
 * Options for configuring the dynamic sitemap.
 */
interface DynamicSitemapOptions {
	/**
	 * An array of sitemap configurations.
	 */
	sitemaps: {
		/**
		 * The name of the plugin that generates the sitemap.
		 */
		pluginName: string;
		/**
		 * The endpoint path or URL where the sitemap XML can be accessed.
		 */
		sitemapXMLEndpointPath: string | URL;
	}[];
}

/**
 * Converts a given string to a safe string format by removing leading and trailing underscores,
 * and replacing the prefix 'studiocms_' if present.
 *
 * @param str - The input string to be converted.
 * @returns The converted safe string.
 */
export function safeString(str: string) {
	return convertToSafeString(str).replace(/^_+/, '').replace(/_+$/, '').replace('studiocms_', '');
}

/**
 * Generates a dynamic sitemap integration for Astro.
 *
 * @param {DynamicSitemapOptions} options - Configuration options for the dynamic sitemap.
 * @returns {AstroIntegration} The Astro integration object.
 *
 * The integration adds virtual imports for sitemaps and injects routes for the sitemap index and individual sitemaps.
 *
 * The `options` parameter should include:
 * - `sitemaps`: An array of objects, each containing:
 *   - `pluginName`: The name of the plugin.
 *   - `sitemapXMLEndpointPath`: The entry point path for the sitemap XML.
 *
 * The function performs the following steps:
 * 1. Creates a resolver using the current module URL.
 * 2. Adds virtual imports for the sitemaps.
 * 3. Injects a route for the sitemap index.
 * 4. Iterates over the provided sitemaps and injects routes for each sitemap.
 *
 * If multiple sitemaps have the same pattern, a unique pattern is generated by appending an index.
 */
export function dynamicSitemap(options: DynamicSitemapOptions): AstroIntegration {
	const { resolve } = createPathResolver(import.meta.url);

	return {
		name: 'studiocms/dynamic-sitemap',
		hooks: {
			/* v8 ignore start */
			'astro:config:setup': (params) => {
				const { injectRoute } = params;

				const { sitemaps } = options;

				addVirtualImports(params, {
					name: 'studiocms/dynamic-sitemap',
					imports: {
						'virtual:studiocms/sitemaps': `
                            export const sitemaps = ${JSON.stringify([...sitemaps.map(({ pluginName }) => `./sitemap-${safeString(pluginName)}.xml`)])};
                        `,
					},
				});

				injectRoute({
					entrypoint: resolve('./sitemap-index.xml.js'),
					pattern: '/sitemap-index.xml',
					prerender: false,
				});

				const existingSitemaps: string[] = [];

				for (const { pluginName, sitemapXMLEndpointPath: entrypoint } of sitemaps) {
					let pattern = `/sitemap-${safeString(pluginName)}.xml`;

					if (existingSitemaps.includes(pattern)) {
						pattern = `/sitemap-${safeString(pluginName)}-${existingSitemaps.length}.xml`;
					}

					injectRoute({
						entrypoint,
						pattern,
						prerender: false,
					});
				}
			},
			/* v8 ignore stop */
		},
	};
}
