<?php
/**
 * Features widget render layer.
 *
 * Shortcode: [rsmspark_features]
 * Attributes:
 *   config — full JSON widget instance (general, layout, design, popouts sections)
 *   title, columns, features — simplified mode (features = JSON chip array)
 *
 * @package Rsmspark_Content_Widgets
 */

defined( 'ABSPATH' ) || exit;

/**
 * Rsmspark_Content_Widgets_Widget_Features
 *
 * Refactored in compat branch - Phase 1
 */
class Rsmspark_Content_Widgets_Widget_Features {

	const REGISTRY_ID = 'features';

	/**
	 * @return void
	 */
	public static function register() {
		self::ensure_dependencies();

		require_once RSMSPARK_CONTENT_WIDGETS_PATH . 'includes/class-rsmspark-content-widgets-features-config.php';
		require_once RSMSPARK_CONTENT_WIDGETS_PATH . 'includes/class-rsmspark-content-widgets-features-json.php';
		Rsmspark_Content_Widgets_Features_Json::init();

		Rsmspark_Content_Widgets_Shortcodes::add(
			Rsmspark_Content_Widgets_Registry::shortcode_tag( self::REGISTRY_ID ),
			array( __CLASS__, 'shortcode' ),
			self::REGISTRY_ID
		);

		Rsmspark_Content_Widgets_Blocks::add(
			'features',
			array(
				'api_version'     => 3,
				'title'           => __( 'RSM Features', 'rsm-content-widgets' ),
				'description'     => __( 'Feature chip cards with icons and optional popouts.', 'rsm-content-widgets' ),
				'category'        => Rsmspark_Content_Widgets_Blocks::BLOCK_CATEGORY,
				'icon'            => 'star-filled',
				'keywords'        => array( 'features', 'chips', 'cards', 'rsm' ),
				'supports'        => array( 'html' => false ),
				'attributes'      => self::block_attributes(),
				'render_callback' => array( __CLASS__, 'render_block' ),
			)
		);
	}

	/**
	 * @return array<string, array<string, mixed>>
	 */
	public static function block_attributes() {
		$design_default = Rsmspark_Content_Widgets_Features_Config::demo_instance()['design'];

		return array(
			'title'          => array(
				'type'    => 'string',
				'default' => __( 'Features', 'rsm-content-widgets' ),
			),
			'columns'        => array( 'type' => 'number', 'default' => 3 ),
			'chip_layout'    => array( 'type' => 'string', 'default' => 'stacked' ),
			'icon_align'     => array( 'type' => 'string', 'default' => 'center' ),
			'design'         => array(
				'type'    => 'object',
				'default' => $design_default,
			),
			'enable_popouts' => array( 'type' => 'boolean', 'default' => false ),
			'popout_items'   => array(
				'type'    => 'array',
				'default' => array(),
				'items'   => array(
					'type' => 'object',
				),
			),
			'features'       => array(
				'type'    => 'array',
				'default' => self::default_feature_chips(),
				'items'   => array(
					'type' => 'object',
				),
			),
		);
	}

	/**
	 * @param array<string, mixed> $atts Shortcode attributes.
	 * @param string               $content Inner content (unused).
	 * @return string
	 */
	public static function shortcode( $atts, $content = '' ) {
		unset( $content );
		$atts = is_array( $atts ) ? $atts : array();
		return self::render( self::normalize_atts( $atts ) );
	}

	/**
	 * @param array<string, mixed> $attributes Block attributes.
	 * @return string
	 */
	public static function render_block( $attributes, $content = '', $block = null ) {
		unset( $content );
		$attributes = self::merge_block_attributes( $attributes, $block );
		return self::render( self::normalize_atts( $attributes ) );
	}

	/**
	 * Merge attributes from WP_Block (parsed block JSON is authoritative).
	 *
	 * @param mixed         $attributes Render callback attributes.
	 * @param WP_Block|null $block      Block instance.
	 * @return array<string, mixed>
	 */
	public static function merge_block_attributes( $attributes, $block = null ) {
		$merged = is_array( $attributes ) ? $attributes : array();

		if ( $block instanceof WP_Block ) {
			if ( ! empty( $block->parsed_block['attrs'] ) && is_array( $block->parsed_block['attrs'] ) ) {
				$merged = array_merge( $merged, $block->parsed_block['attrs'] );
			}
			if ( ! empty( $block->attributes ) && is_array( $block->attributes ) ) {
				$merged = array_merge( $merged, $block->attributes );
			}
		}

		return $merged;
	}

	/**
	 * @param array<string, mixed> $atts Raw attributes.
	 * @return array<string, mixed>
	 */
	public static function normalize_atts( array $atts ) {
		self::ensure_dependencies();

		if ( ! empty( $atts['config'] ) ) {
			$config = $atts['config'];
			if ( is_string( $config ) ) {
				$instance = Rsmspark_Content_Widgets_Render::parse_json_attr( $config, array() );
			} elseif ( is_array( $config ) ) {
				$instance = $config;
			} else {
				$instance = array();
			}
		} else {
			$instance = self::build_instance_from_simple_atts( $atts );
		}

		return self::prepare_template_vars( $instance, array() );
	}

	/**
	 * @param array<string, mixed> $atts Simple shortcode attributes.
	 * @return array<string, mixed>
	 */
	public static function build_instance_from_simple_atts( array $atts ) {
		$defaults = array(
			'title'            => __( 'Features', 'rsm-content-widgets' ),
			'columns'          => 3,
			'chip_layout'      => 'stacked',
			'icon_align'       => 'center',
			'enable_popouts'   => false,
			'popout_items'     => array(),
			'features'         => array(),
		);

		$parsed   = Rsmspark_Content_Widgets_Render::parse_atts( $atts, $defaults, 'rsmspark_features' );
		$features = self::coerce_features( $parsed['features'] );
		$popouts  = self::default_popouts_section();
		$popouts['enable_popouts'] = Rsmspark_Content_Widgets_Features_Popouts::is_enabled( $parsed['enable_popouts'] ?? false );
		$popouts['popout_items']   = self::coerce_popout_items( $parsed['popout_items'] ?? array() );

		$design = wp_parse_args(
			isset( $atts['design'] ) && is_array( $atts['design'] ) ? $atts['design'] : array(),
			Rsmspark_Content_Widgets_Features_Config::demo_instance()['design']
		);
		$design['icon_align'] = sanitize_key(
			(string) ( $parsed['icon_align'] ?? $design['icon_align'] ?? 'center' )
		);

		return array(
			'general' => array(
				'title'    => sanitize_text_field( (string) $parsed['title'] ),
				'features' => $features,
			),
			'layout'  => array(
				'columns'     => max( 1, min( 6, absint( $parsed['columns'] ) ) ),
				'chip_layout' => Rsmspark_Content_Widgets_Features_Styles::sanitize_chip_layout( $parsed['chip_layout'] ?? 'stacked' ),
			),
			'design'  => Rsmspark_Content_Widgets_Features_Config::sanitize_instance(
				array(
					'general'  => array(),
					'layout'   => array(),
					'popouts'  => array(),
					'design'   => $design,
				)
			)['design'],
			'popouts' => $popouts,
		);
	}

	/**
	 * Default popout section values (matches SiteOrigin widget defaults).
	 *
	 * @return array<string, mixed>
	 */
	public static function default_popouts_section() {
		return array(
			'enable_popouts'              => false,
			'popout_overlay_color'        => '#0f172a',
			'popout_overlay_opacity'      => 70,
			'popout_bg'                   => '#ffffff',
			'popout_border_color'         => '#e2e8f0',
			'popout_border_width'         => 1,
			'popout_shape'                => 'large',
			'popout_title_color'          => '#0f172a',
			'popout_text_color'           => '#475569',
			'popout_pad'                  => 28,
			'popout_max_width'            => 640,
			'popout_max_height'           => 720,
			'popout_title_font'           => 'inherit',
			'popout_title_font_size'      => 0,
			'popout_header_icon_scale'    => 125,
			'popout_header_gap'           => 12,
			'popout_subtitle_color'       => '#64748b',
			'popout_subtitle_font_size'   => 0,
			'popout_header_divider'       => false,
			'popout_header_divider_color' => '#e2e8f0',
			'popout_header_divider_width' => 1,
			'popout_body_font'            => 'inherit',
			'popout_body_font_size'       => 0,
			'popout_items'                => array(),
		);
	}

	/**
	 * @param mixed $items Raw popout repeater rows from block/shortcode.
	 * @return array<int, array<string, mixed>>
	 */
	public static function coerce_popout_items( $items ) {
		if ( ! is_array( $items ) ) {
			return array();
		}

		$clean = array();
		foreach ( $items as $item ) {
			if ( ! is_array( $item ) ) {
				continue;
			}

			$row = array(
				'chip_label'                     => sanitize_text_field( (string) ( $item['chip_label'] ?? '' ) ),
				'popout_title'                   => isset( $item['popout_title'] ) ? Rsmspark_Content_Widgets_Headline_Styles::sanitize_line_html( $item['popout_title'] ) : '',
				'popout_subtitle'                => isset( $item['popout_subtitle'] ) ? Rsmspark_Content_Widgets_Headline_Styles::sanitize_line_html( $item['popout_subtitle'] ) : '',
				'popout_content'                 => isset( $item['popout_content'] ) ? Rsmspark_Rich_Text_Body::sanitize( $item['popout_content'] ) : '',
				'popout_media'                   => isset( $item['popout_media'] ) ? sanitize_key( (string) $item['popout_media'] ) : 'inherit',
				'popout_icon'                    => Rsmspark_Content_Widgets_Features_Styles::normalize_icon_classes( $item['popout_icon'] ?? '' ),
				'popout_icon_style'              => Rsmspark_Content_Widgets_Features_Styles::sanitize_icon_style( $item['popout_icon_style'] ?? 'glyph' ),
				'popout_icon_color'              => sanitize_hex_color( (string) ( $item['popout_icon_color'] ?? '' ) ) ?: '',
				'popout_icon_badge_circle_color' => sanitize_hex_color( (string) ( $item['popout_icon_badge_circle_color'] ?? '' ) ) ?: '',
				'popout_icon_badge_text_color'   => sanitize_hex_color( (string) ( $item['popout_icon_badge_text_color'] ?? '' ) ) ?: '',
				'popout_icon_badge_glyph'        => sanitize_key( (string) ( $item['popout_icon_badge_glyph'] ?? '' ) ),
				'popout_image'                   => absint( $item['popout_image'] ?? 0 ),
				'popout_icon_size'               => isset( $item['popout_icon_size'] ) ? sanitize_key( (string) $item['popout_icon_size'] ) : 'inherit',
				'popout_icon_size_custom'        => isset( $item['popout_icon_size_custom'] ) ? (int) $item['popout_icon_size_custom'] : 0,
			);

			$resolved = Rsmspark_Content_Widgets_Features_Popouts::sanitize_popout_item( $row );
			if ( null !== $resolved ) {
				$clean[] = $resolved;
				continue;
			}

			if ( '' !== $row['chip_label'] ) {
				$clean[] = $row;
			}
		}

		return $clean;
	}

	/**
	 * @param mixed $features Raw feature list from shortcode or block.
	 * @return array<int, array<string, mixed>>
	 */
	public static function coerce_features( $features ) {
		if ( is_string( $features ) && '' !== $features ) {
			$features = Rsmspark_Content_Widgets_Render::parse_json_attr( $features, self::default_feature_chips() );
		}
		if ( ! is_array( $features ) || empty( $features ) ) {
			$features = self::default_feature_chips();
		}

		$clean = array();
		foreach ( $features as $feature ) {
			if ( ! is_array( $feature ) ) {
				continue;
			}
			$description = $feature['description'] ?? $feature['body'] ?? $feature['content'] ?? '';

			$clean[] = array(
				'enabled'                 => ! array_key_exists( 'enabled', $feature ) || ! empty( $feature['enabled'] ),
				'title'                   => Rsmspark_Content_Widgets_Headline_Styles::sanitize_line_html( $feature['title'] ?? '' ),
				'description'             => Rsmspark_Rich_Text_Body::sanitize( $description ),
				'title_icon'              => Rsmspark_Content_Widgets_Features_Styles::normalize_icon_classes( (string) ( $feature['title_icon'] ?? '' ) ),
				'title_image'             => absint( $feature['title_image'] ?? 0 ),
				'accent_color'            => sanitize_hex_color( (string) ( $feature['accent_color'] ?? '' ) ) ?: '',
				'icon_style'              => Rsmspark_Content_Widgets_Features_Styles::sanitize_icon_style( $feature['icon_style'] ?? 'glyph' ),
				'icon_color'              => sanitize_hex_color( (string) ( $feature['icon_color'] ?? '' ) ) ?: '',
				'icon_badge_circle_color' => sanitize_hex_color( (string) ( $feature['icon_badge_circle_color'] ?? '' ) ) ?: '',
				'icon_badge_text_color'   => sanitize_hex_color( (string) ( $feature['icon_badge_text_color'] ?? '' ) ) ?: '',
				'icon_badge_glyph'        => sanitize_key( (string) ( $feature['icon_badge_glyph'] ?? '' ) ),
				'chip_shape'              => sanitize_key( (string) ( $feature['chip_shape'] ?? 'inherit' ) ),
				'popout_hot'              => Rsmspark_Content_Widgets_Features_Popouts::is_enabled( $feature['popout_hot'] ?? false ),
			);
		}

		return ! empty( $clean ) ? $clean : self::default_feature_chips();
	}

	/**
	 * @return array<int, array<string, mixed>>
	 */
	public static function default_feature_chips() {
		return array(
			array(
				'enabled'      => true,
				'title'        => __( 'Fast setup', 'rsm-content-widgets' ),
				'description'  => '<p>' . __( 'Drop the widget into any layout and start editing chip cards immediately.', 'rsm-content-widgets' ) . '</p>',
				'title_icon'   => 'dashicons dashicons-performance',
				'title_image'  => 0,
				'accent_color' => '#2563eb',
				'chip_shape'   => 'inherit',
			),
			array(
				'enabled'      => true,
				'title'        => __( 'Theme fonts', 'rsm-content-widgets' ),
				'description'  => '<p>' . __( 'Inherits theme typography by default.', 'rsm-content-widgets' ) . '</p>',
				'title_icon'   => 'dashicons dashicons-editor-textcolor',
				'title_image'  => 0,
				'accent_color' => '#0f766e',
				'chip_shape'   => 'inherit',
			),
			array(
				'enabled'      => true,
				'title'        => __( 'Flexible shapes', 'rsm-content-widgets' ),
				'description'  => '<p>' . __( 'Choose global corner presets or override individual chips.', 'rsm-content-widgets' ) . '</p>',
				'title_icon'   => 'dashicons dashicons-art',
				'title_image'  => 0,
				'accent_color' => '#c2410c',
				'chip_shape'   => 'inherit',
			),
		);
	}

	/**
	 * @param array<string, mixed> $instance Widget instance (SiteOrigin sections).
	 * @param array<string, mixed> $args     Sidebar args.
	 * @return array<string, mixed>
	 */
	public static function prepare_template_vars( $instance, $args = array() ) {
		self::ensure_dependencies();

		$instance = is_array( $instance ) ? $instance : array();
		$args     = is_array( $args ) ? $args : array();

		$general = isset( $instance['general'] ) && is_array( $instance['general'] ) ? $instance['general'] : array();
		$layout  = isset( $instance['layout'] ) && is_array( $instance['layout'] ) ? $instance['layout'] : array();
		$design  = isset( $instance['design'] ) && is_array( $instance['design'] ) ? $instance['design'] : array();
		$popouts = isset( $instance['popouts'] ) && is_array( $instance['popouts'] ) ? $instance['popouts'] : array();

		$popouts_enabled = Rsmspark_Content_Widgets_Features_Popouts::is_enabled( $popouts['enable_popouts'] ?? false );
		$popout_map      = Rsmspark_Content_Widgets_Features_Popouts::build_popout_map(
			isset( $popouts['popout_items'] ) && is_array( $popouts['popout_items'] ) ? $popouts['popout_items'] : array()
		);

		$design['columns']  = isset( $layout['columns'] ) ? (int) $layout['columns'] : 3;
		$design['grid_gap'] = isset( $layout['grid_gap'] ) ? (int) $layout['grid_gap'] : 16;

		$default_shape = isset( $design['chip_shape'] ) ? sanitize_key( (string) $design['chip_shape'] ) : 'medium';
		$chip_style    = isset( $design['chip_style'] ) ? sanitize_key( (string) $design['chip_style'] ) : 'soft';
		if ( ! array_key_exists( $chip_style, Rsmspark_Content_Widgets_Features_Styles::get_chip_style_options() ) ) {
			$chip_style = 'soft';
		}

		$align = isset( $layout['align'] ) ? sanitize_key( (string) $layout['align'] ) : 'left';
		if ( ! in_array( $align, array( 'left', 'center' ), true ) ) {
			$align = 'left';
		}

		$chip_layout = Rsmspark_Content_Widgets_Features_Styles::sanitize_chip_layout( $layout['chip_layout'] ?? 'stacked' );
		$media_gap   = isset( $layout['media_gap'] ) ? max( 0, min( 48, (int) $layout['media_gap'] ) ) : 16;

		$icon_preset = isset( $design['icon_size_preset'] ) ? sanitize_key( (string) $design['icon_size_preset'] ) : 'medium';
		if ( ! in_array( $icon_preset, Rsmspark_Content_Widgets_Features_Styles::icon_size_keys(), true ) || 'inherit' === $icon_preset ) {
			$icon_preset = 'medium';
		}
		$icon_custom = isset( $design['icon_size_custom'] ) ? (int) $design['icon_size_custom'] : Rsmspark_Content_Widgets_Features_Styles::get_icon_size_custom_bounds()['default'];
		$icon_align  = isset( $design['icon_align'] ) ? sanitize_key( (string) $design['icon_align'] ) : 'center';
		if ( ! in_array( $icon_align, array( 'left', 'center', 'right' ), true ) ) {
			$icon_align = 'left';
		}

		$icon_defaults = array(
			'icon_size_preset' => $icon_preset,
			'icon_size_custom' => $icon_custom,
			'icon_align'       => $icon_align,
		);

		$features_raw = isset( $general['features'] ) && is_array( $general['features'] ) ? $general['features'] : array();
		$features_out = array();

		foreach ( $features_raw as $raw_index => $feature ) {
			if ( ! is_array( $feature ) ) {
				continue;
			}
			if ( ! self::is_enabled( $feature['enabled'] ?? true ) ) {
				continue;
			}

			$title = Rsmspark_Content_Widgets_Headline_Styles::sanitize_line_html( $feature['title'] ?? '' );
			if ( ! Rsmspark_Content_Widgets_Headline_Styles::line_has_text( $title ) && empty( $feature['description'] ) ) {
				continue;
			}

			$title_plain = trim( wp_strip_all_tags( $title ) );
			$accent = isset( $feature['accent_color'] ) ? sanitize_hex_color( (string) $feature['accent_color'] ) : '';

			$chip_icon_align = Rsmspark_Content_Widgets_Features_Styles::resolve_icon_align(
				$feature['icon_align'] ?? 'inherit',
				$icon_align
			);

			$is_hot    = $popouts_enabled && self::is_enabled( $feature['popout_hot'] ?? false );
			$popout    = $is_hot ? Rsmspark_Content_Widgets_Features_Popouts::resolve_for_chip( (int) $raw_index, $title_plain, $popout_map ) : null;
			$popout_id = 'p' . (int) $raw_index;

			$popout_title    = '';
			$popout_subtitle = '';
			$popout_content  = '';
			$popout_media    = array(
				'title_icon'   => '',
				'image_url'    => '',
				'inline_style' => '',
			);

			if ( $is_hot ) {
				$chip_image_url = self::media_url( $feature['title_image'] ?? '' );
				$chip_icon      = Rsmspark_Content_Widgets_Features_Styles::normalize_icon_classes( $feature['title_icon'] ?? '' );
				$popout_row     = is_array( $popout ) ? $popout : array();

				if ( is_array( $popout ) ) {
					$popout_title    = Rsmspark_Content_Widgets_Headline_Styles::line_has_text( $popout['popout_title'] ?? '' )
						? $popout['popout_title']
						: $title;
					$popout_subtitle = isset( $popout['popout_subtitle'] ) ? $popout['popout_subtitle'] : '';
					$popout_content  = isset( $popout['popout_content'] ) ? $popout['popout_content'] : '';
				} else {
					$popout_title    = $title;
					$popout_subtitle = '';
					$popout_content  = '';
				}

				if ( '' === trim( wp_strip_all_tags( (string) $popout_content ) ) && ! empty( $feature['description'] ) ) {
					$popout_content = $feature['description'];
				}

				$popout_media = Rsmspark_Content_Widgets_Features_Popouts::resolve_media(
					$popout_row,
					array(
						'title_icon'       => $chip_icon,
						'image_url'        => $chip_image_url,
						'accent_color'     => $accent,
						'icon_size'        => $feature['icon_size'] ?? 'inherit',
						'icon_size_custom' => $feature['icon_size_custom'] ?? 0,
					),
					self::media_url( $popout_row['popout_image'] ?? '' ),
					$icon_defaults
				);
			}

			$features_out[] = array(
				'title'              => $title,
				'description'        => Rsmspark_Rich_Text_Body::sanitize(
					$feature['description'] ?? $feature['body'] ?? $feature['content'] ?? ''
				),
				'title_icon'         => Rsmspark_Content_Widgets_Features_Styles::normalize_icon_classes( $feature['title_icon'] ?? '' ),
				'image_url'          => self::media_url( $feature['title_image'] ?? '' ),
				'accent_color'       => $accent ? $accent : '',
				'chip_shape'         => isset( $feature['chip_shape'] ) ? sanitize_key( (string) $feature['chip_shape'] ) : 'inherit',
				'icon_align'         => $chip_icon_align,
				'is_hot'             => $is_hot && (
					'' !== $title
					|| '' !== trim( wp_strip_all_tags( (string) $popout_content ) )
					|| Rsmspark_Content_Widgets_Headline_Styles::line_has_text( $popout_title )
					|| Rsmspark_Content_Widgets_Headline_Styles::line_has_text( $popout_subtitle )
				),
				'popout_id'          => $popout_id,
				'popout_title'       => $popout_title,
				'popout_subtitle'    => $popout_subtitle,
				'popout_content'     => $popout_content,
				'popout_icon'        => $popout_media['title_icon'],
				'popout_icon_html'   => '',
				'popout_image_url'   => $popout_media['image_url'],
				'popout_media_style' => $popout_media['inline_style'],
				'inline_style'       => Rsmspark_Content_Widgets_Features_Styles::chip_inline_style(
					array(
						'accent_color'     => $accent,
						'chip_shape'       => $feature['chip_shape'] ?? 'inherit',
						'icon_size'        => $feature['icon_size'] ?? 'inherit',
						'icon_size_custom' => $feature['icon_size_custom'] ?? 0,
						'icon_color'       => $feature['icon_color'] ?? '',
					),
					$default_shape,
					$icon_defaults
				),
				'icon_html'          => Rsmspark_Content_Widgets_Features_Styles::render_icon_html(
					Rsmspark_Content_Widgets_Features_Styles::icon_render_args_from_feature(
						array_merge(
							$feature,
							array(
								'title_icon'   => isset( $feature['title_icon'] ) ? Rsmspark_Content_Widgets_Features_Styles::normalize_icon_classes( $feature['title_icon'] ) : '',
								'accent_color' => $accent,
							)
						)
					)
				),
			);

			$last_index = count( $features_out ) - 1;
			if ( $is_hot ) {
				$popout_icon_row = array_merge(
					$feature,
					is_array( $popout ) ? $popout : array(),
					array(
						'popout_icon'  => $popout_media['title_icon'],
						'accent_color' => $accent,
					)
				);
				if ( ! isset( $popout['popout_media'] ) || 'inherit' === sanitize_key( (string) ( $popout['popout_media'] ?? 'inherit' ) ) ) {
					$popout_icon_row['popout_icon_style']              = $feature['icon_style'] ?? 'glyph';
					$popout_icon_row['popout_icon_color']              = $feature['icon_color'] ?? '';
					$popout_icon_row['popout_icon_badge_circle_color'] = $feature['icon_badge_circle_color'] ?? '';
					$popout_icon_row['popout_icon_badge_text_color']   = $feature['icon_badge_text_color'] ?? '';
					$popout_icon_row['popout_icon_badge_glyph']        = $feature['icon_badge_glyph'] ?? '';
				}

				$features_out[ $last_index ]['popout_icon_html'] = Rsmspark_Content_Widgets_Features_Styles::render_icon_html(
					array_merge(
						Rsmspark_Content_Widgets_Features_Styles::icon_render_args_from_feature( $popout_icon_row, 'popout' ),
						array( 'icon' => $popout_media['title_icon'] )
					)
				);
			}
		}

		if ( empty( $features_out ) ) {
			$fallback_icon = 'dashicons dashicons-star-filled';
			$features_out[] = array(
				'title'            => __( 'Feature', 'rsm-content-widgets' ),
				'description'      => '',
				'title_icon'       => $fallback_icon,
				'icon_html'        => Rsmspark_Content_Widgets_Features_Styles::render_icon_html(
					array(
						'icon'           => $fallback_icon,
						'icon_style'     => 'glyph',
						'wrapper_class'  => 'rsmspark-features__chip-media__class',
					)
				),
				'image_url'        => '',
				'accent_color'     => '',
				'chip_shape'       => 'inherit',
				'icon_align'       => $icon_align,
				'popout_icon_html' => '',
				'inline_style'     => Rsmspark_Content_Widgets_Features_Styles::chip_inline_style( array(), $default_shape, $icon_defaults ),
			);
		}

		$css_vars = Rsmspark_Content_Widgets_Features_Styles::build_css_variables( $design );
		$css_vars['--rf-media-gap']         = $media_gap . 'px';
		$css_vars['--rf-stacked-icon-gap']  = max( $media_gap, 12 ) . 'px';
		if ( $popouts_enabled ) {
			$css_vars = array_merge( $css_vars, Rsmspark_Content_Widgets_Features_Popouts::build_css_variables( $popouts ) );
		}
		$style_pairs = array();
		foreach ( $css_vars as $k => $v ) {
			$style_pairs[] = esc_attr( $k ) . ':' . esc_attr( $v );
		}
		$inline_style = implode( ';', $style_pairs );

		$container_border = Rsmspark_Content_Widgets_Features_Styles::is_container_border_enabled( $design['container_border'] ?? false );
		$has_hot_chips    = false;
		foreach ( $features_out as $feature_row ) {
			if ( ! empty( $feature_row['is_hot'] ) ) {
				$has_hot_chips = true;
				break;
			}
		}

		$popout_header_divider = Rsmspark_Content_Widgets_Features_Popouts::is_header_divider_enabled( $popouts['popout_header_divider'] ?? false );
		$popout_dialog_style   = $popouts_enabled ? Rsmspark_Content_Widgets_Features_Popouts::build_inline_style( $popouts ) : '';
		$popout_header_gap_px  = $popouts_enabled ? Rsmspark_Content_Widgets_Features_Popouts::header_gap_px( $popouts ) : 12;

		$widget_uid = 'rsmspark-features-' . wp_unique_id();

		return array(
			'widget_uid'            => $widget_uid,
			'heading_title'         => isset( $general['title'] ) ? sanitize_text_field( $general['title'] ) : '',
			'features'              => $features_out,
			'chip_style'            => $chip_style,
			'chip_layout'           => $chip_layout,
			'align'                 => $align,
			'icon_align'            => $icon_align,
			'container_border'      => $container_border,
			'inline_style'          => $inline_style,
			'popouts_enabled'       => $popouts_enabled && $has_hot_chips,
			'popout_header_divider' => $popout_header_divider,
			'popout_dialog_style'   => $popout_dialog_style,
			'popout_header_gap_px'  => $popout_header_gap_px,
			'modal_label_id'        => $widget_uid . '-modal-title',
			'before_title'          => $args['before_title'] ?? '',
			'after_title'           => $args['after_title'] ?? '',
		);
	}

	/**
	 * @param array<string, mixed> $args Template variables.
	 * @return string
	 */
	public static function render( array $args ) {
		if ( empty( $args['features'] ) ) {
			$args = self::prepare_template_vars( self::build_instance_from_simple_atts( array() ), array() );
		}

		return Rsmspark_Content_Widgets_Render::render_template(
			self::REGISTRY_ID,
			'features.php',
			$args
		);
	}

	/**
	 * @return void
	 */
	public static function ensure_dependencies() {
		require_once RSMSPARK_CONTENT_WIDGETS_PATH . 'includes/class-rsmspark-content-widgets-features-fonts.php';
		require_once RSMSPARK_CONTENT_WIDGETS_PATH . 'includes/class-rsmspark-content-widgets-features-styles.php';
		require_once RSMSPARK_CONTENT_WIDGETS_PATH . 'includes/class-rsmspark-content-widgets-features-popouts.php';
	}

	/**
	 * @param mixed $media Attachment id or SiteOrigin media array.
	 * @return string
	 */
	public static function media_url( $media ) {
		if ( empty( $media ) ) {
			return '';
		}
		$id = 0;
		if ( is_numeric( $media ) ) {
			$id = (int) $media;
		} elseif ( is_array( $media ) ) {
			if ( ! empty( $media['ID'] ) ) {
				$id = (int) $media['ID'];
			} elseif ( ! empty( $media['id'] ) ) {
				$id = (int) $media['id'];
			}
		}
		if ( ! $id ) {
			return '';
		}
		foreach ( array( 'medium', 'large', 'full', 'thumbnail' ) as $size ) {
			$src = wp_get_attachment_image_url( $id, $size );
			if ( $src ) {
				return $src;
			}
		}
		return '';
	}

	/**
	 * @param mixed $value Raw checkbox value.
	 * @return bool
	 */
	public static function is_enabled( $value ) {
		if ( is_bool( $value ) ) {
			return $value;
		}
		if ( is_string( $value ) ) {
			return in_array( strtolower( $value ), array( '1', 'true', 'yes', 'on' ), true );
		}
		return ! empty( $value );
	}
}

/**
 * @param array<string, mixed> $args Widget arguments or SiteOrigin instance.
 * @return string
 */
function rsmspark_cw_render_features( array $args ) {
	if ( isset( $args['general'] ) || isset( $args['layout'] ) || isset( $args['design'] ) ) {
		return Rsmspark_Content_Widgets_Widget_Features::render( Rsmspark_Content_Widgets_Widget_Features::prepare_template_vars( $args, array() ) );
	}
	return Rsmspark_Content_Widgets_Widget_Features::render( Rsmspark_Content_Widgets_Widget_Features::normalize_atts( $args ) );
}
