<?php
declare( strict_types=1 );

namespace FiboFilters\Filtering;

use FiboFilters\Config\Env;
use FiboFilters\Filters\FilterSources;
use FiboFilters\Index\Sources;
use FiboFilters\Index\Values;
use FiboFilters\Indexer\BuildInfo;
use FiboFilters\Integrations\Multilingual;
use FiboFilters\Settings\Settings;
use FiboFilters\Sorting\Sorting;
use FiboFilters\Struct\QueryContext;
use FiboFilters\WooCommerce\Helper as WooCommerceHelper;

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

/**
 * Class Front
 */
class Front {
	/** @var BuildInfo */
	private $build_info;

	/** @var FilterSources */
	private $filter_sources;

	/** @var Multilingual */
	private $multilingual;

	/** @var Settings */
	private $settings;

	/** @var Sources */
	private $sources;

	/** @var WooCommerceHelper */
	private $wc_helper;

	/** @var Values */
	private $values;

	/** @var Sorting */
	private $sorting;

	/** @var array */
	private $config;

	public function __construct(
		BuildInfo $build_info,
		Multilingual $multilingual,
		Settings $settings,
		WooCommerceHelper $wc_helper,
		FilterSources $filter_sources,
		Sources $sources,
		Values $values,
		Sorting $sorting
	) {
		$this->build_info     = $build_info;
		$this->multilingual   = $multilingual;
		$this->settings       = $settings;
		$this->wc_helper      = $wc_helper;
		$this->filter_sources = $filter_sources;
		$this->sources        = $sources;
		$this->values         = $values;
		$this->sorting        = $sorting;
	}

	public function add_hooks( bool $hook_into_shop_loop = true, bool $has_active_filters = false ): void {
		if ( $hook_into_shop_loop ) {
			if ( apply_filters( 'fibofilters/front/hook_into_woocommerce', true ) ) {
				add_action( 'woocommerce_before_shop_loop', [ $this, 'display_horizontal_filters_placeholder' ], 500 );
				add_action( 'woocommerce_before_shop_loop', [ $this, 'display_mobile_filters_placeholder' ], 510 );
				add_action( 'woocommerce_before_shop_loop', [ $this, 'display_applied_filters_placeholder' ], 520 );
			}
			add_action( 'woocommerce_before_shop_loop', [ $this, 'display_load_previous_button_placeholder' ], 520 );
			add_action( 'woocommerce_after_shop_loop', [ $this, 'display_load_more_button_placeholder' ], 5 );
			add_action( 'woocommerce_after_shop_loop', [ $this, 'display_infinite_scroll_trigger' ], 5 );

			if ( $has_active_filters ) {
				// Displaying the applied filters placeholder when no products are found will allow to remove active filters, e.g. price.
				add_action( 'woocommerce_no_products_found', [ $this, 'display_applied_filters_placeholder' ], 5 );
			}

			// Remove pagination if there are active filters.
			if ( $has_active_filters && ( $this->get_config_value( 'pagination_strategy' ) === 'show-more-button' || $this->get_config_value( 'pagination_strategy' ) === 'infinite-scroll' ) ) {
				remove_action( 'woocommerce_before_shop_loop', 'storefront_woocommerce_pagination', 30 );
				remove_action( 'woocommerce_after_shop_loop', 'woocommerce_pagination', 30 );
				remove_action( 'woocommerce_after_shop_loop', 'woocommerce_pagination', 10 );
			}

			// Display pagination placeholder if needed after deselecting active filters.
			if ( $has_active_filters && wc_get_loop_prop( 'total_pages' ) === 1 && apply_filters( 'fibofilters/front/force_display_pagination_placeholder', true ) ) {
				add_action( 'woocommerce_after_shop_loop', [ $this, 'display_pagination_placeholder' ] );
			}
		}

		add_action( 'fibofilters/front/display_horizontal_filters_placeholder', [ $this, 'display_horizontal_filters_placeholder' ] );
		add_action( 'fibofilters/front/display_mobile_filters_placeholder', [ $this, 'display_mobile_filters_placeholder' ] );
		add_action( 'fibofilters/front/display_applied_filters_placeholder', [ $this, 'display_applied_filters_placeholder' ] );
		add_action( 'fibofilters/front/display_load_previous_button_placeholder', [ $this, 'display_load_previous_button_placeholder' ] );
		add_action( 'fibofilters/front/display_load_more_button_placeholder', [ $this, 'display_load_more_button_placeholder' ] );
		add_action( 'fibofilters/front/display_infinite_scroll_trigger', [ $this, 'display_infinite_scroll_trigger' ] );
		add_action( 'fibofilters/front/display_pagination_placeholder', [ $this, 'display_pagination_placeholder' ] );
	}

	/**
	 * Get single front config value
	 *
	 * @param string $key Config key.
	 * @param mixed  $default_value Default value.
	 *
	 * @return false|mixed
	 */
	public function get_config_value( string $key, $default_value = null ) {
		$config = $this->get_config();

		return $config[ $key ] ?? $default_value;
	}

	public function get_config(): array {
		global $wp_locale, $wp_rewrite;

		if ( ! empty( $this->config ) ) {
			return $this->config;
		}

		if ( ! did_action( 'template_redirect' ) && ! did_action( 'elementor/editor/init' ) && ! did_action( 'admin_init' ) ) {
			_doing_it_wrong( '\FiboFilters\Filtering\Front::get_config', 'Do not use this function before the "template_redirect" or "admin_init" action.', '1.2.0' );
		}

		$products_per_page = wc_get_default_product_rows_per_page() * wc_get_default_products_per_row();
		if ( $products_per_page === 0 ) {
			$products_per_page = 12;
		}

		$number_format = [
			'thousands_sep' => ',',
			'decimal_point' => '.',
			'precision'     => 0,
			'prefix'        => '',
			'suffix'        => '',
		];
		if ( ! empty( $wp_locale->number_format ) ) {
			$number_format = wp_parse_args( $wp_locale->number_format, $number_format );
		}

		$collapse_after     = $this->settings->get( 'appearance_filters_collapsible', true ) ? 5 : -1;
		$filters_collapsing = [
			'collapse_after'            => $collapse_after,
			'off_canvas_collapse_after' => $collapse_after,
			'mobile_collapse_after'     => $collapse_after,
		];

		$custom_ordering_enabled = apply_filters( 'fibofilters/config/custom_ordering_enabled', false );
		if ( $custom_ordering_enabled ) {
			$this->apply_custom_ordering();
		}

		// Check if permalink structure is set to use trailing slash.
		$permalink_structure = get_option( 'permalink_structure' );
		$use_trailing_slash  = ! empty( $permalink_structure ) && substr( $permalink_structure, -1 ) === '/';

		$this->config = [
			'app_selector'                                => 'fibofilters',
			'v'                                           => base64_encode( Env::$version ), // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
			// Values: none, top, bottom, both.
			'applied_filters_position_sidebar'            => apply_filters( 'fibofilters/config/applied_filters_position_sidebar', 'none' ),
			'filter_location'                             => apply_filters( 'fibofilters/config/filter_location', $this->settings->get( 'general_filter_location', 'above_products' ) ),
			'show_count'                                  => $this->settings->get( 'appearance_show_count' ),
			'counter_format'                              => apply_filters( 'fibofilters/config/counter_format', 'blank' ),
			'scroll_top'                                  => $this->settings->get( 'appearance_scroll_top' ),
			'scroll_top_wait'                             => apply_filters( 'fibofilters/config/scroll_top_wait', 450 ),
			'scroll_top_offset_mobile'                    => apply_filters( 'fibofilters/config/scroll_top_offset_mobile', 200 ),
			'scroll_top_offset_desktop'                   => apply_filters( 'fibofilters/config/scroll_top_offset_desktop', 200 ),
			'currency'                                    => apply_filters( 'fibofilters/config/currency', $this->wc_helper->get_currency_settings() ),
			'multicurrency'                               => apply_filters( 'fibofilters/config/multicurrency', [] ),
			'mobile_filters_enabled'                      => apply_filters( 'fibofilters/config/mobile_filters_enabled', $this->settings->get( 'general_mobile_filters_enabled', true ) ),
			'mobile_breakpoint'                           => apply_filters( 'fibofilters/config/mobile_breakpoint', $this->settings->get( 'general_mobile_breakpoint', 450 ) ),
			'tablet_filters_enabled'                      => apply_filters( 'fibofilters/config/tablet_filters_enabled', $this->settings->get( 'general_tablet_filters_enabled', true ) ),
			'main_breakpoint'                             => apply_filters( 'fibofilters/config/main_breakpoint', $this->settings->get( 'general_main_breakpoint', 768 ) ),
			'offcanvas_position'                          => apply_filters( 'fibofilters/config/offcanvas_position', 'right' ),
			'pagination_strategy'                         => apply_filters( 'fibofilters/config/pagination_strategy', $this->settings->get( 'appearance_pagination_strategy', 'show-more-button' ) ),
			'pagination_base'                             => apply_filters( 'fibofilters/config/pagination_base', $wp_rewrite->pagination_base ),
			'show_more_less'                              => $this->settings->get( 'appearance_show_more_less' ),
			'show_more_less_number'                       => (int) $this->settings->get( 'appearance_show_more_less_number' ),
			'show_all_number'                             => (int) $this->settings->get( 'appearance_show_all_number' ),
			'show_all_grouping_by_first_char'             => apply_filters( 'fibofilters/config/show_all_grouping_by_first_char', true ),
			'organize_values_force_search'                => false,
			'ignored_classes_in_css_selectors'            => apply_filters( 'fibofilters/config/ignored_classes_in_css_selectors', [] ),
			'products_loop_selectors'                     => apply_filters( 'fibofilters/config/products_loop_selectors', [] ),
			'per_row'                                     => apply_filters( 'fibofilters/config/products_per_row', wc_get_default_products_per_row() ),
			'products_per_page'                           => apply_filters( 'fibofilters/config/products_per_page', $products_per_page ),
			'home_url'                                    => esc_url( home_url( '/' ) ),
			'use_trailing_slash'                          => apply_filters( 'fibofilters/config/use_trailing_slash', $use_trailing_slash ),
			/** The option is set in a different place @see Request::set_config() */
			'single_products_fetch_url'                   => '',
			'show_empty_values'                           => $this->settings->get( 'appearance_show_empty_values' ),
			'collapsing'                                  => apply_filters( 'fibofilters/filters/collapsing', $filters_collapsing ),
			'collapsing_overrides'                        => $this->map_collapsing_overrides_slugs_to_ids( apply_filters( 'fibofilters/filters/collapsing_overrides', [] ) ),
			'show_more_as_button'                         => apply_filters( 'fibofilters/config/show_more_as_button', false ),
			'show_more_button_counter'                    => apply_filters( 'fibofilters/config/show_more_button_counter', true ),
			'show_more_extra_classes'                     => apply_filters( 'fibofilters/config/show_more_extra_classes', [] ),
			'range_slider_histogram_ranges_limit'         => apply_filters( 'fibofilters/config/range_slider_histogram_ranges_limit', 16 ),
			'range_slider_min_value_label'                => apply_filters( 'fibofilters/config/range_slider_min_value_label', 'min' ), // Values: 'dynamic', 'min' or number.
			'range_slider_max_value_label'                => apply_filters( 'fibofilters/config/range_slider_max_value_label', 'max' ), // Values: 'dynamic', 'max' or number.
			'range_slider_step'                           => apply_filters( 'fibofilters/config/range_slider_step', 1 ),
			'range_slider_step_precision'                 => apply_filters( 'fibofilters/config/range_slider_step_precision', 0 ),
			'index_build_id'                              => $this->build_info->get_info( 'build_id' ),
			'last_updated_date'                           => $this->build_info->get_info( 'last_updated_date' ),
			'descriptors_endpoint'                        => apply_filters( 'fibofilters/config/descriptors_endpoint', get_rest_url( null, 'fibofilters/v1/filters/descriptors' ) ),
			'descriptors_json_url'                        => apply_filters( 'fibofilters/config/descriptors_json_url', '' ),
			'descriptors_prevent_cache'                   => apply_filters( 'fibofilters/config/descriptors_prevent_cache', '' ),
			'updated_descriptors_endpoint'                => apply_filters( 'fibofilters/config/updated_descriptors_endpoint', get_rest_url( null, 'fibofilters/v1/filters/updated-descriptors' ) ),
			'refetch_descriptors_after_update'            => apply_filters( 'fibofilters/config/refetch_descriptors_after_update', false ),
			'descriptors_data_fake_url'                   => $this->multilingual->is_multilingual() ? '/descriptors/' . $this->multilingual->get_current_language() : '/fibofilters',
			'is_multilingual'                             => $this->multilingual->is_multilingual(),
			'default_language'                            => $this->multilingual->get_default_language(),
			'current_language'                            => $this->multilingual->get_current_language(),
			'pagination_args'                             => apply_filters(
				'fibofilters/config/pagination_args',
				apply_filters(
					'woocommerce_pagination_args', // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
					[
						'before_page_number' => '',
						'after_page_number'  => '',
						'prev_text'          => is_rtl() ? '&rarr;' : '&larr;',
						'next_text'          => is_rtl() ? '&larr;' : '&rarr;',
						'end_size'           => 3,
						'mid_size'           => 3,
						'show_all'           => false,
						'type'               => 'list',
					]
				)
			),
			'pagination_item_classes'                     => apply_filters(
				'fibofilters/config/pagination_item_classes',
				[
					'prev_item'    => 'page-numbers prev',
					'next_item'    => 'page-numbers next',
					'current_item' => 'page-numbers current',
					'link_item'    => 'page-numbers',
					'dots_item'    => 'page-numbers dots',
				]
			),
			'scroll_top_on_page_change'                   => apply_filters( 'fibofilters/config/scroll_top_on_page_change', true ),
			'content_aware_filters_ratio'                 => apply_filters( 'fibofilters/config/content_aware_filters_ratio', 0.9 ),
			'hidden_filters_by_id'                        => apply_filters( 'fibofilters/config/hidden_filters/by_id', [] ),
			'hidden_filters_by_slug'                      => apply_filters( 'fibofilters/config/hidden_filters/by_slug', [] ),
			// Values: 'single' or 'page'.
			'products_fetching_strategy'                  => apply_filters( 'fibofilters/config/products_fetching_strategy', 'single' ),
			'pagination_selectors'                        => apply_filters( 'fibofilters/config/pagination_selectors', [ '.woocommerce-pagination' ] ),
			'horizontal_max_buttons'                      => apply_filters( 'fibofilters/config/horizontal_max_buttons', 5 ),
			'mobile_max_buttons'                          => apply_filters( 'fibofilters/config/mobile_max_buttons', 2 ),
			'always_display_all_filters_button'           => apply_filters( 'fibofilters/config/always_display_all_filters_button', true ),
			'number_format'                               => wp_parse_args( apply_filters( 'fibofilters/config/number_format', $number_format ), $number_format ),
			'early_products_caching'                      => apply_filters( 'fibofilters/config/early_products_caching', false ),
			'nofibofilters'                               => apply_filters( 'fibofilters/nofibofilters', '' ),
			'hide_categories_when_filters_active'         => apply_filters( 'fibofilters/config/hide_categories_when_filters_active', true ),
			'product_categories_selectors'                => apply_filters( 'fibofilters/config/product_categories_selectors', [ '.product-category' ] ),
			'override_ordering_enabled'                   => apply_filters( 'fibofilters/config/override_ordering_enabled', false ),
			'custom_ordering_enabled'                     => $custom_ordering_enabled,
			'ordering_selectors'                          => apply_filters( 'fibofilters/config/ordering_selectors', [ '.woocommerce-ordering' ] ),
			'catalog_orderedby'                           => [],
			'default_catalog_orderby'                     => '',
			'orderby_sources_map'                         => [],
			'orderby_in_stock_first'                      => apply_filters( 'fibofilters/request/product_order/in_stock_first', false ),
			'orderby_in_stock_first_exceptions'           => apply_filters( 'fibofilters/request/product_order/in_stock_first_exceptions', [] ),
			'orderby_featured_first'                      => apply_filters( 'fibofilters/request/product_order/featured_first', false ),
			'orderby_featured_first_exceptions'           => apply_filters( 'fibofilters/request/product_order/featured_first_exceptions', [] ),
			'removable_url_params'                        => apply_filters( 'fibofilters/config/removable_url_params', [ 'paged' ] ),
			'filter_headline_tag'                         => apply_filters( 'fibofilters/config/filter_headline_tag', 'h3' ),
			'overrides'                                   => apply_filters( 'fibofilters/config/overrides', [] ),
			'expand_to_level'                             => apply_filters( 'fibofilters/config/expand_to_level', 0 ),
			'extra_html'                                  => $this->get_extra_html(),
			'single_variations_support'                   => apply_filters( 'fibofilters/config/single_variations_support', false ),
			'override_result_count_enabled'               => apply_filters( 'fibofilters/config/override_result_count_enabled', true ),
			'clear_product_container_exceptions'          => apply_filters( 'fibofilters/config/clear_product_container_exceptions', ':not(style):not(link)' ),
			'filters_affecting_variation_images_and_urls' => apply_filters( 'fibofilters/config/filters_affecting_variation_images_and_urls', [] ),
			'always_selected_values'                      => $this->get_always_selected_values(),
			'can_show_critical_errors_warning'            => apply_filters( 'fibofilters/config/can_show_critical_errors_warning', current_user_can( 'manage_options' ) ),
		];

		if ( ! empty( $this->config['overrides'] ) ) {
			$this->config['overrides'] = $this->allow_override_filter_settings_by_slug( $this->config['overrides'] );
		}

		if ( $this->config['override_ordering_enabled'] ) {
			$this->config['catalog_orderedby']       = $this->sorting->get_catalog_orderedby();
			$this->config['default_catalog_orderby'] = $this->wc_helper->get_default_catalog_orderby();
			$this->config['orderby_sources_map']     = $this->filter_sources->get_orderby_sources_map( $this->multilingual->is_multilingual() ? $this->multilingual->get_current_language() : '' );
		}

		$this->config['fibosearch'] = [
			'is_active' => did_action( 'fibofilters/integrations/plugin/late_init/fibosearch_pro' ) > 0,
		];
		if ( $this->config['fibosearch']['is_active'] ) {
			$this->config['fibosearch']['search_endpoint']  = DGWT_WCAS()->getInfo( 'search_endpoint' );
			$this->config['fibosearch']['current_language'] = DGWT_WCAS()->getInfo( 'current_language' );
		}

		return $this->config;
	}

	public function display_horizontal_filters_placeholder(): void {
		if ( $this->get_config_value( 'filter_location' ) === 'custom' ) {
			return;
		}
		echo do_shortcode( '[fibofilters layout="horizontal"]' );
	}

	public function display_mobile_filters_placeholder(): void {
		if ( $this->get_config_value( 'filter_location' ) === 'custom' ) {
			return;
		}
		echo do_shortcode( '[fibofilters layout="mobile"]' );
	}

	public function display_applied_filters_placeholder(): void {
		if ( $this->get_config_value( 'filter_location' ) === 'custom' ) {
			return;
		}
		echo do_shortcode( '[fibofilters_applied_filters]' );
	}

	public function display_load_previous_button_placeholder(): void {
		if ( $this->get_config_value( 'filter_location' ) === 'custom' ) {
			return;
		}
		if ( $this->get_config_value( 'pagination_strategy' ) === 'show-more-button' || $this->get_config_value( 'pagination_strategy' ) === 'infinite-scroll' ) {
			echo do_shortcode( '[fibofilters_show_previous_products_btn]' );
		}
	}

	public function display_load_more_button_placeholder(): void {
		if ( $this->get_config_value( 'filter_location' ) === 'custom' ) {
			return;
		}
		if ( $this->get_config_value( 'pagination_strategy' ) === 'show-more-button' ) {
			echo do_shortcode( '[fibofilters_show_more_products_btn]' );
		}
	}

	public function display_infinite_scroll_trigger(): void {
		if ( $this->get_config_value( 'filter_location' ) === 'custom' ) {
			return;
		}
		if ( $this->get_config_value( 'pagination_strategy' ) === 'infinite-scroll' ) {
			echo do_shortcode( '[fibofilters_infinite_scroll_trigger]' );
		}
	}

	public function display_pagination_placeholder(): void {
		if ( $this->get_config_value( 'filter_location' ) === 'custom' ) {
			return;
		}
		echo do_shortcode( '[fibofilters_pagination]' );
	}

	/**
	 * Get breakpoints for shortcode based on global settings
	 *
	 * @param string $layout Shortcode layout.
	 *
	 * @return int[]
	 */
	public function get_breakpoints( string $layout ): array { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.MaxExceeded
		$filter_location        = $this->get_config_value( 'filter_location' );
		$mobile_filters_enabled = $this->get_config_value( 'mobile_filters_enabled' );
		$mobile_breakpoint      = (int) $this->get_config_value( 'mobile_breakpoint' );
		$tablet_filters_enabled = $this->get_config_value( 'tablet_filters_enabled' );
		$main_breakpoint        = (int) $this->get_config_value( 'main_breakpoint' );

		if ( $filter_location === 'sidebar' ) {
			/**
			 * 1 - mobile breakpoint, 2 - main breakpoint
			 * mobile filters: enabled, tablet filters: enabled
			 *
			 *           0---HOR.---*
			 * ---MOB.---*          0---VER.---
			 * ----------1----------2---------->
			 */
			if ( $mobile_filters_enabled && $tablet_filters_enabled ) {
				switch ( $layout ) {
					case 'vertical':
						return [
							'min_screen' => $main_breakpoint + 1,
							'max_screen' => 99999,
						];
					case 'horizontal':
						return [
							'min_screen' => $mobile_breakpoint + 1,
							'max_screen' => $main_breakpoint,
						];
					case 'mobile':
						return [
							'min_screen' => 1,
							'max_screen' => $mobile_breakpoint,
						];
				}
			} elseif ( $mobile_filters_enabled && ! $tablet_filters_enabled ) {
				/**
				 * 1 - mobile breakpoint, 2 - main breakpoint
				 * mobile filters: enabled, tablet filters: disabled
				 *
				 *           0---VER.--------------
				 * ---MOB.---*
				 * ----------1----------2---------->
				 */
				switch ( $layout ) {
					case 'vertical':
						return [
							'min_screen' => $mobile_breakpoint + 1,
							'max_screen' => 99999,
						];
					case 'horizontal':
						return [
							'min_screen' => 99999,
							'max_screen' => 99999,
						];
					case 'mobile':
						return [
							'min_screen' => 1,
							'max_screen' => $mobile_breakpoint,
						];
				}
			} elseif ( ! $mobile_filters_enabled && $tablet_filters_enabled ) {
				/**
				 * 1 - mobile breakpoint, 2 - main breakpoint
				 * mobile filters: disabled, tablet filters: enabled
				 *
				 * *-------------HOR.---*
				 *                      0---VER.---
				 * ----------1----------2---------->
				 */
				switch ( $layout ) {
					case 'vertical':
						return [
							'min_screen' => $main_breakpoint + 1,
							'max_screen' => 99999,
						];
					case 'horizontal':
						return [
							'min_screen' => 1,
							'max_screen' => $main_breakpoint,
						];
					case 'mobile':
						return [
							'min_screen' => 99999,
							'max_screen' => 99999,
						];
				}
			} elseif ( ! $mobile_filters_enabled && ! $tablet_filters_enabled ) {
				/**
				 * 1 - mobile breakpoint, 2 - main breakpoint
				 * - Mobile filters: disabled, Tablet filters: disabled
				 *
				 * *------------------------VER.---
				 * ----------1----------2---------->
				 */
				switch ( $layout ) {
					case 'vertical':
						return [
							'min_screen' => 1,
							'max_screen' => 99999,
						];
					case 'horizontal':
					case 'mobile':
						return [
							'min_screen' => 99999,
							'max_screen' => 99999,
						];
				}
			}
		} elseif ( $filter_location === 'above_products' ) {
			/**
			 * 1 - mobile breakpoint, 2 - main breakpoint
			 * - Mobile filters: enabled, Tablet filters: enabled
			 * - Mobile filters: enabled, Tablet filters: disabled
			 *
			 *           0---HOR.--------------
			 * ---MOB.---*
			 * ----------1----------2---------->
			 */
			if ( $mobile_filters_enabled ) {
				switch ( $layout ) {
					case 'vertical':
						return [
							'min_screen' => 99999,
							'max_screen' => 99999,
						];
					case 'horizontal':
						return [
							'min_screen' => $mobile_breakpoint + 1,
							'max_screen' => 99999,
						];
					case 'mobile':
						return [
							'min_screen' => 1,
							'max_screen' => $mobile_breakpoint,
						];
				}
			} else {
				/**
				 * 1 - mobile breakpoint, 2 - main breakpoint
				 * - Mobile filters: disabled, Tablet filters: enabled
				 * - Mobile filters: disabled, Tablet filters: disabled
				 *
				 * *-------------HOR.--------------
				 * ----------1----------2---------->
				 */
				switch ( $layout ) {
					case 'vertical':
					case 'mobile':
						return [
							'min_screen' => 99999,
							'max_screen' => 99999,
						];
					case 'horizontal':
						return [
							'min_screen' => 1,
							'max_screen' => 99999,
						];
				}
			}
		}

		/**
		 * If the filter location is set to "Custom location", always show filters by default.
		 */
		return [
			'min_screen' => 1,
			'max_screen' => 99999,
		];
	}

	/**
	 * Replaces the filter slug with the filter ID
	 * if the user provided a slug while using the 'fibofilters/config/overrides' filter.
	 *
	 * @param array $overrides Overrides.
	 */
	public function allow_override_filter_settings_by_slug( array $overrides ): array {
		$filters = $this->settings->get( 'filters_filters' );

		if ( empty( $filters ) ) {
			return $overrides;
		}

		foreach ( $overrides as $maybe_slug => $filter_overrides ) {
			foreach ( $filters as $filter ) {
				if ( $filter['url_slug'] === $maybe_slug ) {
					$overrides[ $filter['id'] ] = $filter_overrides;
					unset( $overrides[ $maybe_slug ] );
					break;
				}
			}
		}
		uksort( $overrides, 'strnatcmp' );

		return $overrides;
	}


	public function get_extra_html() {
		$filters = $this->settings->get( 'filters_filters' );

		$extra_html = apply_filters( 'fibofilters/config/extra_html', [] );

		// Replaces the filter slug with the filter ID.
		if ( ! empty( $extra_html ) && is_array( $extra_html ) ) {
			foreach ( $extra_html as $path => $filter_extra_html ) {
				foreach ( $filters as $filter ) {
					$filter_by_slug = sprintf( 'filter=%s/', $filter['url_slug'] );
					if ( strpos( $path, $filter_by_slug ) !== false ) {
						$filter_by_id = sprintf( 'filter=%s/', $filter['id'] );
						$extra_html[ str_replace( $filter_by_slug, $filter_by_id, $path ) ] = $filter_extra_html;
						unset( $extra_html[ $path ] );
						break;
					}
				}
			}
		}

		return $extra_html;
	}

	public function get_always_selected_values(): array {
		$always_selected_values = [];

		$filters = $this->settings->get( 'filters_filters' );

		if ( empty( $filters ) ) {
			return $always_selected_values;
		}

		// Always selected value for the product category filter.
		if ( is_product_category() ) {
			$category = get_queried_object();
			if ( ! empty( $category->term_id ) ) {
				$language = $this->multilingual->is_multilingual() ? $this->multilingual->get_current_language() : '';
				$ctx      = new QueryContext( $language );

				foreach ( $filters as $filter ) {
					if ( $filter['source'] === 'tax_product_cat' && $filter['type'] !== 'category' ) {
						$source_id = $this->sources->get_source_id_by_name( 'tax_product_cat', $ctx );
						if ( $source_id === 0 ) {
							break;
						}

						$value = $this->values->get_value_by_label_url( $category->slug, $source_id, $ctx );
						if ( empty( $value ) ) {
							break;
						}

						$always_selected_values[ $filter['url_slug'] ]   = [];
						$always_selected_values[ $filter['url_slug'] ][] = [
							'label_url' => $category->slug,
							'value_id'  => intval( $value[0]['value_id'] ),
						];
					}
				}
			}
		}

		return $always_selected_values;
	}

	/**
	 * Apply custom ordering
	 */
	public function apply_custom_ordering(): void {
		add_filter( 'fibofilters/config/override_ordering_enabled', '__return_true', PHP_INT_MAX - 5 );

		add_filter(
			'fibofilters/config/ordering_selectors',
			function () {
				return [
					'.fibofilters-ordering',
				];
			},
			PHP_INT_MAX - 5
		);

		add_action(
			'woocommerce_after_template_part',
			function ( $template_name ) {
				if ( $template_name === 'loop/orderby.php' ) {
					echo do_shortcode( '[fibofilters_ordering]' );
				}
			}
		);

		add_action(
			'wp_enqueue_scripts',
			function () {
				ob_start();
				?>
				<style>
					.woocommerce-ordering {
						display: none !important;
					}
				</style>
				<?php
				$css = (string) ob_get_clean();
				wp_add_inline_style(
					'fibofilters',
					str_replace( [ '<style>', '</style>' ], '', $css )
				);
			}
		);
	}

	/**
	 * Map collapsing overrides slugs to IDs.
	 */
	private function map_collapsing_overrides_slugs_to_ids( $config_by_slug ): array {
		$filters      = $this->settings->get( 'filters_filters' );
		$config_by_id = [];

		foreach ( $filters as $filter ) {
			$slug = $filter['url_slug'];
			$id   = $filter['id'];

			if ( isset( $config_by_slug[ $slug ] ) ) {
				$config_by_id[ $id ] = $config_by_slug[ $slug ];
			}
		}

		return $config_by_id;
	}
}
