<?php
/**
 * Features widget configuration, defaults, and JSON migration helpers.
 *
 * @package Rsmspark_Content_Widgets
 */

defined( 'ABSPATH' ) || exit;

require_once RSMSPARK_CONTENT_WIDGETS_PATH . 'includes/widgets/class-rsmspark-content-widgets-widget-features.php';

/**
 * Rsmspark_Content_Widgets_Features_Config
 */
class Rsmspark_Content_Widgets_Features_Config {

	const EXPORT_PLUGIN = 'rsmspark-content-widgets';

	const EXPORT_WIDGET = 'features';

	/**
	 * @return array<string, mixed>
	 */
	public static function demo_instance() {
		Rsmspark_Content_Widgets_Widget_Features::ensure_dependencies();

		return array(
			'general' => array(
				'title'    => __( 'Features', 'rsm-content-widgets' ),
				'features' => Rsmspark_Content_Widgets_Widget_Features::default_feature_chips(),
			),
			'layout'  => array(
				'columns'     => 3,
				'grid_gap'    => 16,
				'chip_layout' => 'stacked',
				'media_gap'   => 16,
				'align'       => 'left',
			),
			'design'  => array(
				'container_border'       => false,
				'container_border_color' => '#e2e8f0',
				'container_border_width' => 1,
				'container_shape'        => 'medium',
				'container_pad'          => 16,
				'chip_style'             => 'soft',
				'chip_shape'             => 'medium',
				'chip_bg'                => '#ffffff',
				'chip_border_color'      => '#e2e8f0',
				'chip_border_width'      => 1,
				'chip_accent_color'      => '#2563eb',
				'chip_title_color'       => '#0f172a',
				'chip_text_color'        => '#475569',
				'chip_pad_top'           => 16,
				'chip_pad_right'         => 18,
				'chip_pad_bottom'        => 16,
				'chip_pad_left'          => 18,
				'icon_size_preset'       => 'medium',
				'icon_size_custom'       => Rsmspark_Content_Widgets_Features_Styles::get_icon_size_custom_bounds()['default'],
				'icon_align'             => 'center',
				'title_font'               => 'inherit',
				'title_font_size'        => 0,
				'title_font_weight'      => 700,
				'body_font'              => 'inherit',
				'body_font_size'         => 0,
			),
			'popouts' => Rsmspark_Content_Widgets_Widget_Features::default_popouts_section(),
		);
	}

	/**
	 * @param mixed $raw Raw instance or block attributes.
	 * @return array<string, mixed>
	 */
	public static function sanitize_instance( $raw ) {
		if ( is_string( $raw ) && '' !== $raw ) {
			$decoded = json_decode( $raw, true );
			$raw     = is_array( $decoded ) ? $decoded : array();
		}

		if ( ! is_array( $raw ) ) {
			$raw = array();
		}

		if ( self::looks_like_block_attributes( $raw ) ) {
			return self::from_block_attributes( $raw );
		}

		$demo = self::demo_instance();

		$general = wp_parse_args(
			isset( $raw['general'] ) && is_array( $raw['general'] ) ? $raw['general'] : array(),
			$demo['general']
		);
		$layout = wp_parse_args(
			isset( $raw['layout'] ) && is_array( $raw['layout'] ) ? $raw['layout'] : array(),
			$demo['layout']
		);
		$design = wp_parse_args(
			isset( $raw['design'] ) && is_array( $raw['design'] ) ? $raw['design'] : array(),
			$demo['design']
		);
		$popouts = wp_parse_args(
			isset( $raw['popouts'] ) && is_array( $raw['popouts'] ) ? $raw['popouts'] : array(),
			$demo['popouts']
		);

		$popouts['enable_popouts'] = Rsmspark_Content_Widgets_Features_Popouts::is_enabled( $popouts['enable_popouts'] ?? false );
		$popouts['popout_items']   = Rsmspark_Content_Widgets_Widget_Features::coerce_popout_items( $popouts['popout_items'] ?? array() );

		return array(
			'general' => array(
				'title'    => sanitize_text_field( (string) ( $general['title'] ?? '' ) ),
				'features' => Rsmspark_Content_Widgets_Widget_Features::coerce_features( $general['features'] ?? array() ),
			),
			'layout'  => self::sanitize_layout( $layout, $demo['layout'] ),
			'design'  => self::sanitize_design( $design, $demo['design'] ),
			'popouts' => self::sanitize_popouts_section( $popouts, $demo['popouts'] ),
		);
	}

	/**
	 * @param array<string, mixed> $raw Block attributes.
	 * @return array<string, mixed>
	 */
	public static function from_block_attributes( array $raw ) {
		return self::sanitize_instance(
			Rsmspark_Content_Widgets_Widget_Features::build_instance_from_simple_atts( $raw )
		);
	}

	/**
	 * @param array<string, mixed> $instance SiteOrigin instance or sanitized config.
	 * @return array<string, mixed>
	 */
	public static function from_siteorigin_instance( array $instance ) {
		return self::sanitize_instance( $instance );
	}

	/**
	 * @param array<string, mixed> $instance Sanitized SiteOrigin instance.
	 * @return array<string, mixed>
	 */
	public static function to_block_attributes( array $instance ) {
		$instance = self::from_siteorigin_instance( $instance );
		$general  = $instance['general'];
		$layout   = $instance['layout'];
		$design   = $instance['design'];
		$popouts  = $instance['popouts'];

		$features = array();
		foreach ( $general['features'] as $feature ) {
			if ( ! is_array( $feature ) ) {
				continue;
			}
			$row = $feature;
			$row['enabled']    = Rsmspark_Content_Widgets_Widget_Features::is_enabled( $feature['enabled'] ?? true );
			$row['popout_hot'] = Rsmspark_Content_Widgets_Features_Popouts::is_enabled( $feature['popout_hot'] ?? false );
			$row['title_image'] = absint( $feature['title_image'] ?? 0 );
			$features[] = $row;
		}

		return array(
			'title'          => (string) ( $general['title'] ?? '' ),
			'columns'        => (int) ( $layout['columns'] ?? 3 ),
			'chip_layout'    => (string) ( $layout['chip_layout'] ?? 'stacked' ),
			'icon_align'     => (string) ( $design['icon_align'] ?? 'center' ),
			'design'         => $design,
			'enable_popouts' => Rsmspark_Content_Widgets_Features_Popouts::is_enabled( $popouts['enable_popouts'] ?? false ),
			'popout_items'   => is_array( $popouts['popout_items'] ?? null ) ? $popouts['popout_items'] : array(),
			'features'       => $features,
		);
	}

	/**
	 * @param array<string, mixed> $layout Layout section.
	 * @param array<string, mixed> $demo   Defaults.
	 * @return array<string, mixed>
	 */
	private static function sanitize_layout( array $layout, array $demo ) {
		$align = sanitize_key( (string) ( $layout['align'] ?? $demo['align'] ) );
		if ( ! in_array( $align, array( 'left', 'center' ), true ) ) {
			$align = (string) $demo['align'];
		}

		return array(
			'columns'     => max( 1, min( 6, absint( $layout['columns'] ?? $demo['columns'] ) ) ),
			'grid_gap'    => max( 0, min( 48, absint( $layout['grid_gap'] ?? $demo['grid_gap'] ) ) ),
			'chip_layout' => Rsmspark_Content_Widgets_Features_Styles::sanitize_chip_layout( $layout['chip_layout'] ?? $demo['chip_layout'] ),
			'media_gap'   => max( 0, min( 48, absint( $layout['media_gap'] ?? $demo['media_gap'] ) ) ),
			'align'       => $align,
		);
	}

	/**
	 * @param array<string, mixed> $design Design section.
	 * @param array<string, mixed> $demo   Defaults.
	 * @return array<string, mixed>
	 */
	private static function sanitize_design( array $design, array $demo ) {
		$sanitize_color = static function ( $value, $fallback ) {
			$color = sanitize_hex_color( (string) $value );
			return $color ? $color : (string) $fallback;
		};

		$icon_align = sanitize_key( (string) ( $design['icon_align'] ?? $demo['icon_align'] ) );
		if ( ! in_array( $icon_align, array( 'left', 'center', 'right' ), true ) ) {
			$icon_align = (string) $demo['icon_align'];
		}

		$chip_style = sanitize_key( (string) ( $design['chip_style'] ?? $demo['chip_style'] ) );
		if ( ! array_key_exists( $chip_style, Rsmspark_Content_Widgets_Features_Styles::get_chip_style_options() ) ) {
			$chip_style = (string) $demo['chip_style'];
		}

		return array(
			'container_border'       => Rsmspark_Content_Widgets_Features_Styles::is_container_border_enabled( $design['container_border'] ?? $demo['container_border'] ),
			'container_border_color' => $sanitize_color( $design['container_border_color'] ?? '', $demo['container_border_color'] ),
			'container_border_width' => max( 1, min( 8, absint( $design['container_border_width'] ?? $demo['container_border_width'] ) ) ),
			'container_shape'        => sanitize_key( (string) ( $design['container_shape'] ?? $demo['container_shape'] ) ),
			'container_pad'          => max( 0, min( 48, absint( $design['container_pad'] ?? $demo['container_pad'] ) ) ),
			'chip_style'             => $chip_style,
			'chip_shape'             => sanitize_key( (string) ( $design['chip_shape'] ?? $demo['chip_shape'] ) ),
			'chip_bg'                => $sanitize_color( $design['chip_bg'] ?? '', $demo['chip_bg'] ),
			'chip_border_color'      => $sanitize_color( $design['chip_border_color'] ?? '', $demo['chip_border_color'] ),
			'chip_border_width'      => max( 0, min( 6, absint( $design['chip_border_width'] ?? $demo['chip_border_width'] ) ) ),
			'chip_accent_color'      => $sanitize_color( $design['chip_accent_color'] ?? '', $demo['chip_accent_color'] ),
			'chip_title_color'       => $sanitize_color( $design['chip_title_color'] ?? '', $demo['chip_title_color'] ),
			'chip_text_color'        => $sanitize_color( $design['chip_text_color'] ?? '', $demo['chip_text_color'] ),
			'chip_pad_top'           => max( 0, min( 48, absint( $design['chip_pad_top'] ?? $demo['chip_pad_top'] ) ) ),
			'chip_pad_right'         => max( 0, min( 48, absint( $design['chip_pad_right'] ?? $demo['chip_pad_right'] ) ) ),
			'chip_pad_bottom'        => max( 0, min( 48, absint( $design['chip_pad_bottom'] ?? $demo['chip_pad_bottom'] ) ) ),
			'chip_pad_left'          => max( 0, min( 48, absint( $design['chip_pad_left'] ?? $demo['chip_pad_left'] ) ) ),
			'icon_size_preset'       => sanitize_key( (string) ( $design['icon_size_preset'] ?? $demo['icon_size_preset'] ) ),
			'icon_size_custom'       => (int) ( $design['icon_size_custom'] ?? $demo['icon_size_custom'] ),
			'icon_align'             => $icon_align,
			'title_font'             => sanitize_key( (string) ( $design['title_font'] ?? $demo['title_font'] ) ),
			'title_font_size'        => max( 0, min( 36, absint( $design['title_font_size'] ?? $demo['title_font_size'] ) ) ),
			'title_font_weight'      => max( 400, min( 900, absint( $design['title_font_weight'] ?? $demo['title_font_weight'] ) ) ),
			'body_font'              => sanitize_key( (string) ( $design['body_font'] ?? $demo['body_font'] ) ),
			'body_font_size'         => max( 0, min( 24, absint( $design['body_font_size'] ?? $demo['body_font_size'] ) ) ),
		);
	}

	/**
	 * @param array<string, mixed> $popouts Popouts section.
	 * @param array<string, mixed> $demo    Defaults.
	 * @return array<string, mixed>
	 */
	private static function sanitize_popouts_section( array $popouts, array $demo ) {
		$merged = wp_parse_args( $popouts, $demo );
		$merged['enable_popouts'] = Rsmspark_Content_Widgets_Features_Popouts::is_enabled( $merged['enable_popouts'] ?? false );
		$merged['popout_items']   = Rsmspark_Content_Widgets_Widget_Features::coerce_popout_items( $merged['popout_items'] ?? array() );

		$color_keys = array(
			'popout_overlay_color',
			'popout_bg',
			'popout_border_color',
			'popout_title_color',
			'popout_text_color',
			'popout_subtitle_color',
			'popout_header_divider_color',
		);

		foreach ( $color_keys as $key ) {
			if ( ! array_key_exists( $key, $merged ) ) {
				continue;
			}
			$color = sanitize_hex_color( (string) $merged[ $key ] );
			$merged[ $key ] = $color ? $color : (string) ( $demo[ $key ] ?? '' );
		}

		$merged['popout_overlay_opacity'] = max( 0, min( 100, absint( $merged['popout_overlay_opacity'] ?? $demo['popout_overlay_opacity'] ) ) );
		$merged['popout_border_width']      = max( 0, min( 6, absint( $merged['popout_border_width'] ?? $demo['popout_border_width'] ) ) );
		$merged['popout_shape']             = sanitize_key( (string) ( $merged['popout_shape'] ?? $demo['popout_shape'] ) );
		$merged['popout_pad']               = max( 0, min( 48, absint( $merged['popout_pad'] ?? $demo['popout_pad'] ) ) );
		$merged['popout_max_width']         = max( 320, min( 1280, absint( $merged['popout_max_width'] ?? $demo['popout_max_width'] ) ) );
		$merged['popout_max_height']        = max( 400, min( 960, absint( $merged['popout_max_height'] ?? $demo['popout_max_height'] ) ) );
		$merged['popout_title_font']        = sanitize_key( (string) ( $merged['popout_title_font'] ?? $demo['popout_title_font'] ) );
		$merged['popout_title_font_size']   = max( 0, min( 48, absint( $merged['popout_title_font_size'] ?? $demo['popout_title_font_size'] ) ) );
		$merged['popout_header_icon_scale'] = max( 100, min( 200, absint( $merged['popout_header_icon_scale'] ?? $demo['popout_header_icon_scale'] ) ) );
		$merged['popout_header_gap']        = max( 0, min( 48, absint( $merged['popout_header_gap'] ?? $demo['popout_header_gap'] ) ) );
		$merged['popout_subtitle_font_size'] = max( 0, min( 36, absint( $merged['popout_subtitle_font_size'] ?? $demo['popout_subtitle_font_size'] ) ) );
		$merged['popout_header_divider']    = Rsmspark_Content_Widgets_Features_Popouts::is_header_divider_enabled( $merged['popout_header_divider'] ?? false );
		$merged['popout_header_divider_width'] = max( 0, min( 6, absint( $merged['popout_header_divider_width'] ?? $demo['popout_header_divider_width'] ) ) );
		$merged['popout_body_font']         = sanitize_key( (string) ( $merged['popout_body_font'] ?? $demo['popout_body_font'] ) );
		$merged['popout_body_font_size']    = max( 0, min( 24, absint( $merged['popout_body_font_size'] ?? $demo['popout_body_font_size'] ) ) );

		return $merged;
	}

	/**
	 * @param array<string, mixed> $raw Raw payload fragment.
	 * @return bool
	 */
	private static function looks_like_block_attributes( array $raw ) {
		if ( isset( $raw['general'] ) || isset( $raw['layout'] ) || isset( $raw['popouts'] ) ) {
			return false;
		}

		return isset( $raw['features'] ) && is_array( $raw['features'] );
	}

	/**
	 * @param array<string, mixed> $config Sanitized config.
	 * @return array<string, mixed>
	 */
	public static function enrich_export_media( array $config ) {
		if ( ! empty( $config['general']['features'] ) && is_array( $config['general']['features'] ) ) {
			foreach ( $config['general']['features'] as $index => $feature ) {
				if ( ! is_array( $feature ) || empty( $feature['title_image'] ) ) {
					continue;
				}
				$url = Rsmspark_Content_Widgets_Widget_Features::media_url( $feature['title_image'] );
				if ( $url ) {
					$config['general']['features'][ $index ]['title_image_src'] = (string) $url;
				}
			}
		}

		if ( ! empty( $config['popouts']['popout_items'] ) && is_array( $config['popouts']['popout_items'] ) ) {
			foreach ( $config['popouts']['popout_items'] as $index => $item ) {
				if ( ! is_array( $item ) || empty( $item['popout_image'] ) ) {
					continue;
				}
				$url = Rsmspark_Content_Widgets_Widget_Features::media_url( $item['popout_image'] );
				if ( $url ) {
					$config['popouts']['popout_items'][ $index ]['popout_image_src'] = (string) $url;
				}
			}
		}

		return $config;
	}

	/**
	 * @param array<string, mixed> $config Features config or SO instance.
	 * @param string               $label  Export label.
	 * @return array<string, mixed>
	 */
	public static function build_export_payload( array $config, $label = '' ) {
		$config = self::from_siteorigin_instance( $config );
		$config = self::enrich_export_media( $config );

		if ( '' === trim( $label ) ) {
			$label = (string) ( $config['general']['title'] ?? '' );
		}
		if ( '' === trim( $label ) ) {
			$label = __( 'Features', 'rsm-content-widgets' );
		}

		return array(
			'plugin'      => self::EXPORT_PLUGIN,
			'widget'      => self::EXPORT_WIDGET,
			'version'     => RSMSPARK_CONTENT_WIDGETS_VERSION,
			'exported_at' => gmdate( DATE_ATOM ),
			'label'       => sanitize_text_field( $label ),
			'config'      => $config,
		);
	}

	/**
	 * @param array<string, mixed> $payload Decoded export payload.
	 * @return array<string, mixed>|null
	 */
	public static function extract_config_from_payload( array $payload ) {
		$plugin = (string) ( $payload['plugin'] ?? '' );

		if (
			self::EXPORT_PLUGIN === $plugin
			&& self::EXPORT_WIDGET === sanitize_key( (string) ( $payload['widget'] ?? '' ) )
			&& is_array( $payload['config'] ?? null )
		) {
			return $payload['config'];
		}

		if (
			self::EXPORT_WIDGET === sanitize_key( (string) ( $payload['widget'] ?? '' ) )
			&& is_array( $payload['config'] ?? null )
		) {
			return $payload['config'];
		}

		if (
			self::EXPORT_PLUGIN === $plugin
			&& self::EXPORT_WIDGET === sanitize_key( (string) ( $payload['block'] ?? '' ) )
			&& is_array( $payload['attributes'] ?? null )
		) {
			return $payload['attributes'];
		}

		if (
			self::EXPORT_WIDGET === sanitize_key( (string) ( $payload['block'] ?? '' ) )
			&& is_array( $payload['attributes'] ?? null )
		) {
			return $payload['attributes'];
		}

		if ( self::looks_like_siteorigin_instance( $payload ) ) {
			return $payload;
		}

		return null;
	}

	/**
	 * @param array<string, mixed> $payload Payload fragment.
	 * @return bool
	 */
	private static function looks_like_siteorigin_instance( array $payload ) {
		return isset( $payload['general'] ) || isset( $payload['layout'] ) || isset( $payload['popouts'] );
	}

	/**
	 * @param mixed $payload Decoded JSON or array.
	 * @return array{config: array<string, mixed>, label: string, attributes: array<string, mixed>}|null
	 */
	public static function parse_import_payload( $payload ) {
		if ( is_string( $payload ) ) {
			$payload = json_decode( $payload, true );
		}

		if ( ! is_array( $payload ) ) {
			return null;
		}

		$config = self::extract_config_from_payload( $payload );
		if ( null === $config ) {
			return null;
		}

		$instance = self::sanitize_instance( $config );

		return array(
			'label'      => sanitize_text_field( (string) ( $payload['label'] ?? '' ) ),
			'config'     => $instance,
			'attributes' => self::to_block_attributes( $instance ),
		);
	}

	/**
	 * @param array<string, mixed> $config  Import config.
	 * @param array<string, mixed> $current Current config.
	 * @return array<string, mixed>
	 */
	public static function merge_config( array $config, array $current = array() ) {
		$config  = self::sanitize_instance( $config );
		$current = self::sanitize_instance( $current );
		$merged  = $current;

		if ( isset( $config['general']['title'] ) ) {
			$merged['general']['title'] = $config['general']['title'];
		}

		if ( array_key_exists( 'features', $config['general'] ) ) {
			$merged['general']['features'] = $config['general']['features'];
		}

		if ( isset( $config['layout'] ) && is_array( $config['layout'] ) ) {
			$merged['layout'] = array_merge( $current['layout'], $config['layout'] );
		}

		if ( isset( $config['design'] ) && is_array( $config['design'] ) ) {
			$merged['design'] = array_merge( $current['design'], $config['design'] );
		}

		if ( isset( $config['popouts'] ) && is_array( $config['popouts'] ) ) {
			$merged['popouts'] = array_merge( $current['popouts'], $config['popouts'] );
		}

		if ( array_key_exists( 'popout_items', $config['popouts'] ) ) {
			$merged['popouts']['popout_items'] = $config['popouts']['popout_items'];
		}

		return self::sanitize_instance( $merged );
	}

	/**
	 * @param array<string, mixed> $config Sanitized config.
	 * @return array<string, mixed>
	 */
	public static function to_siteorigin_instance( array $config ) {
		$config = self::sanitize_instance( $config );

		$general_features = array();
		foreach ( $config['general']['features'] as $feature ) {
			if ( ! is_array( $feature ) ) {
				continue;
			}
			$row               = $feature;
			$row['enabled']    = Rsmspark_Content_Widgets_Widget_Features::is_enabled( $feature['enabled'] ?? true );
			$row['popout_hot'] = Rsmspark_Content_Widgets_Features_Popouts::is_enabled( $feature['popout_hot'] ?? false );
			$general_features[] = $row;
		}

		$popouts               = $config['popouts'];
		$popouts['enable_popouts'] = Rsmspark_Content_Widgets_Features_Popouts::is_enabled( $popouts['enable_popouts'] ?? false );

		return array(
			'general' => array(
				'title'    => $config['general']['title'],
				'features' => $general_features,
			),
			'layout'  => $config['layout'],
			'design'  => $config['design'],
			'popouts' => $popouts,
		);
	}

	/**
	 * @param array<string, mixed> $instance Current SO instance.
	 * @param array<string, mixed> $config   Import config.
	 * @return array<string, mixed>
	 */
	public static function merge_siteorigin_instance( array $instance, array $config ) {
		$current = self::from_siteorigin_instance( $instance );
		$merged  = self::merge_config( $config, $current );

		return self::to_siteorigin_instance( $merged );
	}
}
