<?php
declare( strict_types=1 );

namespace FiboFilters\Integrations\Themes;

use FiboFilters\Config\Env;
use FiboFilters\Integrations\Themes\Avada\FiboFiltersShortcodes;
use FiboFilters\Util\Helpers;

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

/**
 * Class Astra
 */
class Avada extends AbstractTheme {

	/**
	 * @var string
	 */
	private string $filter_price_type = '';

	public function init( string $slug = '', string $name = '', array $args = [] ): void {
		parent::init( $slug, $name, $args );

		add_action(
			'awb_init_elements',
			function () {

				if ( fusion_is_element_enabled( 'fusion_woo_shortcodes' ) && class_exists( 'WooCommerce' ) ) {
					require_once Env::$path . '/lib/Integrations/Themes/Avada/FiboFiltersShortcodes.php';
					new FiboFiltersShortcodes();
				}

				add_action( 'fusion_builder_before_init', [ $this, 'register_avada_element' ] );
			}
		);

		$this->change_enable_integration_field_desc();

		if ( $this->is_integration_enabled() ) {
			add_filter( 'fibofilters/request/context_and_query_vars', [ $this,'support_page_with_fusion_woo_product_grid' ], 10, 2 );
			add_filter( 'fibofilters/request/context_and_query_vars', [ $this,'support_shop_page_with_fusion_post_cards' ], 10, 2 );
			add_filter( 'fibofilters/request/context_and_query_vars', [ $this,'support_custom_page_with_fusion_post_cards' ], 10, 2 );

			add_filter( 'fusion_builder_element_params', [ $this, 'add_fibofilters_switch_to_fusion_woo_product_grid_widget' ], 10, 2 );
			add_filter( 'fusion_builder_element_params', [ $this, 'add_fibofilters_switch_to_fusion_post_cards_widget' ], 10, 2 );

			add_action(
				'pre_get_posts',
				function ( \WP_Query $query ) {
					$filtered_products_ids = apply_filters( 'fibofilters/request/filtered_product_ids', [] );

					if ( ! empty( $filtered_products_ids ) && Helpers::is_running_inside_class( 'FusionSC_PostCards', 20 ) ) {
						if ( $this->filter_price_type ) {
							$filtered_products_ids = $this->filter_by_price_type( $filtered_products_ids );
						}

						$query->set( 'post__in', $filtered_products_ids );
					}
				}
			);
		}
	}

	/**
	 * Adds extra description for the "Enable integration" option
	 */
	protected function change_enable_integration_field_desc(): void {
		add_filter(
			'fibofilters/settings/section=general',
			function ( array $settings ): array {

				$doc_url_1              = esc_url( Env::$doc_url . 'themes-integrations/avada-theme/' );
				$doc_url_2              = esc_url( Env::$doc_url . 'how-it-works/horizontal-filters/' );
				$avada_layouts_internal = esc_url( admin_url( 'admin.php?page=avada-layouts#' ) );

				// Filter location.
				/* translators: %s: name of the theme */
				$settings[200]['description'] = sprintf( _x( 'Filters can be displayed in these modes in the <b>%s</b> theme:', '[admin]', 'fibofilters' ), $this->name );

				// Filter location - Sidebar.
				$settings[250]['options'][0]['label'] = _x( 'Sidebar (by Avada Layout Builder)', '[admin]', 'fibofilters' );

				/* translators: %s: name of the theme */
				$html  = '<p>' . sprintf( _x( 'When your <a href="%s" target="_blank">Avada layouts</a> are finished and you want to add filters in your grid, follow these steps:', '[admin]', 'fibofilters' ), $avada_layouts_internal ) . '</p>';
				$html .= '<ol>';
				$html .= '<li>' . _x( 'Edit Avada layout sections that display products e.g. shop, product archives and so on.', '[admin]', 'fibofilters' ) . '</li>';
				$html .= '<li>' . _x( 'Scroll down to the "<b>Layout Section Options</b>" section and click the "<b>Sidebar</b>" tab.', '[admin]', 'fibofilters' ) . '</li>';
				$html .= '<li>' . _x( 'In the "<b>Select Sidebar 1</b>" option choose the widget area you want to use to display widgets in the sidebar.', '[admin]', 'fibofilters' ) . '</li>';
				$html .= '<li>' . _x( 'Save the layout settings by clicking the "Update" button.', '[admin]', 'fibofilters' ) . '</li>';
				$html .= '<li>' . sprintf( _x( 'Go to <code><a href="%s" target="_blank">Appearance -> Widgets</a></code>.', '[admin]', 'fibofilters' ), $this->get_widgets_link() ) . '</li>';
				$html .= '<li>' . _x( 'Add a widget called "<b>FiboFilters - product filters</b>" to the widget area you selected in the step 3.', '[admin]', 'fibofilters' ) . '</li>';
				$html .= '</ol>';

				$html .= '<p>';
				$html .= sprintf( _x( 'Learn more about embedding filters in Avada Builder in <a href="%s" target="_blank">our documentation</a>. ', '[admin]', 'fibofilters' ), $doc_url_1 );
				$html .= '</p>';

				$settings[260]['html'] = $html;

				// Filter location - Above products.
				$settings[250]['options'][1]['label'] = _x( 'Above the products', '[admin]', 'fibofilters' );

				$html  = '<p>';
				$html .= _x( 'Filters will be displayed above the <b>Woo Archives</b> or <b>Woo Product Grid</b> elements of the Avada Builder.', '[admin]', 'fibofilters' ) . ' ';
				/* translators: 1: Plugin documentation URL */
				$html                 .= sprintf( _x( 'This positioning forces a <a href="%s" target="_blank">horizontal layout</a>.', '[admin]', 'fibofilters' ), $doc_url_2 );
				$html                 .= ' ' . _x( 'There is no need to add filters via Avada Builder. Filters will be added automatically.', '[admin]', 'fibofilters' );
				$html                 .= '</p>';
				$settings[270]['html'] = $html;

				return $settings;
			},
			15
		);
	}

	/**
	 * Map shortcode to Avada Builder.
	 */
	function register_avada_element() {
		if ( class_exists( 'WooCommerce' ) ) {
			fusion_builder_map(
				[
					'name'                              => esc_attr_x( 'FiboFilters', '[admin]', 'fibofilters' ),
					'shortcode'                         => 'fusion_fibofilters_shortcodes',
					'icon'                              => 'fusiona-filter-by-attributes',
					'admin_enqueue_js'                  => Env::$base_url . '/lib/Integrations/Themes/Avada/fibofilters-shortcodes.js',
					'front_end_custom_settings_view_js' => Env::$base_url . '/lib/Integrations/Themes/Avada/fibofilters-shortcodes-settings.js',
					'help_url'                          => Env::$doc_url . 'themes-integrations/avada-theme/',
					'params'                            => [
						[
							'type'             => 'select',
							'heading'          => esc_attr_x( 'Filters type', '[admin]', 'fibofilters' ),
							'skip_debounce'    => true,
							'param_name'       => 'fusion_fibofilters_shortcodes',
							'value'            => [
								0 => esc_attr_x( 'Vertical filters', '[admin]', 'fibofilters' ),
							],
							'default'          => 0,
							'remove_from_atts' => true,
						],
						[
							'type'        => 'textarea',
							'heading'     => esc_attr_x( 'Shortcode content', '[admin]', 'fibofilters' ),
							'description' => esc_attr_x( 'Shortcode will appear here.', '[admin]', 'fibofilters' ),
							'param_name'  => 'element_content',
							'value'       => '[fibofilters]',
						],
					],
				]
			);
		}
	}

	public function add_fibofilters_switch_to_fusion_woo_product_grid_widget( $params, $shortcode ) {
		if ( $shortcode !== 'fusion_woo_product_grid' ) {
			return $params;
		}

		$params[] = [
			'type'       => 'radio_button_set',
			'heading'    => _x( 'Integrate with FiboFilters', '[admin]', 'fibofilters' ),
			'param_name' => 'fibofilters_integration',
			'default'    => 'no',
			'value'      => [
				'yes' => esc_attr__( 'Yes', 'fusion-builder' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
				'no'  => esc_attr__( 'No', 'fusion-builder' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
			],
			'group'      => esc_html__( 'Extras', 'fusion-builder' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
			'callback'   => [
				'function' => 'fusion_ajax',
				'action'   => 'get_fusion_woo_product_grid',
				'ajax'     => true,
			],
		];

		return $params;
	}

	public function add_fibofilters_switch_to_fusion_post_cards_widget( $params, $shortcode ) {

		if ( $shortcode !== 'fusion_post_cards' ) {
			return $params;
		}

		$params[] = [
			'type'       => 'radio_button_set',
			'heading'    => _x( 'Integrate with FiboFilters', '[admin]', 'fibofilters' ),
			'param_name' => 'fibofilters_integration',
			'default'    => 'no',
			'value'      => [
				'yes' => esc_attr__( 'Yes', 'fusion-builder' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
				'no'  => esc_attr__( 'No', 'fusion-builder' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
			],
			'group'      => esc_html__( 'Extras', 'fusion-builder' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
			'callback'   => [
				'function' => 'fusion_ajax',
				'action'   => 'get_fusion_post_cards',
				'ajax'     => true,
			],
		];

		return $params;
	}

	/**
	 * @param array     $args Context and query vars.
	 * @param \WP_Query $query Main query.
	 */
	public function support_page_with_fusion_woo_product_grid( array $args, \WP_Query $query ): array {
		list ( $context, $query_vars ) = $args;

		// Break early if filters are already displayed.
		if ( $context['show_filters'] ) {
			return $args;
		}

		if ( is_a( $query->queried_object, 'WP_Post' ) && $this->wp_helper->has_shortcode( $query->queried_object->post_content, 'fusion_woo_product_grid' ) ) {
			$shortcodes = $this->wp_helper->get_shortcodes( $query->queried_object->post_content, 'fusion_woo_product_grid' );
			foreach ( $shortcodes as $shortcode ) {
				if ( ! isset( $shortcode['atts']['fibofilters_integration'] ) || $shortcode['atts']['fibofilters_integration'] !== 'yes' ) {
					continue;
				}

				if (
					! method_exists( 'FusionSC_WooProductGrid', 'get_element_defaults' ) ||
					! method_exists( 'FusionBuilder', 'set_shortcode_defaults' )
				) {
					return $args;
				}

				$defaults = \FusionSC_WooProductGrid::get_element_defaults();
				$defaults = \FusionBuilder::set_shortcode_defaults( $defaults, $shortcode['atts'], 'fusion_woo_product_grid' );

				$args = [
					'post_type'      => 'product',
					'posts_per_page' => (int) $defaults['number_posts'],
					'paged'          => $defaults['paged'],
				];

				/**
				 * PART FROM AVADA
				 *
				 * @see \FusionSC_WooProductGrid::query()
				 */
				$args = $this->add_ordering_args( $args, $defaults );
				$args = $this->add_offset_arg( $args, $defaults );

				// Pull products by category.
				if ( 'tag' !== $defaults['pull_by'] ) {
					if ( '' !== $defaults['cat_slug'] && $defaults['cat_slug'] ) {
						$cat_id = $defaults['cat_slug'];
						if ( false !== strpos( $defaults['cat_slug'], ',' ) ) {
							$cat_id = explode( ',', $defaults['cat_slug'] );
						} elseif ( false !== strpos( $defaults['cat_slug'], '|' ) ) {
							$cat_id = explode( '|', $defaults['cat_slug'] );
						}
						$args['tax_query'] = [ // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query
							[
								'taxonomy' => 'product_cat',
								'field'    => 'slug',
								'terms'    => $cat_id,
							],
						];
					}

					if ( '' !== $defaults['exclude_cats'] && $defaults['exclude_cats'] ) {
						$cat_id = $defaults['exclude_cats'];
						if ( false !== strpos( $defaults['exclude_cats'], ',' ) ) {
							$cat_id = explode( ',', $defaults['exclude_cats'] );
						} elseif ( false !== strpos( $defaults['exclude_cats'], '|' ) ) {
							$cat_id = explode( '|', $defaults['exclude_cats'] );
						}
						$args['tax_query'][] = [
							'taxonomy' => 'product_cat',
							'field'    => 'slug',
							'terms'    => $cat_id,
							'operator' => 'NOT IN',
						];
					}
				} else {
					if ( '' !== $defaults['tag_slug'] && $defaults['tag_slug'] ) {
						$cat_id = $defaults['tag_slug'];
						if ( false !== strpos( $defaults['tag_slug'], ',' ) ) {
							$cat_id = explode( ',', $defaults['tag_slug'] );
						} elseif ( false !== strpos( $defaults['tag_slug'], '|' ) ) {
							$cat_id = explode( '|', $defaults['tag_slug'] );
						}
						$args['tax_query'] = [ // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query
							[
								'taxonomy' => 'product_tag',
								'field'    => 'slug',
								'terms'    => $cat_id,
							],
						];
					}

					if ( '' !== $defaults['exclude_tags'] && $defaults['exclude_tags'] ) {
						$cat_id = $defaults['exclude_tags'];
						if ( false !== strpos( $defaults['exclude_tags'], ',' ) ) {
							$cat_id = explode( ',', $defaults['exclude_tags'] );
						} elseif ( false !== strpos( $defaults['exclude_tags'], '|' ) ) {
							$cat_id = explode( '|', $defaults['exclude_tags'] );
						}
						$args['tax_query'][] = [
							'taxonomy' => 'product_tag',
							'field'    => 'slug',
							'terms'    => $cat_id,
							'operator' => 'NOT IN',
						];
					}
				}

				$args['tax_query']['relation'] = 'AND';
				$args                          = $this->add_visibility_filter_arg( $args );

				// If out of stock are set not to show, hide them.
				if ( 'yes' === get_option( 'woocommerce_hide_out_of_stock_items', 'no' ) ) {
					$args = $this->add_stock_filter_arg( $args );
				}
				/**
				 * END OF PART FROM AVADA
				 */

				$args['post_status'] = 'publish';

				$query_vars = $args;

				$context['show_filters'] = true;

				// Woo Product Grid >> General >> Pagination Type: No Pagination.
				if ( ! empty( $defaults['scrolling'] ) && $defaults['scrolling'] === 'no' ) {
					$context['internal']['forced_query_args']                   = [];
					$context['internal']['forced_query_args']['posts_per_page'] = $defaults['number_posts'] ?? 12;
					$context['internal']['forced_query_args']['nopaging']       = false;
				}

				/**
				 * ╭───────────────────────────╮
				 * | Skip main query filtering |
				 * ╰───────────────────────────╯
				 */
				add_filter( 'fibofilters/request/skip_main_query_filtering', '__return_true' );

				/**
				 * ╭───────────────────────────╮
				 * | Config: products per page |
				 * ╰───────────────────────────╯
				 */
				add_filter( 'fibofilters/config/products_per_page', fn() => intval( $defaults['number_posts'] ), 15 );

				/**
				 * ╭─────────────────────────────╮
				 * | Config: pagination selector |
				 * ╰─────────────────────────────╯
				 */
				add_filter( 'fibofilters/config/pagination_selectors', fn() => [ '.woocommerce-pagination' ], 15 );

				// Break after first matching shortcode.
				break;
			}
		}

		return [ $context, $query_vars ];
	}

	/**
	 * Support for shop page with Fusion Post Cards.
	 *
	 * @param array     $args Context and query vars.
	 * @param \WP_Query $query Main query.
	 *
	 * @return array
	 */
	public function support_shop_page_with_fusion_post_cards( array $args, \WP_Query $query ): array {
		list ( $context ) = $args;

		if ( ! $context['show_filters'] && ! $context['conditions']['is_shop'] ) {
			return $args;
		}

		if ( ! is_a( $query->queried_object, 'WP_Post_Type' ) ) {
			return $args;
		}

		$page_id = wc_get_page_id( 'shop' );

		if ( ! $page_id ) {
			return $args;
		}

		$queried_object = get_post( $page_id );

		return $this->support_page_with_fusion_post_cards( $args, $queried_object );
	}

	/**
	 * Support for custom page with Fusion Post Cards.
	 *
	 * @param array     $args Context and query vars.
	 * @param \WP_Query $query Main query.
	 *
	 * @return array
	 */
	public function support_custom_page_with_fusion_post_cards( array $args, \WP_Query $query ): array {
		list ( $context ) = $args;

		$queried_object = $query->queried_object;

		if ( $context['show_filters'] ) {
			return $args;
		}

		return $this->support_page_with_fusion_post_cards( $args, $queried_object );
	}

	private function support_page_with_fusion_post_cards( array $args, $queried_object, $has_template = false ): array {
		list ( $context, $query_vars ) = $args;

		if ( is_a( $queried_object, 'WP_Post' ) && $this->wp_helper->has_shortcode( $queried_object->post_content, 'fusion_post_cards' ) ) {

			$shortcodes = $this->wp_helper->get_shortcodes( $queried_object->post_content, 'fusion_post_cards' );

			foreach ( $shortcodes as $shortcode ) {
				if ( ! isset( $shortcode['atts']['fibofilters_integration'] ) || $shortcode['atts']['fibofilters_integration'] !== 'yes' ) {
					continue;
				}

				if (
					! method_exists( 'FusionSC_PostCards', 'get_element_defaults' ) ||
					! method_exists( 'FusionBuilder', 'set_shortcode_defaults' )
				) {
					return $args;
				}

				/**
				 * ╭─────────────────────────────╮
				 * | Config: post card shortcode |
				 * ╰─────────────────────────────╯
				 */
				$defaults = \FusionSC_PostCards::get_element_defaults();
				$defaults = \FusionBuilder::set_shortcode_defaults( $defaults, $shortcode['atts'], 'fusion_post_cards' );

				if ( ! empty( $defaults['number_posts'] ) && $defaults['number_posts'] !== '0' ) {
					$defaults['number_posts'] = (int) $defaults['number_posts'];
				} elseif ( function_exists( 'awb_get_fusion_settings' ) ) {
					$fusion_settings          = awb_get_fusion_settings();
					$defaults['number_posts'] = (int) $fusion_settings->get( 'woo_items' );
				} else {
					$defaults['number_posts'] = 12;
				}

				$args = [
					'post_type'      => 'product',
					'posts_per_page' => $defaults['number_posts'],
				];

				$args = $this->add_ordering_args( $args, $defaults );
				$args = $this->add_offset_arg( $args, $defaults );

				if ( $defaults['out_of_stock'] === 'exclude' ) {
					$args = $this->add_stock_filter_arg( $args );
				}

				if ( $defaults['show_hidden'] === 'yes' ) {
					$args = $this->add_visibility_filter_arg( $args );
				}

				$args['post_status'] = 'publish';
				$query_vars          = $args;

				$context['show_filters'] = true;

				$forced_args = $this->get_forced_query_args( $defaults );
				if ( ! empty( $forced_args ) ) {
					$context['internal']['forced_query_args'] = $forced_args;
				}

				if ( isset( $defaults['filter_price_type'] ) && $defaults['filter_price_type'] !== 'both' ) {
					$sale_ids                = wc_get_product_ids_on_sale();
					$this->filter_price_type = $defaults['filter_price_type'];

					if ( $defaults['filter_price_type'] === 'sale_price' ) {
						$context['internal']['forced_query_args']['post__in'] = $sale_ids;
					} elseif ( $defaults['filter_price_type'] === 'regular_price' ) {
						$context['internal']['forced_query_args']['post__not_in'] = $sale_ids;
					}
				}

				$single_product_ids = apply_filters( 'fibofilters/request/get_single_product_ids', [] );

				if ( ! empty( $single_product_ids ) ) {
					add_action(
						'pre_get_posts',
						function ( \WP_Query $query ) use ( $single_product_ids ) {
							if ( Helpers::is_running_inside_class( 'FusionSC_PostCards', 20 ) ) {
								$query->set( 'post__in', $single_product_ids );
								$query->set( 'tax_query', [] );
								$query->set( 'meta_query', [] );
								$query->set( 'posts_per_page', -1 );
							}
						}
					);
				}

				add_filter( 'fibofilters/request/single_products/break_early', '__return_true' );

				/*
				* ╭────────────────────────────╮
				* | Products fetching strategy |
				* ╰────────────────────────────╯
				*/
				add_filter( 'fibofilters/config/products_fetching_strategy', fn() => 'page' );

				/**
				 * ╭───────────────────────────╮
				 * | Skip main query filtering |
				 * ╰───────────────────────────╯
				 */
				add_filter( 'fibofilters/request/skip_main_query_filtering', '__return_true' );

				/**
				 * ╭─────────────────────────────╮
				 * | Config: single products URL  |
				 * ╰─────────────────────────────╯
				 */
				if ( ! $has_template ) {
					add_filter( 'fibofilters/config/single_products_fetch_url', fn() => get_permalink( $queried_object->ID ) );
				}

				/**
				 * ╭───────────────────────────╮
				 * | Config: products per page |
				 * ╰───────────────────────────╯
				 */
				add_filter( 'fibofilters/config/products_per_page', fn() => intval( $defaults['number_posts'] ), 15 );

				/**
				 * ╭─────────────────────────────╮
				 * | Config: pagination selector |
				 * ╰─────────────────────────────╯
				 */
				add_filter(
					'fibofilters/config/products_loop_selectors',
					function () {
						return [ '.fusion-grid-posts-cards' ];
					},
				);

				/**
				 * ╭─────────────────────────────╮
				 * | Config: Pagination strategy |
				 * ╰─────────────────────────────╯
				 */
				add_filter(
					'fibofilters/config/pagination_strategy',
					function ( $pagination_strategy ) use ( $defaults ) {

						$shop_pagination = $defaults['scrolling'];

						if ( $shop_pagination === 'pagination' ) {
							$pagination_strategy = 'pagination';
						} elseif ( $shop_pagination === 'infinite' ) {
							$pagination_strategy = 'infinite-scroll';
						}

						return $pagination_strategy;
					}
				);

				/**
				 * ╭────────────────────────────── ╮
				 * | Pagination HTML for infinite  |
				 * | scroll trigger                |
				 * ╰────────────────────────────── ╯
				 */
				add_filter(
					'fusion_post_cards_pagination_html',
					function ( $pagination_html ) use ( $defaults ) {
						if ( $defaults['scrolling'] === 'infinite' ) {
							ob_start();
							do_action( 'fibofilters/front/display_infinite_scroll_trigger' );
							return ob_get_clean();
						}

						return $pagination_html;
					},
					10,
					5
				);

				/**
				 * ╭─────────────────────╮
				 * | Product placeholder |
				 * ╰─────────────────────╯
				 */
				add_filter(
					'fibofilters/request/html/product_placeholder',
					function () {
						ob_start();
						?>
						<li class="post-card fusion-grid-column">
							<div class="fusion-column-wrapper">
								<img src="<?php echo esc_url( wc_placeholder_img_src() ); ?> " alt="Placeholder image"/>
							</div>
						</li>
						<?php
						return (string) ob_get_clean();
					},
					15
				);

				// Break after first matching shortcode.
				break;
			}
		}

		return [ $context, $query_vars ];
	}

	/**
	 * Adds ordering args to the query.
	 *
	 * @param array $args     Query arguments.
	 * @param array $defaults Shortcode defaults.
	 *
	 * @return array
	 */
	private function add_ordering_args( array $args, array $defaults ): array {
		if ( is_shop() && ! empty( $defaults['order'] ) ) {
			add_filter(
				'woocommerce_get_catalog_ordering_args',
				function ( $ordering ) use ( $defaults ) {
					$ordering['order'] = strtoupper( $defaults['order'] );
					return $ordering;
				},
				9999
			);
		}

		$ordering = WC()->query->get_catalog_ordering_args(
			$defaults['orderby'] ?? 'menu_order',
			$defaults['order'] ?? 'asc'
		);

		$args['orderby'] = $ordering['orderby'];
		$args['order']   = $ordering['order'];

		if ( ! empty( $ordering['meta_key'] ) ) {
			$args['meta_key'] = $ordering['meta_key']; // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
		}

		return $args;
	}

	/**
	 * Adds offset argument to the query.
	 *
	 * @param array $args     Query arguments.
	 * @param array $defaults Shortcode defaults.
	 *
	 * @return array
	 */
	private function add_offset_arg( array $args, array $defaults ): array {
		if ( isset( $defaults['offset'] ) && $defaults['offset'] !== '' ) {
			$args['offset'] = (int) $defaults['offset'];
		}
		return $args;
	}

	/**
	 * Returns forced query args based on the defaults.
	 *
	 * @param array $defaults Shortcode defaults.
	 *
	 * @return array
	 */
	private function get_forced_query_args( array $defaults ): array {
		if ( ! empty( $defaults['scrolling'] ) && $defaults['scrolling'] === 'no' ) {
			return [
				'posts_per_page' => (int) ( $defaults['number_posts'] ?? 12 ),
				'nopaging'       => false,
			];
		}

		return [];
	}

	/**
	 * Adds a filter to exclude out-of-stock products.
	 *
	 * @param array $args Query arguments.
	 *
	 * @return array
	 */
	private function add_stock_filter_arg( array $args ): array {
		$args['meta_query'][] = [
			'key'     => '_stock_status',
			'value'   => 'outofstock',
			'compare' => 'NOT IN',
		];

		return $args;
	}

	/**
	 * Adds a filter to exclude products that are not visible in the catalog or search.
	 *
	 * @param array $args Query arguments.
	 *
	 * @return array
	 */
	private function add_visibility_filter_arg( array $args ): array {
		$args['tax_query'][] = [
			'taxonomy' => 'product_visibility',
			'field'    => 'slug',
			'terms'    => [ 'exclude-from-catalog', 'exclude-from-search' ],
			'operator' => 'NOT IN',
		];

		return $args;
	}

	/**
	 * Filters product IDs by price type.
	 *
	 * @param array $product_ids Array of product IDs.
	 *
	 * @return array Filtered product IDs.
	 */
	private function filter_by_price_type( array $product_ids ): array {
		$sale_ids = wc_get_product_ids_on_sale();

		if ( $this->filter_price_type === 'sale_price' ) {
			return array_values( array_intersect( $product_ids, $sale_ids ) );
		}

		if ( $this->filter_price_type === 'regular_price' ) {
			return array_values( array_diff( $product_ids, $sale_ids ) );
		}

		return $product_ids;
	}
}
