<?php
declare( strict_types=1 );

namespace FiboFilters\Integrations\Themes;

use FiboFilters\Config\AssetsLoader;
use FiboFilters\Filtering\Front;
use FiboFilters\Integrations\Plugins\Elementor\Utils as ElementorUtils;
use FiboFilters\Settings\Settings;
use FiboFilters\WP\Helper as WPHelper;

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

/**
 * Class Porto
 */
class Porto extends AbstractTheme {

	private const PORTO_SB_ARCHIVES_SHORTCODE = 'porto_sb_archives';
	private const PORTO_TB_ARCHIVES_SHORTCODE = 'porto_tb_archives';

	/** @var ElementorUtils */
	private $elementor_utils;

	public function __construct( ElementorUtils $elementor_utils, WPHelper $wp_helper, Front $front, Settings $settings, AssetsLoader $assets_loader ) {
		parent::__construct( $wp_helper, $front, $settings, $assets_loader );

		$this->elementor_utils = $elementor_utils;
	}

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

		if ( $this->is_integration_enabled() ) {
			add_action( 'wp', [ $this, 'support_porto_builder_archives_widget_wpbackery' ] );
			add_action( 'wp', [ $this, 'support_porto_builder_archives_widget_elementor' ] );

			add_action( 'vc_after_init', [ $this, 'add_fibofilters_switch_to_porto_builder_archives_widget_wpbackery' ] );
			add_action(
				'elementor/element/porto_sb_archives/post_advanced_section/after_section_end',
				[ $this, 'add_fibofilters_switch_to_porto_builder_archives_widget_elementor' ]
			);
		}
	}

	public function support_porto_builder_archives_widget_elementor() {
		$context = apply_filters( 'fibofilters/request/get_context', [] );
		if ( empty( $context['show_filters'] ) && empty( $context['is_get_products'] ) ) {
			return;
		}

		if ( ! function_exists( 'porto_check_builder_condition' ) ) {
			return;
		}

		$builder_id = porto_check_builder_condition( 'shop' );

		if ( empty( $builder_id ) ) {
			return;
		}

		$element = $this->elementor_utils->get_element_for_integrate_with_it_on_single(
			self::PORTO_SB_ARCHIVES_SHORTCODE,
			$builder_id,
			true
		);

		if ( empty( $element ) ) {
			return;
		}

		$this->integrate_porto_elementor_widget_with_fibofilters();
	}

	private function integrate_porto_elementor_widget_with_fibofilters() {

		add_filter(
			'elementor/widget/render_content',
			function ( $content, $widget ) {
				if ( $widget->get_name() !== self::PORTO_SB_ARCHIVES_SHORTCODE ) {
					return $content;
				}

				return $this->remove_infinite_scroll_classes( $content );
			},
			99,
			2
		);

		/**
		 * ╭──────────────────────────────────────────────╮
		 * | Hook our placeholders before Products widget |
		 * ╰──────────────────────────────────────────────╯
		 */
		add_action(
			'elementor/frontend/widget/before_render',
			function ( $element ) {
				if ( $element->get_name() !== self::PORTO_SB_ARCHIVES_SHORTCODE ) {
					return;
				}

				if ( did_action( 'woocommerce_before_shop_loop' ) > 0 ) {
					return;
				}

				do_action( 'fibofilters/front/display_load_previous_button_placeholder' );
				do_action( 'fibofilters/front/display_horizontal_filters_placeholder' );
				do_action( 'fibofilters/front/display_mobile_filters_placeholder' );
				do_action( 'fibofilters/front/display_applied_filters_placeholder' );
			}
		);

		/**
		 * ╭─────────────────────────────────────────────╮
		 * | Hook our placeholders after Products widget |
		 * ╰─────────────────────────────────────────────╯
		 */
		add_action(
			'elementor/frontend/widget/after_render',
			function ( $element ) {
				if ( $element->get_name() !== self::PORTO_SB_ARCHIVES_SHORTCODE ) {
					return;
				}

				if ( did_action( 'woocommerce_after_shop_loop' ) > 0 ) {
					return;
				}

				do_action( 'fibofilters/front/display_load_more_button_placeholder' );
				do_action( 'fibofilters/front/display_infinite_scroll_trigger' );
			}
		);
	}

	public function support_porto_builder_archives_widget_wpbackery() {
		$context = apply_filters( 'fibofilters/request/get_context', [] );

		if ( empty( $context['show_filters'] ) && empty( $context['is_get_products'] ) ) {
			return;
		}

		if ( ! function_exists( 'porto_check_builder_condition' ) ) {
			return;
		}

		$builder_id = porto_check_builder_condition( 'shop' );

		if ( ! $builder_id ) {
			return;
		}

		$content = get_post_field( 'post_content', get_post( $builder_id ) );

		if ( $this->wp_helper->has_shortcode( $content, self::PORTO_TB_ARCHIVES_SHORTCODE ) ) {
			$shortcodes = $this->wp_helper->get_shortcodes( $content, self::PORTO_TB_ARCHIVES_SHORTCODE );
			foreach ( $shortcodes as $shortcode ) {
				if ( isset( $shortcode['atts']['fibofilters_integration'] ) && $shortcode['atts']['fibofilters_integration'] === 'on' ) {
						$this->integrate_porto_wpbackery_widget_with_fibofilters( $shortcode['atts'] ?? [] );
					break;
				}
			}
		}
	}

	private function integrate_porto_wpbackery_widget_with_fibofilters( array $shortcode_atts ) {
		/**
		 * Inject FiboFilters shortcodes before and after products loop.
		 */
		add_filter(
			'do_shortcode_tag',
			function ( $output, $tag, $attr ) use ( $shortcode_atts ) {
				$integration_enabled = isset( $attr['fibofilters_integration'] ) && 'on' === $attr['fibofilters_integration'];

				if ( $tag === self::PORTO_TB_ARCHIVES_SHORTCODE & $integration_enabled ) {
					/**
					 * ╭──────────────────────────────────────────────╮
					 * | Hook our placeholders before Products widget |
					 * ╰──────────────────────────────────────────────╯
					 */

					if ( ! did_action( 'woocommerce_before_shop_loop' ) ) {
						$injection_start = do_shortcode( '[fibofilters layout=mobile]' ) .
											do_shortcode( '[fibofilters layout=horizontal]' ) .
											do_shortcode( '[fibofilters_applied_filters]' ) .
											do_shortcode( '[fibofilters_show_previous_products_btn]' );
						$output          = preg_replace(
							'/^(\s*<div\b[^>]*>)/i',
							'$1' . $injection_start,
							$output,
							1 // Only the first opening <div>.
						);
					}

					$pagination_strategy = $shortcode_atts['pagination_style'] ?? 'none';
					$injection_end       = '';

					/**
					 * ╭─────────────────────────────────────────────╮
					 * | Hook our placeholders after Products widget |
					 * ╰─────────────────────────────────────────────╯
					 */
					if ( $pagination_strategy === 'ajax' || $pagination_strategy === 'load_more' ) {
						$injection_end = do_shortcode( '[fibofilters_show_more_products_btn]' );
					} elseif ( $pagination_strategy === 'infinite' ) {
						$injection_end = do_shortcode( '[fibofilters_infinite_scroll_trigger]' );
					}

					if ( ! empty( $injection_end ) ) {
						$output = preg_replace(
							'/(<\/div>\s*)$/i',
							$injection_end . '$1',
							$output,
							1 // Only the last closing </div>.
						);
					}

					$output = $this->remove_infinite_scroll_classes( $output );
				}

				return $output;
			},
			10,
			3
		);
	}

	public function add_fibofilters_switch_to_porto_builder_archives_widget_wpbackery() {
		if ( ! function_exists( 'vc_add_param' ) ) {
			return;
		}

		vc_add_param(
			self::PORTO_TB_ARCHIVES_SHORTCODE,
			[
				'type'       => 'porto_button_group',
				'heading'    => _x( 'Integrate with FiboFilters', '[admin]', 'fibofilters' ),
				'param_name' => 'fibofilters_integration',
				'std'        => 'off',
				'value'      => [
					'off' => [
						'title' => 'Off',
						'label' => 'Off',
					],
					'on'  => [
						'title' => 'On',
						'label' => 'On',
					],
				],
				'group'      => esc_html__( 'Extras', 'porto_tb_archives' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
			]
		);
	}

	public function add_fibofilters_switch_to_porto_builder_archives_widget_elementor( $element ) {
		$element->start_controls_section(
			'fibofilters_section',
			[
				'label' => _x( 'FiboFilters', '[admin]', 'fibofilters' ),
				'tab'   => \Elementor\Controls_Manager::TAB_CONTENT,
			]
		);

		$element->add_control(
			'fibofilters_integration',
			[
				'label'   => _x( 'Integrate with FiboFilters', '[admin]', 'fibofilters' ),
				'type'    => \Elementor\Controls_Manager::SWITCHER,
				'default' => '',
			]
		);

		$element->end_controls_section();
	}

	/**
	 *
	 * Remove 'load-infinite' class from the first <div> in the content.
	 *
	 * This prevents conflicts between Porto's infinite scroll and FiboFilters' infinite scroll.
	 *
	 * @param string $content The HTML content to process.
	 */
	private function remove_infinite_scroll_classes( string $content ) {
		return preg_replace_callback(
			'/(<div\b[^>]*\bclass\s*=\s*)([\'"])([^\'"]*)(\2)/i',
			static function ( $m ) {
				$classes = preg_split( '/\s+/', trim( $m[3] ) );
				$classes = array_values( array_filter( $classes, static fn( $c ) => strtolower( $c ) !== 'load-infinite' ) );
				return $m[1] . $m[2] . implode( ' ', $classes ) . $m[4];
			},
			$content,
			1
		);
	}
}
