<?php
declare( strict_types=1 );

namespace FiboFilters\Integrations\Themes;

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

/**
 * Class Divi
 */
class Divi extends AbstractTheme {

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

		if ( $this->is_integration_enabled() ) {
			add_filter(
				'et_pb_all_fields_unprocessed_et_pb_shop',
				[
					$this,
					'add_fibofilters_switch_to_woo_products_module',
				]
			);
			add_filter(
				'fibofilters/request/context_and_query_vars',
				[
					$this,
					'support_page_with_woo_products',
				],
				10,
				2
			);
			add_action( 'wp', [ $this, 'support_theme_builder' ] );
		}
	}

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

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

		$queried_object = $query->queried_object;

		if (
			! is_a( $queried_object, 'WP_Post' ) &&
			$query->is_page() &&
			$query->get( 'page_id' ) === wc_get_page_id( 'shop' )
		) {
			$queried_object = get_post( $query->get( 'page_id' ) );
		}

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

				/**
				 * Converting attributes from shortcode "et_pb_shop" to attributes for "products".
				 */
				$products_shortcode_atts = [
					'orderby' => 'default',
					'order'   => 'ASC',
				];

				$type = $shortcode['atts']['type'] ?? '';
				if ( $type === 'product_category' ) {
					$products_shortcode_atts['category'] = $shortcode['atts']['include_categories'];
				} elseif ( $type === 'latest' ) {
					$products_shortcode_atts['orderby'] = 'date';
					$products_shortcode_atts['order']   = 'DESC';
				} elseif ( $type === 'featured' ) {
					$products_shortcode_atts['visibility'] = 'featured';
				}

				// Limit.
				$show_pagination = ! empty( $shortcode['atts']['show_pagination'] ) && $shortcode['atts']['show_pagination'] === 'on';
				if ( ! $show_pagination && isset( $shortcode['atts']['posts_number'] ) && is_numeric( $shortcode['atts']['posts_number'] ) ) {
					$products_shortcode_atts['limit'] = $shortcode['atts']['posts_number'];
				}
				// Columns.
				if ( isset( $shortcode['atts']['columns_number'] ) && is_numeric( $shortcode['atts']['columns_number'] ) ) {
					$products_shortcode_atts['columns'] = $shortcode['atts']['columns_number'];
					add_filter( 'fibofilters/config/products_per_row', fn() => intval( $shortcode['atts']['columns_number'] ) );
				}
				// Order by.
				if ( isset( $shortcode['atts']['orderby'] ) ) {
					if ( strpos( $shortcode['atts']['orderby'], '-desc' ) !== false ) {
						$products_shortcode_atts['order'] = 'DESC';
					}
					$products_shortcode_atts['orderby'] = str_replace( [ '-asc', '-desc' ], '', $shortcode['atts']['orderby'] );
				}

				$wc_shortcode_products = new \WC_Shortcode_Products( $products_shortcode_atts );
				$query_vars            = $wc_shortcode_products->get_query_args();

				/**
				 * The adjustments we make already on query vars.
				 */
				// Offset.
				if ( isset( $shortcode['atts']['offset_number'] ) && is_numeric( $shortcode['atts']['offset_number'] ) ) {
					$query_vars['offset'] = intval( $shortcode['atts']['offset_number'] );
				}
				if ( $type === 'sale' ) {
					// Product View Type: Sale Products.
					$query_vars['post__in'] = array_merge( [ 0 ], wc_get_product_ids_on_sale() );
				} elseif ( $type === 'best_selling' ) {
					// Product View Type: Best Selling Products.
					$query_vars['meta_key'] = 'total_sales';
					$query_vars['order']    = 'DESC';
					$query_vars['orderby']  = 'meta_value_num';
				} elseif ( $type === 'top_rated' ) {
					// Product View Type: Top rated.
					$query_vars['meta_key'] = '_wc_average_rating';
					$query_vars['order']    = 'DESC';
					$query_vars['orderby']  = 'meta_value_num';
				}

				$context['show_filters'] = true;
				if ( ! $show_pagination ) {
					$context['internal']['forced_query_args']                   = [];
					$context['internal']['forced_query_args']['posts_per_page'] = $shortcode['atts']['posts_number'] ?? 12;
					$context['internal']['forced_query_args']['nopaging']       = false;
				}

				$this->adjust_divi_config();
				$this->adjust_fibofilters_config( $shortcode['atts'] ?? [] );

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

		return [ $context, $query_vars ];
	}

	private function adjust_divi_config() {
		/*
		 * ╭─────────────────────────────────────────╮
		 * | Woo Products - add CSS class to wrapper |
		 * ╰─────────────────────────────────────────╯
		 */
		add_filter(
			'et_pb_module_shortcode_attributes',
			function ( $props, $attrs, $render_slug ) {
				if ( $render_slug === 'et_pb_shop' && isset( $attrs['fibofilters_integration'] ) && $attrs['fibofilters_integration'] === 'on' ) {
					$props['module_class'] .= ' fibofilters-divi-products ';
				}
				return $props;
			},
			10,
			3
		);
	}

	private function adjust_fibofilters_config( array $shortcode_atts = [] ) {
		/*
		 * ╭───────────────────────────────────────╮
		 * | Config: adjust products loop selector |
		 * ╰───────────────────────────────────────╯
		 */
		add_filter(
			'fibofilters/config/products_loop_selectors',
			function ( $selectors ) {
				$selectors[] = '.fibofilters-divi-products ul.products';

				return $selectors;
			}
		);

		add_filter(
			'fibofilters/config/products_per_page',
			function ( $products_per_page ) use ( $shortcode_atts ): int {
				if (
					! empty( $shortcode_atts['show_pagination'] ) &&
					$shortcode_atts['show_pagination'] === 'on' &&
					! empty( $shortcode_atts['posts_number'] )
				) {
					return (int) $shortcode_atts['posts_number'];
				}
				return $products_per_page;
			},
			15
		);

		// Prevents 404 errors when refreshing a page with an active filter by skipping main query filtering.
		// Not very elegant (causes products to jump on page load), but avoids the 404 issue.
		add_filter( 'fibofilters/request/skip_main_query_filtering', '__return_true' );
	}


	public function add_fibofilters_switch_to_woo_products_module( $fields ) {
		$fields['fibofilters_integration'] = [
			'label'           => esc_html_x( 'Integrate with FiboFilters', '[admin]', 'fibofilters' ),
			'type'            => 'yes_no_button',
			'option_category' => 'basic_option',
			'options'         => [
				'yes' => esc_html_x( 'Yes', '[admin]', 'fibofilters' ),
				'no'  => esc_html_x( 'No', '[admin]', 'fibofilters' ),
			],
			'toggle_slug'     => 'main_content',
			'description'     => '',
		];

		return $fields;
	}

	/**
	 * Support for Divi Theme Builder.
	 */
	public function support_theme_builder() {
		if ( ! function_exists( 'et_theme_builder_get_template_layouts' ) ) {
			return;
		}

		$layouts = et_theme_builder_get_template_layouts();

		// Break early if Divi doesn't use builder for body.
		if ( empty( $layouts ) || ! $layouts['et_body_layout']['override'] || ! $layouts['et_body_layout']['enabled'] ) {
			return;
		}

		// Break early if body layout is not set.
		if ( empty( $layouts['et_body_layout']['id'] ) ) {
			return;
		}

		$post = get_post( $layouts['et_body_layout']['id'] );

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

				// Limit.
				if ( isset( $shortcode['atts']['posts_number'] ) && is_numeric( $shortcode['atts']['posts_number'] ) ) {
					add_filter( 'fibofilters/config/products_per_page', fn() => intval( $shortcode['atts']['posts_number'] ), 15 );
				}
				// Columns.
				if ( isset( $shortcode['atts']['columns_number'] ) && is_numeric( $shortcode['atts']['columns_number'] ) ) {
					add_filter( 'fibofilters/config/products_per_row', fn() => intval( $shortcode['atts']['columns_number'] ) );
				}

				$this->adjust_divi_config();
				$this->adjust_fibofilters_config();
			}
		}
	}
}
