<?php
/**
 * CSS generator for the List block's custom markers and marker icon.
 *
 * The list targets several elements the shared generator cannot express:
 *   - <ul|ol class="uniqueClass">                       — main/hover, handled by
 *                                                          axcelersblocks_generate_block_styles()
 *   - .uniqueClass > .axcelersblocks-list-item          — item spacing / list-style reset
 *   - … > .axcelersblocks-list-item__marker (a.k.a. .icon) — marker chrome + icon styling
 *
 * The marker element carries both `axcelersblocks-list-item__marker` and `icon`
 * classes, so its appearance is driven by the marker* attributes (background,
 * border, size, …) and the icon* attributes (position, inset, overflow, effect).
 *
 * @package AxcelersBlocks
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

if ( ! function_exists( 'axcelersblocks_list_generate_marker_css' ) ) {
	/**
	 * Generate the list-specific marker and icon CSS rules.
	 *
	 * @param string $unique_class Block-scoped unique class.
	 * @param array  $devices      Device map from axcelersblocks_get_responsive_devices().
	 * @param array  $attributes   Full block attributes.
	 * @return string[] CSS rule strings (with media queries where needed).
	 */
	function axcelersblocks_list_generate_marker_css( string $unique_class, array $devices, array $attributes ): array {
		// Backward-compat: fill empty mobile values from desktop for min-width output.
		$has_css_v = function ( $v ) use ( &$has_css_v ) {
			if ( is_bool( $v ) || is_null( $v ) ) { return false; }
			if ( is_string( $v ) ) { return $v !== ''; }
			if ( is_array( $v ) ) { foreach ( $v as $__i ) { if ( $has_css_v( $__i ) ) { return true; } } }
			return false;
		};
		foreach ( $attributes as &$__av ) {
			if ( ! is_array( $__av ) ) { continue; }
			$__has_d = isset( $__av['desktop'] ) && $has_css_v( $__av['desktop'] );
			$__has_t = isset( $__av['tablet'] )  && $has_css_v( $__av['tablet'] );
			$__has_m = isset( $__av['mobile'] )  && $has_css_v( $__av['mobile'] );
			if ( $__has_d && ! $__has_m ) {
				$__av['mobile'] = $__av['desktop'];
			}
			if ( $__has_t && ! $__has_d ) {
				$__av['desktop'] = $__av['tablet'];
				if ( ! $__has_m ) {
					$__av['mobile'] = $__av['tablet'];
				}
			}
		}
		unset( $__av );

		$rules = [];

		// Append one rule (selector + declarations) for the given device, wrapping
		// it in the device's media query when one exists.
		$add = function ( $device, $selector, $declarations ) use ( &$rules, $devices ) {
			if ( empty( $selector ) || empty( $declarations ) || ! is_array( $declarations ) ) {
				return;
			}
			$css = $selector . ' { ' . implode( ' ', $declarations ) . ' }';
			$rules[] = ! empty( $devices[ $device ]['media'] )
				? $devices[ $device ]['media'] . ' { ' . $css . ' }'
				: $css;
		};

		// Normalise an iconSize value that may be a legacy string (both sides equal)
		// or an object { width, height }, returning a single scalar.
		$icon_size_scalar = static function ( $raw ) {
			if ( is_string( $raw ) ) {
				return axcelersblocks_sanitize_css_value( $raw );
			}
			if ( is_array( $raw ) ) {
				$w = isset( $raw['width'] )  && is_string( $raw['width'] )  ? $raw['width']  : '';
				$h = isset( $raw['height'] ) && is_string( $raw['height'] ) ? $raw['height'] : '';
				return axcelersblocks_sanitize_css_value( '' !== $w ? $w : $h );
			}
			return '';
		};

		$tag_name          = $attributes['tagName'] ?? 'ul';
		$is_ordered        = 'ol' === $tag_name;
		$has_custom_marker = ! empty( $attributes['iconSvg'] ) && is_string( $attributes['iconSvg'] ) && false !== strpos( $attributes['iconSvg'], '<svg' );

		$base_selector   = '.' . $unique_class;
		$item_selector   = $base_selector . ' > .axcelersblocks-list-item';
		$marker_selector = $item_selector . ' > .axcelersblocks-list-item__marker';

		$item_gap                = $attributes['itemGap'] ?? [];
		$icon_gap                = $attributes['iconGap'] ?? [];
		$icon_size               = $attributes['iconSize'] ?? [];
		$icon_color              = axcelersblocks_sanitize_css_value( $attributes['iconColor'] ?? '' );
		$marker_text_color       = $attributes['markerTextColor'] ?? [];
		$marker_background_color = $attributes['markerBackgroundColor'] ?? [];
		$marker_font_size        = $attributes['markerFontSize'] ?? [];
		$marker_font_weight      = $attributes['markerFontWeight'] ?? [];
		$marker_border_width     = $attributes['markerBorderWidth'] ?? [];
		$marker_border_style     = $attributes['markerBorderStyle'] ?? [];
		$marker_border_color     = $attributes['markerBorderColor'] ?? [];
		$marker_border_radius    = $attributes['markerBorderRadius'] ?? [];
		$marker_width            = $attributes['markerWidth'] ?? [];
		$marker_height           = $attributes['markerHeight'] ?? [];
		$marker_padding          = $attributes['markerPadding'] ?? [];
		$start                   = isset( $attributes['start'] ) ? absint( $attributes['start'] ) : 1;
		$counter_start           = $start > 1 ? $start - 1 : 0;

		// ─── Marker base + ordered-list counters (base, no media query) ───────────
		// These are STRUCTURAL — they must apply at every breakpoint, so they're
		// emitted on the base ('mobile') device with no media query. (Emitting on
		// 'desktop' would gate them behind min-width:1025px and break smaller screens.)
		if ( $has_custom_marker || $is_ordered ) {
			// 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 the marker with the first text
			// line (mirrors a native ::marker).
			$add( 'mobile', $item_selector, [ 'list-style: none;', 'display: flex;', 'align-items: baseline;' ] );
			// The content takes the remaining width and can shrink/wrap beside the marker.
			$add( 'mobile', $item_selector . ' > .axcelersblocks-list-item__content', [ 'flex: 1 1 auto;', 'min-width: 0;' ] );

			if ( $is_ordered ) {
				$add( 'mobile', $base_selector, [ 'counter-reset: axb-list-counter ' . $counter_start . ';' ] );
				$add( 'mobile', $item_selector, [ 'counter-increment: axb-list-counter;' ] );
				$add( 'mobile', $marker_selector . '::before', [ 'content: counter(axb-list-counter);' ] );
			}

			$base_marker_declarations = [
				'display: inline-flex;',
				'align-items: center;',
				'justify-content: center;',
				'vertical-align: middle;',
				'line-height: 1;',
				'flex: 0 0 auto;',
			];
			if ( $has_custom_marker && '' !== $icon_color ) {
				$base_marker_declarations[] = 'color: ' . $icon_color . ';';
			}
			$add( 'mobile', $marker_selector, $base_marker_declarations );

			if ( $has_custom_marker ) {
				$add(
					'mobile',
					$marker_selector . ' svg, ' . $marker_selector . ' img',
					[ 'display: block;', 'width: 1em;', 'height: 1em;' ]
				);
				$add( 'mobile', $marker_selector . ' svg', [ 'fill: currentColor;' ] );
			}
		}

		// ─── Per-device item spacing + marker styling ─────────────────────────────
		$previous_item_gap  = '';
		$previous_icon_gap  = '';
		$previous_icon_size = '';

		foreach ( $devices as $device => $config ) {
			$current_item_gap  = axcelersblocks_sanitize_css_value( $item_gap[ $device ] ?? '' );
			$current_icon_gap  = axcelersblocks_sanitize_css_value( $icon_gap[ $device ] ?? '' );
			$current_icon_size = axcelersblocks_sanitize_css_value( $icon_size[ $device ] ?? '' );

			if ( '' !== $current_item_gap && ( 'desktop' === $device || $current_item_gap !== $previous_item_gap ) ) {
				$add( $device, $item_selector . ' + .axcelersblocks-list-item', [ 'margin-top: ' . $current_item_gap . ';' ] );
			}
			if ( '' !== $current_item_gap ) {
				$previous_item_gap = $current_item_gap;
			}

			if ( $has_custom_marker || $is_ordered ) {
				$marker_declarations = [];

				if ( '' !== $current_icon_gap && ( 'desktop' === $device || $current_icon_gap !== $previous_icon_gap ) ) {
					$marker_declarations[] = 'margin-right: ' . $current_icon_gap . ';';
				}
				if ( $has_custom_marker && '' !== $current_icon_size && ( 'desktop' === $device || $current_icon_size !== $previous_icon_size ) ) {
					$marker_declarations[] = 'font-size: ' . $current_icon_size . ';';
				}
				if ( '' !== ( $marker_text_color[ $device ] ?? '' ) ) {
					$marker_declarations[] = 'color: ' . axcelersblocks_sanitize_css_value( $marker_text_color[ $device ] ) . ';';
				}
				if ( '' !== ( $marker_background_color[ $device ] ?? '' ) ) {
					$marker_declarations[] = 'background: ' . axcelersblocks_sanitize_css_value( $marker_background_color[ $device ] ) . ';';
				}
				if ( '' !== ( $marker_font_size[ $device ] ?? '' ) ) {
					$marker_declarations[] = 'font-size: ' . axcelersblocks_sanitize_css_value( $marker_font_size[ $device ] ) . ';';
				}
				if ( '' !== ( $marker_font_weight[ $device ] ?? '' ) ) {
					$marker_declarations[] = 'font-weight: ' . axcelersblocks_sanitize_css_value( $marker_font_weight[ $device ] ) . ';';
				}
				if ( '' !== ( $marker_border_width[ $device ] ?? '' ) ) {
					$marker_declarations[] = 'border-width: ' . axcelersblocks_sanitize_css_value( $marker_border_width[ $device ] ) . ';';
				}
				if ( '' !== ( $marker_border_style[ $device ] ?? '' ) ) {
					$marker_declarations[] = 'border-style: ' . axcelersblocks_sanitize_css_value( $marker_border_style[ $device ] ) . ';';
				}
				if ( '' !== ( $marker_border_color[ $device ] ?? '' ) ) {
					$marker_declarations[] = 'border-color: ' . axcelersblocks_sanitize_css_value( $marker_border_color[ $device ] ) . ';';
				}
				if ( '' !== ( $marker_border_radius[ $device ] ?? '' ) ) {
					$marker_declarations[] = 'border-radius: ' . axcelersblocks_sanitize_css_value( $marker_border_radius[ $device ] ) . ';';
				}
				if ( '' !== ( $marker_width[ $device ] ?? '' ) ) {
					$width = axcelersblocks_sanitize_css_value( $marker_width[ $device ] );
					$marker_declarations[] = 'width: ' . $width . ';';
					$marker_declarations[] = 'min-width: ' . $width . ';';
				}
				if ( '' !== ( $marker_height[ $device ] ?? '' ) ) {
					$marker_declarations[] = 'height: ' . axcelersblocks_sanitize_css_value( $marker_height[ $device ] ) . ';';
				}
				if ( '' !== ( $marker_padding[ $device ] ?? '' ) ) {
					$marker_declarations[] = 'padding: ' . axcelersblocks_sanitize_css_value( $marker_padding[ $device ] ) . ';';
				}

				if ( ! empty( $marker_declarations ) ) {
					$add( $device, $marker_selector, $marker_declarations );
				}

				if ( '' !== $current_icon_gap ) {
					$previous_icon_gap = $current_icon_gap;
				}
				if ( '' !== $current_icon_size ) {
					$previous_icon_size = $current_icon_size;
				}
			}
		}

		// ─── Native marker (::marker) — disc / decimal / etc. ─────────────────────
		// The browser's native bullet/number can only be styled via ::marker, which
		// supports a limited set (colour + font properties — NOT background, border,
		// width, height or padding; those require a custom marker element). Emit the
		// supported subset so the Marker controls also affect plain native lists.
		// Harmless for custom/ordered markers (those set list-style:none, hiding ::marker).
		$marker_pseudo = $item_selector . '::marker';
		$prev_pseudo   = [];
		foreach ( $devices as $device => $config ) {
			$pseudo_declarations = [];

			$mtc = axcelersblocks_sanitize_css_value( $marker_text_color[ $device ] ?? '' );
			if ( '' !== $mtc && ( 'mobile' === $device || ( $prev_pseudo['color'] ?? '' ) !== $mtc ) ) {
				$pseudo_declarations[] = 'color: ' . $mtc . ';';
				$prev_pseudo['color']  = $mtc;
			}

			$mfs = axcelersblocks_sanitize_css_value( $marker_font_size[ $device ] ?? '' );
			if ( '' !== $mfs && ( 'mobile' === $device || ( $prev_pseudo['font-size'] ?? '' ) !== $mfs ) ) {
				$pseudo_declarations[]    = 'font-size: ' . $mfs . ';';
				$prev_pseudo['font-size'] = $mfs;
			}

			$mfw = axcelersblocks_sanitize_css_value( $marker_font_weight[ $device ] ?? '' );
			if ( '' !== $mfw && ( 'mobile' === $device || ( $prev_pseudo['font-weight'] ?? '' ) !== $mfw ) ) {
				$pseudo_declarations[]      = 'font-weight: ' . $mfw . ';';
				$prev_pseudo['font-weight'] = $mfw;
			}

			if ( ! empty( $pseudo_declarations ) ) {
				$add( $device, $marker_pseudo, $pseudo_declarations );
			}
		}

		// ─── Marker icon (.icon) position / overflow / effect, normal + hover ─────
		$icon_effect_to_css = static function ( $effect, $property ) {
			if ( ! is_array( $effect ) ) {
				return null;
			}
			$value_or_default = static function ( $value, $fallback ) {
				return ( isset( $value ) && '' !== $value ) ? $value : $fallback;
			};
			switch ( $property ) {
				case 'box-shadow':
					$shadow = $effect['boxShadow'] ?? null;
					if ( ! is_array( $shadow ) ) { return null; }
					$x      = $value_or_default( $shadow['xOffset'] ?? null, '0px' );
					$y      = $value_or_default( $shadow['yOffset'] ?? null, '0px' );
					$blur   = $value_or_default( $shadow['blurRadius'] ?? null, '0px' );
					$spread = $value_or_default( $shadow['spreadRadius'] ?? null, '0px' );
					$color  = $value_or_default( $shadow['color'] ?? null, 'transparent' );
					$inset  = ! empty( $shadow['inset'] ) ? 'inset ' : '';
					if ( '0px' === $x && '0px' === $y && '0px' === $blur && '0px' === $spread && 'transparent' === $color && '' === $inset ) {
						return null;
					}
					return $inset . $x . ' ' . $y . ' ' . $blur . ' ' . $spread . ' ' . $color;

				case 'transition':
					$transition = $effect['transition'] ?? null;
					if ( ! is_array( $transition ) ) { return null; }
					$prop   = $value_or_default( $transition['property'] ?? null, 'all' );
					$dur    = $value_or_default( $transition['duration'] ?? null, '0s' );
					$timing = $value_or_default( $transition['timingFunction'] ?? null, 'ease' );
					$delay  = $value_or_default( $transition['delay'] ?? null, '0s' );
					if ( 'all' === $prop && '0s' === $dur && 'ease' === $timing && '0s' === $delay ) {
						return null;
					}
					return $prop . ' ' . $dur . ' ' . $timing . ' ' . $delay;

				case 'filter':
					$filter = $effect['filter'] ?? null;
					if ( ! is_array( $filter ) ) { return null; }
					$filters = [];
					if ( ! empty( $filter['blur'] ) ) { $filters[] = 'blur(' . $filter['blur'] . ')'; }
					if ( ! empty( $filter['brightness'] ) && '100%' !== $filter['brightness'] ) { $filters[] = 'brightness(' . $filter['brightness'] . ')'; }
					if ( ! empty( $filter['contrast'] ) && '100%' !== $filter['contrast'] ) { $filters[] = 'contrast(' . $filter['contrast'] . ')'; }
					if ( ! empty( $filter['grayscale'] ) && '0%' !== $filter['grayscale'] ) { $filters[] = 'grayscale(' . $filter['grayscale'] . ')'; }
					if ( ! empty( $filter['hueRotate'] ) && '0deg' !== $filter['hueRotate'] ) { $filters[] = 'hue-rotate(' . $filter['hueRotate'] . ')'; }
					if ( ! empty( $filter['invert'] ) && '0%' !== $filter['invert'] ) { $filters[] = 'invert(' . $filter['invert'] . ')'; }
					if ( ! empty( $filter['opacity'] ) && '100%' !== $filter['opacity'] ) { $filters[] = 'opacity(' . $filter['opacity'] . ')'; }
					if ( ! empty( $filter['saturate'] ) && '100%' !== $filter['saturate'] ) { $filters[] = 'saturate(' . $filter['saturate'] . ')'; }
					if ( ! empty( $filter['sepia'] ) && '0%' !== $filter['sepia'] ) { $filters[] = 'sepia(' . $filter['sepia'] . ')'; }
					return ! empty( $filters ) ? implode( ' ', $filters ) : null;

				case 'text-shadow':
					$text_shadow = $effect['textShadow'] ?? null;
					if ( ! is_array( $text_shadow ) ) { return null; }
					$x     = $value_or_default( $text_shadow['xOffset'] ?? null, '0px' );
					$y     = $value_or_default( $text_shadow['yOffset'] ?? null, '0px' );
					$blur  = $value_or_default( $text_shadow['blurRadius'] ?? null, '0px' );
					$color = $value_or_default( $text_shadow['color'] ?? null, 'transparent' );
					if ( '0px' === $x && '0px' === $y && '0px' === $blur && 'transparent' === $color ) {
						return null;
					}
					return $x . ' ' . $y . ' ' . $blur . ' ' . $color;

				case 'transform':
					return axcelersblocks_build_transform_style( $effect['transform'] ?? null );

				case 'opacity':
					return isset( $effect['opacity'] ) && '' !== $effect['opacity'] && '1' !== $effect['opacity'] ? $effect['opacity'] : null;

				case 'visibility':
					return ! empty( $effect['visibility'] ) && 'visible' !== $effect['visibility'] ? $effect['visibility'] : null;
			}
			return null;
		};

		$icon_selector       = $base_selector . ' .icon';
		$icon_hover_selector = $base_selector . ':hover .icon';
		$previous_list_icon_size       = '';
		$previous_list_icon_base_size  = '';
		$previous_list_icon_hover_size = '';

		foreach ( $devices as $device => $config ) {
			$icon_declarations = [];
			$current_icon_size = $icon_size_scalar( $attributes['iconSize'][ $device ] ?? '' );

			if ( $has_custom_marker && '' !== $current_icon_size && ( 'desktop' === $device || $current_icon_size !== $previous_list_icon_size ) ) {
				$icon_declarations[] = 'font-size: ' . $current_icon_size . ';';
			}
			if ( '' !== $current_icon_size ) {
				$previous_list_icon_size = $current_icon_size;
			}

			$icon_position = axcelersblocks_sanitize_css_value( $attributes['iconPosition'][ $device ] ?? '' );
			if ( '' !== $icon_position ) {
				$icon_declarations[] = 'position: ' . $icon_position . ';';
			}

			$icon_inset = $attributes['iconInset'][ $device ] ?? [];
			foreach ( [ 'top', 'right', 'bottom', 'left' ] as $edge ) {
				$edge_value = axcelersblocks_sanitize_css_value( $icon_inset[ $edge ] ?? '' );
				if ( '' !== $edge_value ) {
					$icon_declarations[] = $edge . ': ' . $edge_value . ';';
				}
			}

			$overflow_x = axcelersblocks_sanitize_css_value( $attributes['iconOverflowX'][ $device ] ?? '' );
			if ( '' !== $overflow_x ) {
				$icon_declarations[] = 'overflow-x: ' . $overflow_x . ';';
			}
			$overflow_y = axcelersblocks_sanitize_css_value( $attributes['iconOverflowY'][ $device ] ?? '' );
			if ( '' !== $overflow_y ) {
				$icon_declarations[] = 'overflow-y: ' . $overflow_y . ';';
			}
			$z_index = axcelersblocks_sanitize_css_value( $attributes['iconZIndex'][ $device ] ?? '' );
			if ( '' !== $z_index ) {
				$icon_declarations[] = 'z-index: ' . $z_index . ';';
			}

			foreach ( [ 'box-shadow', 'transition', 'filter', 'text-shadow', 'transform', 'opacity', 'visibility' ] as $property ) {
				$css_value = $icon_effect_to_css( $attributes['iconEffect'][ $device ] ?? null, $property );
				if ( null !== $css_value && '' !== $css_value ) {
					$icon_declarations[] = $property . ': ' . axcelersblocks_sanitize_css_value( $css_value ) . ';';
				}
			}

			if ( ! empty( $icon_declarations ) ) {
				$add( $device, $icon_selector, $icon_declarations );
			}

			$icon_hover_declarations = [];
			$icon_size_hover         = $icon_size_scalar( $attributes['iconSize__hover'][ $device ] ?? '' );
			$icon_base_size          = '' !== $current_icon_size ? $current_icon_size : $previous_list_icon_base_size;

			if ( '' !== $icon_base_size ) {
				$previous_list_icon_base_size = $icon_base_size;
			}

			if ( $has_custom_marker && '' !== $icon_size_hover && $icon_size_hover !== $icon_base_size && ( 'desktop' === $device || $icon_size_hover !== $previous_list_icon_hover_size ) ) {
				$icon_hover_declarations[] = 'font-size: ' . $icon_size_hover . ';';
			}
			if ( '' !== $icon_size_hover ) {
				$previous_list_icon_hover_size = $icon_size_hover;
			}

			$icon_hover_position = axcelersblocks_sanitize_css_value( $attributes['iconPosition__hover'][ $device ] ?? '' );
			if ( '' !== $icon_hover_position ) {
				$icon_hover_declarations[] = 'position: ' . $icon_hover_position . ';';
			}

			$icon_hover_inset = $attributes['iconInset__hover'][ $device ] ?? [];
			foreach ( [ 'top', 'right', 'bottom', 'left' ] as $edge ) {
				$edge_value = axcelersblocks_sanitize_css_value( $icon_hover_inset[ $edge ] ?? '' );
				if ( '' !== $edge_value ) {
					$icon_hover_declarations[] = $edge . ': ' . $edge_value . ';';
				}
			}

			$overflow_x_hover = axcelersblocks_sanitize_css_value( $attributes['iconOverflowX__hover'][ $device ] ?? '' );
			if ( '' !== $overflow_x_hover ) {
				$icon_hover_declarations[] = 'overflow-x: ' . $overflow_x_hover . ';';
			}
			$overflow_y_hover = axcelersblocks_sanitize_css_value( $attributes['iconOverflowY__hover'][ $device ] ?? '' );
			if ( '' !== $overflow_y_hover ) {
				$icon_hover_declarations[] = 'overflow-y: ' . $overflow_y_hover . ';';
			}
			$z_index_hover = axcelersblocks_sanitize_css_value( $attributes['iconZIndex__hover'][ $device ] ?? '' );
			if ( '' !== $z_index_hover ) {
				$icon_hover_declarations[] = 'z-index: ' . $z_index_hover . ';';
			}

			foreach ( [ 'box-shadow', 'transition', 'filter', 'text-shadow', 'transform', 'opacity', 'visibility' ] as $property ) {
				$css_value = $icon_effect_to_css( $attributes['iconEffect__hover'][ $device ] ?? null, $property );
				if ( null !== $css_value && '' !== $css_value ) {
					$icon_hover_declarations[] = $property . ': ' . axcelersblocks_sanitize_css_value( $css_value ) . ';';
				}
			}

			if ( ! empty( $icon_hover_declarations ) ) {
				$add( $device, $icon_hover_selector, $icon_hover_declarations );
			}
		}

		if ( ! empty( $attributes['iconColor__hover'] ) ) {
			$hover_color = axcelersblocks_sanitize_css_value( $attributes['iconColor__hover'] );
			if ( '' !== $hover_color ) {
				$rules[] = $icon_hover_selector . ' { color: ' . $hover_color . '; }';
				$rules[] = $icon_hover_selector . ' svg { fill: currentColor; }';
			}
		}

		return $rules;
	}
}
