<?php
/**
 * Bricks UGC Gallery element.
 *
 * @package Ugcify\Bricks\Elements
 */

namespace Ugcify\Bricks\Elements;

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

/**
 * Class UGCGalleryElement
 */
class UGCGalleryElement extends \Bricks\Element {
	public $category = 'general';
	public $name = 'ugcify-gallery';
	public $icon = 'ti-star';
	public $css_selector = '.ugcify-bricks-gallery';

	/**
	 * Return element label.
	 *
	 * @return string
	 */
	public function get_label() {
		return esc_html__( 'UGC Gallery', 'ugcify' );
	}

	/**
	 * Return element keywords.
	 *
	 * @return array
	 */
	public function get_keywords() {
		return array( 'ugcify', 'reviews', 'gallery', 'carousel', 'mosaic', 'testimonial' );
	}

	/**
	 * Set builder control groups.
	 *
	 * @return void
	 */
	public function set_control_groups() {
		$this->control_groups['template'] = array(
			'title' => esc_html__( 'Template', 'ugcify' ),
			'tab'   => 'content',
		);
		$this->control_groups['filters'] = array(
			'title' => esc_html__( 'Review Filters', 'ugcify' ),
			'tab'   => 'content',
		);
		$this->control_groups['header'] = array(
			'title' => esc_html__( 'Header Area', 'ugcify' ),
			'tab'   => 'content',
		);
		$this->control_groups['review'] = array(
			'title' => esc_html__( 'Review Section', 'ugcify' ),
			'tab'   => 'content',
		);
		$this->control_groups['media'] = array(
			'title' => esc_html__( 'Media Behavior', 'ugcify' ),
			'tab'   => 'content',
		);
		$this->control_groups['actions'] = array(
			'title' => esc_html__( 'Shoppable Tags', 'ugcify' ),
			'tab'   => 'content',
		);
		$this->control_groups['colors'] = array(
			'title' => esc_html__( 'Colors and Styles', 'ugcify' ),
			'tab'   => 'style',
		);
		$this->control_groups['advanced'] = array(
			'title' => esc_html__( 'Advanced', 'ugcify' ),
			'tab'   => 'style',
		);
	}

	/**
	 * Set builder controls.
	 *
	 * @return void
	 */
	public function set_controls() {
		$this->controls['blockTemplate'] = array(
			'tab'         => 'content',
			'group'       => 'template',
			'label'       => esc_html__( 'Apply Template', 'ugcify' ),
			'type'        => 'select',
			'options'     => array(
				'minimal_gallery'      => esc_html__( 'Minimal Gallery', 'ugcify' ),
				'reels'                => esc_html__( 'Reels', 'ugcify' ),
				'carousel'             => esc_html__( 'Attachment Carousel Template', 'ugcify' ),
				'card_carousel'        => esc_html__( 'Card Carousel', 'ugcify' ),
				'media_mosaic'         => esc_html__( 'Media Mosaic', 'ugcify' ),
				'testimonial_carousel' => esc_html__( 'Testimonial Carousel', 'ugcify' ),
			),
			'default'     => 'minimal_gallery',
			'inline'      => true,
			'clearable'   => false,
			'pasteStyles' => false,
		);

		$this->controls['minimalWidgetType'] = array(
			'tab'         => 'content',
			'group'       => 'template',
			'label'       => esc_html__( 'Widget Type', 'ugcify' ),
			'type'        => 'select',
			'options'     => array(
				'grid'    => esc_html__( 'Grid', 'ugcify' ),
				'masonry' => esc_html__( 'Masonry', 'ugcify' ),
				'slider'  => esc_html__( 'Slider', 'ugcify' ),
			),
			'default'     => 'grid',
			'inline'      => true,
			'clearable'   => false,
			'pasteStyles' => false,
			'required'    => array( 'blockTemplate', '=', 'minimal_gallery' ),
		);

		$this->add_text_control( 'productId', 'filters', esc_html__( 'Product ID', 'ugcify' ), '' );
		$this->add_text_control( 'categories', 'filters', esc_html__( 'Categories', 'ugcify' ), '' );
		$this->add_text_control( 'tags', 'filters', esc_html__( 'Tags', 'ugcify' ), '' );

		$this->add_checkbox_control( 'showHeaderTitle', 'header', esc_html__( 'Show Header Title', 'ugcify' ), true );
		$this->add_text_control( 'title', 'header', esc_html__( 'Title', 'ugcify' ), 'Customers are saying' );
		$this->add_select_control( 'titleFontWeight', 'header', esc_html__( 'Title Font Weight', 'ugcify' ), array( '400' => '400', '500' => '500', '600' => '600', '700' => '700' ), '600' );
		$this->add_select_control( 'titleFontSize', 'header', esc_html__( 'Title Font Size', 'ugcify' ), $this->get_size_options(), 'medium' );
		$this->add_text_control( 'emptyReviewText', 'header', esc_html__( 'Empty Review Text', 'ugcify' ), 'No customer review yet. Be the first to review!' );

		$this->add_checkbox_control( 'showMediaCarousel', 'review', esc_html__( 'Show Carousel', 'ugcify' ), true, array( 'blockTemplate', '=', 'carousel' ) );
		$this->add_number_control( 'mediaCarouselItemsToShow', 'review', esc_html__( 'Items to Show', 'ugcify' ), 10, 1, 100, array( 'blockTemplate', '=', 'carousel' ) );
		$this->add_select_control( 'mediaMosaicStyle', 'review', esc_html__( 'Style', 'ugcify' ), array( 'grid' => esc_html__( 'Grid', 'ugcify' ), 'masonry' => esc_html__( 'Masonry', 'ugcify' ), 'slider' => esc_html__( 'Slider', 'ugcify' ) ), 'grid', array( 'blockTemplate', '=', 'media_mosaic' ) );
		$this->add_checkbox_control( 'showReviews', 'review', esc_html__( 'Show Reviews', 'ugcify' ), true );
		$this->add_select_control( 'reviewerNameFormat', 'review', esc_html__( 'Reviewer Name Format', 'ugcify' ), array( 'full' => esc_html__( 'Full', 'ugcify' ), 'first_last_initial' => esc_html__( 'First + Last Initial', 'ugcify' ), 'first_only' => esc_html__( 'First Only', 'ugcify' ), 'initials' => esc_html__( 'Initials', 'ugcify' ) ), 'full' );
		$this->add_select_control( 'reviewerNameFontSize', 'review', esc_html__( 'Reviewer Name Font Size', 'ugcify' ), $this->get_size_options(), 'medium' );
		$this->add_checkbox_control( 'showCustomerAvatar', 'review', esc_html__( 'Show Customer Avatar', 'ugcify' ), true, array( 'blockTemplate', '=', 'media_mosaic' ) );
		$this->add_select_control( 'testimonialQuoteSize', 'review', esc_html__( 'Quote Icon Size', 'ugcify' ), $this->get_size_options(), 'medium', array( 'blockTemplate', '=', 'testimonial_carousel' ) );
		$this->add_color_control( 'testimonialQuoteColor', 'review', esc_html__( 'Quote Icon Color', 'ugcify' ), '#322EFE', 'content', array( 'blockTemplate', '=', 'testimonial_carousel' ) );
		$this->add_number_control( 'testimonialQuoteOpacity', 'review', esc_html__( 'Quote Icon Opacity', 'ugcify' ), 100, 0, 100, array( 'blockTemplate', '=', 'testimonial_carousel' ) );
		$this->add_checkbox_control( 'showVerifiedCheck', 'review', esc_html__( 'Show Verified Check', 'ugcify' ), true );
		$this->add_checkbox_control( 'showInfluencerBadge', 'review', esc_html__( 'Show Influencer Badge', 'ugcify' ), true );
		$this->add_select_control( 'reviewDateFormat', 'review', esc_html__( 'Review Date Format', 'ugcify' ), array( 'd M, Y' => '12 Dec, 2025', 'M d, Y' => 'Dec 12, 2025', 'd/m/Y' => '12/12/2025', 'Y-m-d' => '2025-12-12' ), 'd M, Y' );
		$this->add_select_control( 'starRatingSize', 'review', esc_html__( 'Star Rating Size', 'ugcify' ), $this->get_size_options(), 'medium' );
		$this->add_select_control( 'reviewTextSize', 'review', esc_html__( 'Review Text Size', 'ugcify' ), $this->get_size_options(), 'medium' );
		$this->add_select_control( 'reviewTextLength', 'review', esc_html__( 'Review Text Length', 'ugcify' ), array_merge( $this->get_size_options(), array( 'full' => esc_html__( 'Full', 'ugcify' ) ) ), 'large' );
		$this->add_number_control( 'reviewCardBorderRadius', 'review', esc_html__( 'Review Card Border Radius', 'ugcify' ), 10, 0, 100, array( 'blockTemplate', '!=', 'carousel' ) );
		$this->add_select_control( 'reviewColumn', 'review', esc_html__( 'Review Columns', 'ugcify' ), array( '1' => '1', '2' => '2', '3' => '3', '4' => '4' ), '3', array( 'blockTemplate', '!=', 'carousel' ) );
		$this->add_number_control( 'reviewsPerPage', 'review', esc_html__( 'Reviews Per Page', 'ugcify' ), 3, 1, 50 );
		$this->add_checkbox_control( 'showLoadMoreButton', 'review', esc_html__( 'Show Load More Button', 'ugcify' ), true );
		$this->add_select_control( 'loadMoreTextSize', 'review', esc_html__( 'Load More Text Size', 'ugcify' ), $this->get_size_options(), 'medium' );
		$this->add_number_control( 'loadMoreBorderRadius', 'review', esc_html__( 'Load More Border Radius', 'ugcify' ), 10, 0, 100 );

		$this->add_checkbox_control( 'lazyLoadImages', 'media', esc_html__( 'Lazy Load Images', 'ugcify' ), true );
		$this->add_checkbox_control( 'autoplayVideo', 'media', esc_html__( 'Autoplay Video (Muted)', 'ugcify' ), false );
		$this->add_checkbox_control( 'enableLightbox', 'media', esc_html__( 'Enable Lightbox', 'ugcify' ), true );
		$this->add_checkbox_control( 'directAddToCart', 'actions', esc_html__( 'Direct Add-to-Cart', 'ugcify' ), true );

		foreach ( $this->get_color_defaults() as $key => $data ) {
			$this->add_color_control( $key, 'colors', $data['label'], $data['default'] );
		}

		$this->controls['customCSS'] = array(
			'tab'     => 'style',
			'group'   => 'advanced',
			'label'   => esc_html__( 'Custom CSS', 'ugcify' ),
			'type'    => 'textarea',
			'default' => '',
		);
	}

	/**
	 * Render element.
	 *
	 * @return void
	 */
	public function render() {
		if ( ! shortcode_exists( 'ugcify_reviews' ) ) {
			return;
		}

		$this->enqueue_runtime_assets();
		$this->set_attribute( '_root', 'class', 'ugcify-bricks-gallery' );
		$this->set_attribute( '_root', 'style', 'display:block;width:100%;max-width:100%;' );

		echo '<div ' . $this->render_attributes( '_root' ) . '>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
		echo $this->get_runtime_style_link(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
		echo do_shortcode( $this->build_shortcode() ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
		echo '</div>';
	}

	/**
	 * Ensure frontend runtime assets are available in Bricks canvas/output.
	 *
	 * @return void
	 */
	private function enqueue_runtime_assets() {
		static $done = false;
		if ( $done ) {
			return;
		}

		$done = true;
		$script_file       = UGCIFY_PATH . 'assets/frontend/app.js';
		$script_asset_file = UGCIFY_PATH . 'assets/frontend/app.asset.php';
		$script_asset      = array(
			'dependencies' => array( 'jquery', 'wp-i18n' ),
			'version'      => file_exists( $script_file ) ? (string) filemtime( $script_file ) : UGCIFY_VERSION,
		);
		if ( file_exists( $script_asset_file ) ) {
			$loaded_asset = require $script_asset_file;
			if ( is_array( $loaded_asset ) ) {
				$script_asset = array_merge( $script_asset, $loaded_asset );
			}
		}
		$script_asset['dependencies'] = array_values(
			array_unique(
				array_merge(
					array( 'jquery', 'wp-i18n' ),
					isset( $script_asset['dependencies'] ) && is_array( $script_asset['dependencies'] ) ? $script_asset['dependencies'] : array()
				)
			)
		);

		wp_enqueue_style( 'ugcify-frontend', UGCIFY_URL . 'assets/frontend/styles.css', array(), $this->get_runtime_style_version() );
		wp_enqueue_script( 'ugcify-frontend', UGCIFY_URL . 'assets/frontend/app.js', $script_asset['dependencies'], $script_asset['version'], true );

		wp_localize_script(
			'ugcify-frontend',
			'ugcCommerce',
			array(
				'apiUrl'           => rest_url( 'ugcify/v1' ),
				'ajaxUrl'          => admin_url( 'admin-ajax.php' ),
				'nonce'            => wp_create_nonce( 'wp_rest' ),
				'pluginUrl'        => UGCIFY_URL,
				'productId'        => get_the_ID(),
				'perPage'          => apply_filters( 'ugcify_reviews_per_page', 3 ),
				'locale'           => str_replace( '_', '-', get_locale() ),
				'gmtOffset'        => (float) get_option( 'gmt_offset', 0 ),
				'wcCartRedirect'   => 'yes' === get_option( 'woocommerce_cart_redirect_after_add', 'no' ),
				'wcCartUrl'        => function_exists( 'wc_get_cart_url' ) ? wc_get_cart_url() : '',
				'i18n'             => array(
					'guest'                => __( 'Guest', 'ugcify' ),
					'reviewMediaAlt'       => __( 'Review Media', 'ugcify' ),
					'errorLoadingReview'   => __( 'Error loading review. Please try again.', 'ugcify' ),
					'failedFetchReview'    => __( 'Failed to fetch review', 'ugcify' ),
					'failedFetchReviewIds' => __( 'Failed to fetch review ids', 'ugcify' ),
					'addingToCart'         => __( 'Adding...', 'ugcify' ),
					'addedToCart'          => __( 'Added', 'ugcify' ),
					'addToCartError'       => __( 'Try Again', 'ugcify' ),
					'readMore'             => __( 'Read More', 'ugcify' ),
					'readLess'             => __( 'Read less', 'ugcify' ),
				),
			)
		);
	}

	/**
	 * Return stylesheet link fallback for builders that render after wp_head.
	 *
	 * @return string
	 */
	private function get_runtime_style_link() {
		static $printed = false;
		if ( $printed || wp_style_is( 'ugcify-frontend', 'done' ) ) {
			return '';
		}

		$printed = true;

		return sprintf(
			'<link rel="stylesheet" id="ugcify-bricks-runtime-css" href="%1$s" media="all" />',
			esc_url( UGCIFY_URL . 'assets/frontend/styles.css?ver=' . rawurlencode( $this->get_runtime_style_version() ) )
		);
	}

	/**
	 * Get frontend stylesheet build version.
	 *
	 * @return string
	 */
	private function get_runtime_style_version() {
		$style_file       = UGCIFY_PATH . 'assets/frontend/styles.css';
		$style_asset_file = UGCIFY_PATH . 'assets/frontend/styles.asset.php';
		$version          = file_exists( $style_file ) ? (string) filemtime( $style_file ) : UGCIFY_VERSION;

		if ( file_exists( $style_asset_file ) ) {
			$style_asset = require $style_asset_file;
			if ( is_array( $style_asset ) && isset( $style_asset['version'] ) ) {
				$version = (string) $style_asset['version'];
			}
		}
		if ( file_exists( $style_file ) ) {
			$version = (string) filemtime( $style_file );
		}

		return $version;
	}

	/**
	 * Build shortcode from Bricks settings.
	 *
	 * @return string
	 */
	private function build_shortcode() {
		$settings = is_array( $this->settings ) ? $this->settings : array();
		$template = $this->resolve_block_template( $settings );
		$widget_type = $this->resolve_widget_type( $template, $settings );

		$atts = array(
			'instance_id'    => 'ugcify-bricks-' . sanitize_html_class( (string) $this->id ),
			'widgetType'     => $widget_type,
			'blockTemplate'  => $template,
			'block_template' => $template,
			'template'       => $template,
		);

		foreach ( $this->get_setting_keys() as $key ) {
			$raw_value = $this->get_setting_value( $settings, $key );
			if ( null === $raw_value ) {
				continue;
			}

			$value = $this->sanitize_setting_value( $key, $raw_value );
			if ( null === $value || '' === $value ) {
				continue;
			}

			$atts[ $key ] = is_bool( $value ) ? ( $value ? '1' : '0' ) : (string) $value;
		}

		$minimal_widget_type = $this->get_setting_value( $settings, 'minimalWidgetType' );
		if ( null !== $minimal_widget_type && 'minimal_gallery' === $template ) {
			$atts['widgetType'] = $this->sanitize_setting_value( 'minimalWidgetType', $minimal_widget_type );
		}

		$product_id = $this->get_setting_value( $settings, 'productId' );
		if ( ! empty( $product_id ) ) {
			$atts['product_id'] = (string) absint( $product_id );
		}
		$categories = $this->get_setting_value( $settings, 'categories' );
		if ( ! empty( $categories ) ) {
			$atts['categories'] = sanitize_text_field( (string) $categories );
		}
		$tags = $this->get_setting_value( $settings, 'tags' );
		if ( ! empty( $tags ) ) {
			$atts['tags'] = sanitize_text_field( (string) $tags );
		}

		$shortcode = '[ugcify_reviews';
		foreach ( $atts as $key => $value ) {
			$shortcode .= sprintf( ' %1$s="%2$s"', sanitize_key( $key ), esc_attr( $value ) );
		}
		$shortcode .= ']';

		return $shortcode;
	}

	/**
	 * Resolve selected block template from Bricks settings.
	 *
	 * @param array $settings Settings.
	 * @return string
	 */
	private function resolve_block_template( $settings ) {
		$template = $this->normalize_key_value( $this->get_setting_value( $settings, 'blockTemplate', '' ) );
		$allowed  = array( 'minimal_gallery', 'reels', 'carousel', 'card_carousel', 'media_mosaic', 'testimonial_carousel' );

		if ( in_array( $template, $allowed, true ) ) {
			return $template;
		}

		$widget_type = $this->normalize_key_value( $this->get_setting_value( $settings, 'widgetType', '' ) );
		if ( 'gallery' === $widget_type ) {
			return 'carousel';
		}
		if ( in_array( $widget_type, array( 'reels', 'card_carousel', 'media_mosaic', 'testimonial_carousel' ), true ) ) {
			return $widget_type;
		}

		return 'minimal_gallery';
	}

	/**
	 * Resolve selected frontend widget type.
	 *
	 * @param string $template Template id.
	 * @param array  $settings Settings.
	 * @return string
	 */
	private function resolve_widget_type( $template, $settings ) {
		if ( 'reels' === $template ) {
			return 'reels';
		}
		if ( 'carousel' === $template ) {
			return 'gallery';
		}
		if ( in_array( $template, array( 'card_carousel', 'media_mosaic', 'testimonial_carousel' ), true ) ) {
			return $template;
		}

		$value = $this->normalize_key_value( $this->get_setting_value( $settings, 'minimalWidgetType', 'grid' ) );
		return in_array( $value, array( 'grid', 'masonry', 'slider' ), true ) ? $value : 'grid';
	}

	/**
	 * Normalize scalar or structured builder select values to a key.
	 *
	 * @param mixed $value Raw value.
	 * @return string
	 */
	private function normalize_key_value( $value ) {
		if ( is_array( $value ) ) {
			foreach ( array( 'value', 'id', 'key', 'name' ) as $array_key ) {
				if ( isset( $value[ $array_key ] ) && is_scalar( $value[ $array_key ] ) ) {
					return sanitize_key( (string) $value[ $array_key ] );
				}
			}

			return '';
		}

		return is_scalar( $value ) ? sanitize_key( (string) $value ) : '';
	}

	/**
	 * Resolve a setting value using canonical, lower-case, and snake-case keys.
	 *
	 * @param array  $settings Settings.
	 * @param string $key      Canonical key.
	 * @param mixed  $default  Default value.
	 * @return mixed
	 */
	private function get_setting_value( $settings, $key, $default = null ) {
		foreach ( $this->get_setting_aliases( $key ) as $alias ) {
			if ( array_key_exists( $alias, $settings ) ) {
				return $settings[ $alias ];
			}
		}

		return $default;
	}

	/**
	 * Get setting aliases for a canonical key.
	 *
	 * @param string $key Canonical key.
	 * @return array
	 */
	private function get_setting_aliases( $key ) {
		$aliases = array(
			$key,
			strtolower( $key ),
			strtolower( preg_replace( '/([a-z])([A-Z])/', '$1_$2', $key ) ),
		);

		if ( 'blockTemplate' === $key ) {
			$aliases[] = 'template';
		}

		return array_values( array_unique( array_filter( $aliases ) ) );
	}

	/**
	 * Add text control.
	 *
	 * @param string $key Key.
	 * @param string $group Group.
	 * @param string $label Label.
	 * @param string $default Default.
	 * @return void
	 */
	private function add_text_control( $key, $group, $label, $default = '', $required = null ) {
		$control = array(
			'tab'     => 'content',
			'group'   => $group,
			'label'   => $label,
			'type'    => 'text',
			'default' => $default,
		);
		$this->controls[ $key ] = $this->with_required( $control, $required );
	}

	/**
	 * Add select control.
	 *
	 * @param string $key Key.
	 * @param string $group Group.
	 * @param string $label Label.
	 * @param array  $options Options.
	 * @param string $default Default.
	 * @return void
	 */
	private function add_select_control( $key, $group, $label, $options, $default, $required = null ) {
		$control = array(
			'tab'         => 'content',
			'group'       => $group,
			'label'       => $label,
			'type'        => 'select',
			'options'     => $options,
			'default'     => $default,
			'inline'      => true,
			'clearable'   => false,
			'pasteStyles' => false,
		);
		$this->controls[ $key ] = $this->with_required( $control, $required );
	}

	/**
	 * Add checkbox control.
	 *
	 * @param string $key Key.
	 * @param string $group Group.
	 * @param string $label Label.
	 * @param bool   $default Default.
	 * @return void
	 */
	private function add_checkbox_control( $key, $group, $label, $default, $required = null ) {
		$control = array(
			'tab'     => 'content',
			'group'   => $group,
			'label'   => $label,
			'type'    => 'checkbox',
			'default' => $default,
		);
		$this->controls[ $key ] = $this->with_required( $control, $required );
	}

	/**
	 * Add number control.
	 *
	 * @param string $key Key.
	 * @param string $group Group.
	 * @param string $label Label.
	 * @param int    $default Default.
	 * @param int    $min Min.
	 * @param int    $max Max.
	 * @return void
	 */
	private function add_number_control( $key, $group, $label, $default, $min, $max, $required = null ) {
		$control = array(
			'tab'     => 'content',
			'group'   => $group,
			'label'   => $label,
			'type'    => 'number',
			'min'     => $min,
			'max'     => $max,
			'default' => $default,
		);
		$this->controls[ $key ] = $this->with_required( $control, $required );
	}

	/**
	 * Add color control.
	 *
	 * @param string $key Key.
	 * @param string $group Group.
	 * @param string $label Label.
	 * @param string $default Default.
	 * @return void
	 */
	private function add_color_control( $key, $group, $label, $default, $tab = 'style', $required = null ) {
		$control = array(
			'tab'     => $tab,
			'group'   => $group,
			'label'   => $label,
			'type'    => 'color',
			'default' => array( 'hex' => $default ),
		);
		$this->controls[ $key ] = $this->with_required( $control, $required );
	}

	/**
	 * Add Bricks visibility requirement to a control.
	 *
	 * @param array      $control Control definition.
	 * @param array|null $required Required condition.
	 * @return array
	 */
	private function with_required( $control, $required = null ) {
		if ( is_array( $required ) && ! empty( $required ) ) {
			$control['required'] = $required;
		}

		return $control;
	}

	/**
	 * Get common size options.
	 *
	 * @return array
	 */
	private function get_size_options() {
		return array(
			'small'  => esc_html__( 'Small', 'ugcify' ),
			'medium' => esc_html__( 'Medium', 'ugcify' ),
			'large'  => esc_html__( 'Large', 'ugcify' ),
		);
	}

	/**
	 * Get color defaults.
	 *
	 * @return array
	 */
	private function get_color_defaults() {
		return array(
			'primaryColor'        => array( 'label' => esc_html__( 'Primary Color', 'ugcify' ), 'default' => '#201CFE' ),
			'titleColor'          => array( 'label' => esc_html__( 'Title Color', 'ugcify' ), 'default' => '#000000' ),
			'bodyFontColor'       => array( 'label' => esc_html__( 'Body Font Color', 'ugcify' ), 'default' => '#444444' ),
			'cardBgColor'         => array( 'label' => esc_html__( 'Card Background Color', 'ugcify' ), 'default' => '#FFFFFF' ),
			'ratingColor'         => array( 'label' => esc_html__( 'Rating Color', 'ugcify' ), 'default' => '#FFA800' ),
			'buttonTextColor'     => array( 'label' => esc_html__( 'Button Text Color', 'ugcify' ), 'default' => '#FFFFFF' ),
			'filterFillColor'     => array( 'label' => esc_html__( 'Filter Fill Color', 'ugcify' ), 'default' => '#FFFFFF' ),
			'filterStrokeColor'   => array( 'label' => esc_html__( 'Filter Stroke Color', 'ugcify' ), 'default' => '#201CFE' ),
			'filterIconColor'     => array( 'label' => esc_html__( 'Filter Icon Color', 'ugcify' ), 'default' => '#292D32' ),
			'readMoreColor'       => array( 'label' => esc_html__( 'Read More Color', 'ugcify' ), 'default' => '#000000' ),
			'loadMoreTextColor'   => array( 'label' => esc_html__( 'Load More Text Color', 'ugcify' ), 'default' => '#201CFE' ),
			'loadMoreBgColor'     => array( 'label' => esc_html__( 'Load More Background Color', 'ugcify' ), 'default' => '#FFFFFF' ),
			'loadMoreBorderColor' => array( 'label' => esc_html__( 'Load More Border Color', 'ugcify' ), 'default' => '#201CFE' ),
		);
	}

	/**
	 * Get setting keys passed to shortcode.
	 *
	 * @return array
	 */
	private function get_setting_keys() {
		return array(
			'showHeaderTitle',
			'title',
			'titleFontWeight',
			'titleFontSize',
			'emptyReviewText',
			'showMediaCarousel',
			'mediaCarouselItemsToShow',
			'mediaMosaicStyle',
			'showReviews',
			'reviewerNameFormat',
			'reviewerNameFontSize',
			'showCustomerAvatar',
			'testimonialQuoteSize',
			'testimonialQuoteColor',
			'testimonialQuoteOpacity',
			'showVerifiedCheck',
			'showInfluencerBadge',
			'reviewDateFormat',
			'starRatingSize',
			'reviewTextSize',
			'reviewTextLength',
			'reviewCardBorderRadius',
			'reviewColumn',
			'reviewsPerPage',
			'showLoadMoreButton',
			'loadMoreTextSize',
			'loadMoreBorderRadius',
			'lazyLoadImages',
			'autoplayVideo',
			'enableLightbox',
			'directAddToCart',
			'customCSS',
			'primaryColor',
			'titleColor',
			'bodyFontColor',
			'cardBgColor',
			'ratingColor',
			'buttonTextColor',
			'filterFillColor',
			'filterStrokeColor',
			'filterIconColor',
			'readMoreColor',
			'loadMoreTextColor',
			'loadMoreBgColor',
			'loadMoreBorderColor',
		);
	}

	/**
	 * Sanitize setting value.
	 *
	 * @param string $key Key.
	 * @param mixed  $value Value.
	 * @return mixed
	 */
	private function sanitize_setting_value( $key, $value ) {
		if ( is_array( $value ) && isset( $value['hex'] ) ) {
			$value = $value['hex'];
		} elseif ( is_array( $value ) ) {
			foreach ( array( 'value', 'id', 'key', 'name' ) as $array_key ) {
				if ( isset( $value[ $array_key ] ) && is_scalar( $value[ $array_key ] ) ) {
					$value = $value[ $array_key ];
					break;
				}
			}
			if ( is_array( $value ) ) {
				$value = '';
			}
		}

		$bool_keys = array( 'showHeaderTitle', 'showMediaCarousel', 'showReviews', 'showCustomerAvatar', 'showVerifiedCheck', 'showInfluencerBadge', 'showLoadMoreButton', 'lazyLoadImages', 'autoplayVideo', 'enableLightbox', 'directAddToCart' );
		if ( in_array( $key, $bool_keys, true ) ) {
			return filter_var( $value, FILTER_VALIDATE_BOOLEAN );
		}

		$color_keys = array_keys( $this->get_color_defaults() );
		$color_keys[] = 'testimonialQuoteColor';
		if ( in_array( $key, $color_keys, true ) ) {
			$color = sanitize_hex_color( (string) $value );
			return $color ? $color : null;
		}

		$size_keys = array( 'titleFontSize', 'reviewerNameFontSize', 'testimonialQuoteSize', 'starRatingSize', 'reviewTextSize', 'loadMoreTextSize' );
		if ( in_array( $key, $size_keys, true ) ) {
			return in_array( $value, array( 'small', 'medium', 'large' ), true ) ? $value : 'medium';
		}

		if ( 'testimonialQuoteOpacity' === $key ) {
			return (string) min( 1, max( 0, (float) $value / 100 ) );
		}

		return sanitize_text_field( (string) $value );
	}
}
