/**
 * Editor-only CSS for the List block's custom markers.
 *
 * Mirrors the frontend marker CSS in includes/render-helpers/list-css.php so the
 * editor preview matches the saved output. The generic main/hover CSS is produced
 * separately by generateBlockStyles()/generateBlockStylesHover().
 */

const DEVICE_ORDER = [ 'mobile', 'tablet', 'desktop' ];

const hasCssValue = ( value ) => {
	if ( typeof value === 'boolean' || value == null ) {
		return false;
	}
	if ( typeof value === 'string' ) {
		return value !== '';
	}
	if ( Array.isArray( value ) ) {
		return value.some( hasCssValue );
	}
	if ( typeof value === 'object' ) {
		return Object.values( value ).some( hasCssValue );
	}
	return false;
};

const backfillResponsiveAttributes = ( attributes = {} ) => {
	const next = { ...attributes };

	Object.entries( next ).forEach( ( [ key, value ] ) => {
		if (
			! value ||
			typeof value !== 'object' ||
			!( 'desktop' in value ) ||
			!( 'mobile' in value )
		) {
			return;
		}

		const hasDesktop = hasCssValue( value.desktop );
		const hasTablet = hasCssValue( value.tablet );
		const hasMobile = hasCssValue( value.mobile );

		if ( hasDesktop && ! hasMobile ) {
			next[ key ] = { ...value, mobile: value.desktop };
		}

		if ( hasTablet && ! hasDesktop ) {
			next[ key ] = {
				...next[ key ],
				desktop: value.tablet,
				...( hasMobile ? {} : { mobile: value.tablet } ),
			};
		}
	} );

	return next;
};

// Normalise a per-device iconSize value (legacy string or { width, height } object)
// into a single scalar suitable for use as font-size on custom list markers.
const iconSizeScalar = ( raw ) => {
	if ( typeof raw === 'string' ) return raw;
	if ( raw && typeof raw === 'object' ) {
		return ( typeof raw.width === 'string' && raw.width )
			|| ( typeof raw.height === 'string' && raw.height )
			|| '';
	}
	return '';
};

export function generateListEditorStyles( uniqueClass, devices, attributes ) {
	if ( ! uniqueClass ) {
		return '';
	}

	const normalizedAttributes = backfillResponsiveAttributes( attributes );

	const hasCustomMarker =
		typeof normalizedAttributes.iconSvg === 'string' &&
		normalizedAttributes.iconSvg.includes( '<svg' );

	const isOrdered = normalizedAttributes.tagName === 'ol';

	const itemGap = normalizedAttributes.itemGap || {};
	const iconGap = normalizedAttributes.iconGap || {};
	const iconSize = normalizedAttributes.iconSize || {};
	const iconColor = normalizedAttributes.iconColor || '';

	const markerTextColor = normalizedAttributes.markerTextColor || {};
	const markerBackgroundColor = normalizedAttributes.markerBackgroundColor || {};
	const markerFontSize = normalizedAttributes.markerFontSize || {};
	const markerFontWeight = normalizedAttributes.markerFontWeight || {};
	const markerBorderWidth = normalizedAttributes.markerBorderWidth || {};
	const markerBorderStyle = normalizedAttributes.markerBorderStyle || {};
	const markerBorderColor = normalizedAttributes.markerBorderColor || {};
	const markerBorderRadius = normalizedAttributes.markerBorderRadius || {};
	const markerWidth = normalizedAttributes.markerWidth || {};
	const markerHeight = normalizedAttributes.markerHeight || {};
	const markerPadding = normalizedAttributes.markerPadding || {};

	const baseSelector = `.${ uniqueClass }`;
	const itemSelector = `${ baseSelector } > .axcelersblocks-list-item`;
	const markerSelector = `${ itemSelector } > .axcelersblocks-list-item__marker`;

	const listStyleType = normalizedAttributes.listStyleType || '';
	const start = parseInt( normalizedAttributes.start || 1, 10 );
	const counterStart = start > 1 ? start - 1 : 0;
	let previousIconSize = '';

	return DEVICE_ORDER
		.filter( ( device ) => devices?.[ device ] )
		.map( ( device ) => {
			const rules = [];
			const isDesktop = device === 'desktop';
			// Structural marker rules (flex layout, list-style reset, counters) emit on
			// the base device (no media query) so they apply at every breakpoint.
			const isMobile = device === 'mobile';
			const currentIconSize = iconSizeScalar( iconSize[ device ] );

			if ( isMobile && listStyleType ) {
				rules.push( `${ baseSelector } { list-style-type: ${ listStyleType }; }` );
			}

			if ( itemGap[ device ] ) {
				rules.push(
					`${ itemSelector } + .axcelersblocks-list-item { margin-top: ${ itemGap[ device ] }; }`
				);
			}

			if ( hasCustomMarker || isOrdered ) {
				if ( isMobile ) {
					// Lay the marker inline with the content: the <li> becomes a flex row
					// so the icon/number sits beside the text instead of stacking above
					// the block-level __content. baseline aligns it with the first text line.
					rules.push(
					`${ baseSelector } > .axcelersblocks-list-item { list-style: none; display: flex; align-items: baseline; }`
					);
					rules.push(
					`${ itemSelector } > .axcelersblocks-list-item__content { flex: 1 1 auto; min-width: 0; }`
					);
				}

				if ( isOrdered && isMobile ) {
					rules.push(
						`${ baseSelector } { counter-reset: axb-list-counter ${ counterStart }; }`
					);
					rules.push(
						`${ itemSelector } { counter-increment: axb-list-counter; }`
					);
					rules.push(
						`${ markerSelector }::before { content: counter(axb-list-counter); }`
					);
				}

				// Structural marker box layout emits on the base device (all breakpoints).
				const markerRules = isMobile
					? [
						'display: inline-flex',
						'align-items: center',
						'justify-content: center',
						'vertical-align: middle',
						'line-height: 1',
						'flex: 0 0 auto',
					]
					: [];

				if ( iconGap[ device ] ) {
					markerRules.push( `margin-right: ${ iconGap[ device ] }` );
				}

				if (
					hasCustomMarker &&
					currentIconSize &&
					( isDesktop || currentIconSize !== previousIconSize )
				) {
					markerRules.push( `font-size: ${ currentIconSize }` );
				}

				if ( hasCustomMarker && iconColor ) {
				if ( isDesktop ) {
					markerRules.push( `color: ${ iconColor }` );
				}
				}

				if ( markerTextColor[ device ] ) {
					markerRules.push( `color: ${ markerTextColor[ device ] }` );
				}

				if ( markerBackgroundColor[ device ] ) {
					markerRules.push( `background: ${ markerBackgroundColor[ device ] }` );
				}

				if ( markerFontSize[ device ] ) {
					markerRules.push( `font-size: ${ markerFontSize[ device ] }` );
				}

				if ( markerFontWeight[ device ] ) {
					markerRules.push( `font-weight: ${ markerFontWeight[ device ] }` );
				}

				if ( markerBorderWidth[ device ] ) {
					markerRules.push( `border-width: ${ markerBorderWidth[ device ] }` );
				}

				if ( markerBorderStyle[ device ] ) {
					markerRules.push( `border-style: ${ markerBorderStyle[ device ] }` );
				}

				if ( markerBorderColor[ device ] ) {
					markerRules.push( `border-color: ${ markerBorderColor[ device ] }` );
				}

				if ( markerBorderRadius[ device ] ) {
					markerRules.push( `border-radius: ${ markerBorderRadius[ device ] }` );
				}

				if ( markerWidth[ device ] ) {
					markerRules.push( `width: ${ markerWidth[ device ] }` );
					markerRules.push( `min-width: ${ markerWidth[ device ] }` );
				}

				if ( markerHeight[ device ] ) {
					markerRules.push( `height: ${ markerHeight[ device ] }` );
				}

				if ( markerPadding[ device ] ) {
					markerRules.push( `padding: ${ markerPadding[ device ] }` );
				}

				if ( markerRules.length ) {
					rules.push(
						`${ markerSelector } { ${ markerRules.join( '; ' ) }; }`
					);
				}

				if ( isMobile ) {
					rules.push(
					`${ markerSelector } svg, ${ markerSelector } img { display: block; width: 1em; height: 1em; }`
					);

					rules.push(
					`${ markerSelector } svg { fill: currentColor; }`
					);
				}
			}

			// Native marker (::marker) — disc / decimal bullets can only be styled
			// via ::marker, which supports colour + font only (not background, border,
			// width, height, padding — those need a custom marker icon). Emitted
			// ungated so the Marker controls also preview on plain native lists.
			const pseudoRules = [];
			if ( markerTextColor[ device ] ) {
				pseudoRules.push( `color: ${ markerTextColor[ device ] }` );
			}
			if ( markerFontSize[ device ] ) {
				pseudoRules.push( `font-size: ${ markerFontSize[ device ] }` );
			}
			if ( markerFontWeight[ device ] ) {
				pseudoRules.push( `font-weight: ${ markerFontWeight[ device ] }` );
			}
			if ( pseudoRules.length ) {
				rules.push( `${ itemSelector }::marker { ${ pseudoRules.join( '; ' ) }; }` );
			}

			if ( currentIconSize ) {
				previousIconSize = currentIconSize;
			}

			if ( ! rules.length ) {
				return '';
			}

			return devices[ device ]?.media
				? `${ devices[ device ].media } { ${ rules.join( ' ' ) } }`
				: rules.join( ' ' );
		} )
		.join( ' ' );
}
