/**
 * Theme font stylesheet helpers for admin parent + preview iframes.
 */

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

const FONT_LINK_ATTR = 'data-bm-theme-font';

/**
 * @param {Record<string, unknown>} [cfg]
 * @return {Array<{ family?: string, slug?: string, source?: string }>}
 */
export function getConfiguredFonts( cfg = null ) {
	const host = cfg || themeConfigHost();
	const fonts = host.themeConfig?.fonts ?? host.fonts;
	return Array.isArray( fonts ) ? fonts : [];
}

/**
 * Collect stylesheet URLs for Inter + configured theme fonts.
 *
 * @param {Array<{ source?: string }>|null} [fonts]
 * @param {Record<string, unknown>|null} [cfg]
 * @return {string[]}
 */
export function getConfiguredFontStylesheetHrefs( fonts = null, cfg = null ) {
	const host = cfg || themeConfigHost();
	const list = Array.isArray( fonts ) ? fonts : getConfiguredFonts( host );
	const hrefs = [];
	const seen = new Set();

	const push = ( href ) => {
		const url = String( href || '' ).trim();
		if ( ! url || seen.has( url ) ) {
			return;
		}
		seen.add( url );
		hrefs.push( url );
	};

	const interHref = String(
		host.interFontUrl ||
			( host.pluginUrl
				? String( host.pluginUrl ).replace( /\/?$/, '/' ) +
				  'assets/fonts/inter/inter.css'
				: '' )
	).trim();
	push( interHref );

	list.forEach( ( font ) => {
		const href = String( font?.source || '' ).trim();
		if ( ! href || ! /^https?:\/\//i.test( href ) ) {
			return;
		}
		if ( href.includes( 'assets/fonts/inter/inter.css' ) ) {
			return;
		}
		push( href );
	} );

	return hrefs;
}

/**
 * @param {ParentNode} root
 * @param {string} href
 * @return {Element|null}
 */
function findStylesheetByHref( root, href ) {
	return (
		Array.from( root.querySelectorAll( 'link[rel="stylesheet"]' ) ).find(
			( link ) => String( link.getAttribute( 'href' ) || '' ).trim() === href
		) || null
	);
}

/**
 * Keep parent-document `<link>` tags in sync with configured fonts so font
 * dropdown previews (portaled to document.body) can render each typeface
 * without a full page reload after Global Settings save.
 *
 * @param {Array<{ source?: string }>|null} [fonts]
 * @param {ParentNode|Document|null} [doc]
 */
export function syncConfiguredFontStylesheets( fonts = null, doc = null ) {
	const target =
		doc || ( typeof document !== 'undefined' ? document : null );
	if ( ! target?.head || typeof target.createElement !== 'function' ) {
		return;
	}

	const hrefs = getConfiguredFontStylesheetHrefs( fonts );
	const wanted = new Set( hrefs );

	Array.from(
		target.querySelectorAll( `link[${ FONT_LINK_ATTR }="1"]` )
	).forEach( ( link ) => {
		const href = String( link.getAttribute( 'href' ) || '' ).trim();
		if ( ! wanted.has( href ) ) {
			link.remove();
		}
	} );

	const present = new Set(
		Array.from(
			target.querySelectorAll( `link[${ FONT_LINK_ATTR }="1"]` )
		).map( ( link ) => String( link.getAttribute( 'href' ) || '' ).trim() )
	);

	hrefs.forEach( ( href ) => {
		if ( present.has( href ) ) {
			return;
		}
		const already = findStylesheetByHref( target, href );
		if ( already ) {
			already.setAttribute( FONT_LINK_ATTR, '1' );
			present.add( href );
			return;
		}
		const link = target.createElement( 'link' );
		link.rel = 'stylesheet';
		link.setAttribute( FONT_LINK_ATTR, '1' );
		link.href = href;
		target.head.appendChild( link );
		present.add( href );
	} );
}
