/**
 * Shared preview iframe helpers (dashicons, theme fonts, slider runtime, etc.).
 */

import {
	absolutizeAssetUrl,
	expandStylesheetUrls,
} from '../shared/iconRegistry';
import {
	getConfiguredFontStylesheetHrefs,
	getConfiguredFonts as getThemeFonts,
} from '../shared/themeFonts';

export { syncConfiguredFontStylesheets } from '../shared/themeFonts';

/**
 * @return {Record<string, unknown>}
 */
function previewConfig() {
	if ( typeof window === 'undefined' ) {
		return {};
	}
	return (
		window.jocbmAdmin ||
		window.jocbmEditor ||
		window.jocbmFront ||
		{}
	);
}

/**
 * @return {string} Absolute URL to dashicons.min.css, or empty.
 */
export function getDashiconsCssUrl() {
	const cfg = previewConfig();
	return typeof cfg.dashiconsUrl === 'string' ? cfg.dashiconsUrl : '';
}

/**
 * @return {string} Link tag for dashicons, or empty.
 */
export function dashiconsStylesheetTag() {
	const url = getDashiconsCssUrl();
	if ( ! url ) {
		return '';
	}
	return `<link rel="stylesheet" href="${ url.replace( /"/g, '' ) }" />`;
}

/**
 * @return {string} Absolute URL to theme-agnostic.css, or empty.
 */
export function getThemeAgnosticCssUrl() {
	const cfg = previewConfig();
	if ( typeof cfg.themeAgnosticUrl === 'string' && cfg.themeAgnosticUrl ) {
		return cfg.themeAgnosticUrl;
	}
	const pluginUrl =
		typeof cfg.pluginUrl === 'string' ? cfg.pluginUrl.replace( /\/?$/, '/' ) : '';
	return pluginUrl ? `${ pluginUrl }assets/css/theme-agnostic.css` : '';
}

/**
 * @return {string} Link tag for theme-agnostic base styles, or empty.
 */
export function themeAgnosticStylesheetTag() {
	const url = getThemeAgnosticCssUrl();
	if ( ! url ) {
		return '';
	}
	return `<link rel="stylesheet" id="bm-theme-agnostic" href="${ url.replace( /"/g, '' ) }" />`;
}

/**
 * Frontend runtime URLs (BmSlider / Splide).
 *
 * @return {{ js: string, css: string }}
 */
export function getFrontendRuntimeUrls() {
	const cfg = previewConfig();
	return {
		js: typeof cfg.frontendJsUrl === 'string' ? cfg.frontendJsUrl : '',
		css: typeof cfg.frontendCssUrl === 'string' ? cfg.frontendCssUrl : '',
	};
}

/**
 * Stylesheet + script tags for BmSlider inside preview iframes.
 * URLs are plugin-local (`build/frontend.*`) from PHP localization — never a CDN.
 *
 * @return {string}
 */
export function frontendRuntimeTags() {
	const { js, css } = getFrontendRuntimeUrls();
	const parts = [];
	if ( css ) {
		parts.push(
			`<link rel="stylesheet" id="bm-frontend-css" href="${ escapeHref( css ) }" />`
		);
	}
	if ( js ) {
		parts.push(
			`<script id="bm-frontend-js" src="${ escapeHref( js ) }" defer></script>`
		);
	}
	return parts.join( '' );
}

/**
 * Ensure BmSlider is mounted under a document/root (preview remounts).
 *
 * @param {ParentNode|Document} [scope]
 */
export function remountPreviewSliders( scope ) {
	const root = scope || document;
	const win =
		( root && root.defaultView ) ||
		( typeof window !== 'undefined' ? window : null );
	if ( ! win ) {
		return;
	}
	const api = win.jocbmSlider;
	if ( api && typeof api.remount === 'function' ) {
		api.remount( root.body || root );
		return;
	}
	// Script may still be loading in an iframe — retry briefly.
	let tries = 0;
	const tick = () => {
		tries += 1;
		const delayed = win.jocbmSlider;
		if ( delayed && typeof delayed.remount === 'function' ) {
			delayed.remount( root.body || root );
			return;
		}
		if ( tries < 20 ) {
			win.setTimeout( tick, 50 );
		}
	};
	tick();
}

/**
 * Theme fonts from localized admin / editor config.
 *
 * @return {Array<{ family?: string, slug?: string, source?: string }>}
 */
export function getConfiguredFonts() {
	return getThemeFonts();
}

/**
 * Escape a URL for use in an HTML attribute.
 *
 * @param {string} url
 * @return {string}
 */
function escapeHref( url ) {
	return String( url || '' )
		.replace( /&/g, '&amp;' )
		.replace( /"/g, '&quot;' )
		.replace( /</g, '&lt;' )
		.replace( />/g, '&gt;' );
}

/**
 * Theme fonts from localized admin / editor config + always include Inter.
 *
 * @return {string}
 */
export function fontStylesheetTags() {
	return getConfiguredFontStylesheetHrefs()
		.map(
			( href ) =>
				`<link rel="stylesheet" href="${ escapeHref( href ) }" />`
		)
		.join( '' );
}

/**
 * Enabled icon libraries from localized config.
 *
 * @return {Array<{ id?: string, enabled?: boolean, stylesheetUrl?: string, classTemplate?: string, type?: string }>}
 */
export function getIconLibrariesConfig() {
	const raw = previewConfig().iconLibraries;
	const list = raw?.libraries || raw;
	return Array.isArray( list ) ? list : [];
}

/**
 * Link tags for icon library stylesheets used in preview HTML.
 * Includes enabled libraries that have a stylesheet URL when the preview markup
 * looks like it uses that library (class probe), or always when html is empty.
 *
 * @param {string} [html] Preview body HTML.
 * @return {string}
 */
export function iconStylesheetTags( html = '' ) {
	const hay = String( html || '' );
	const tags = [];
	const seen = new Set();

	getIconLibrariesConfig().forEach( ( lib ) => {
		if ( ! lib || ! lib.enabled || lib.id === 'dashicons' ) {
			return;
		}
		const href = absolutizeAssetUrl( String( lib.stylesheetUrl || '' ).trim() );
		if ( ! href ) {
			return;
		}

		if ( hay ) {
			const type = lib.type || 'font-class';
			let used = false;
			if ( type === 'svg-sprite' ) {
				used = hay.includes( 'bm-icon--svg' );
			} else if ( type === 'css-mask' ) {
				used = hay.includes( 'bm-icon--mask' );
			} else {
				const tpl = String( lib.classTemplate || '' );
				const first = tpl.split( /\s+/ ).find( Boolean ) || '';
				if ( first && ! first.includes( '{id}' ) ) {
					used = hay.includes( first );
				} else {
					const probe = first.replace( /\{id\}/g, '' ).replace( /-+$/g, '' );
					used = Boolean( probe && probe.length > 2 && hay.includes( probe ) );
				}
			}
			if ( ! used ) {
				return;
			}
		}

		expandStylesheetUrls( href ).forEach( ( sheet, i ) => {
			if ( seen.has( sheet ) ) {
				return;
			}
			seen.add( sheet );
			tags.push(
				`<link rel="stylesheet" id="bm-icon-lib-${ escapeHref(
					String( lib.id || 'lib' )
				) }${ i ? `-${ i }` : '' }" href="${ escapeHref( sheet ) }" />`
			);
		} );
	} );

	return tags.join( '' );
}
