<?php

/**
 * Archive Products Grid with AJAX sidebar filters.
 *
 * @package storzen
 */

namespace Elementor;

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

class Storzen_Archive_Grid extends Widget_Base
{
	public function get_name()
	{
		return 'storzen-archive-grid';
	}

	public function get_title()
	{
		return esc_html__('Archive Products Grid', 'storzen');
	}

	public function get_icon()
	{
		return 'eicon-products';
	}

	public function get_categories()
	{
		return array('storzen');
	}

	public function get_script_depends()
	{
		return array('storzen-shop-sidebar');
	}

	protected function register_controls()
	{
		$this->start_controls_section(
			'layout_section',
			array(
				'label' => esc_html__('Layout', 'storzen'),
			)
		);

		$this->add_control(
			'style',
			array(
				'label'   => esc_html__('Select Style', 'storzen'),
				'type'    => Controls_Manager::SELECT2,
				'options' => array(
					'style-1' => esc_html__('Style 1', 'storzen'),
				),
				'default' => 'style-1',
			)
		);

		$this->end_controls_section();

		$this->start_controls_section(
			'grid_section',
			array(
				'label' => esc_html__('Product grid', 'storzen'),
			)
		);

		$this->add_control(
			'column',
			array(
				'label'   => esc_html__('Columns (main area)', 'storzen'),
				'type'    => Controls_Manager::SELECT2,
				'options' => array(
					'2' => esc_html__('6', 'storzen'),
					'3' => esc_html__('4', 'storzen'),
					'4' => esc_html__('3', 'storzen'),
					'6' => esc_html__('2', 'storzen'),
				),
				'default' => '4',
			)
		);

		$this->add_control(
			'ppr',
			array(
				'label'   => esc_html__('Products per page', 'storzen'),
				'type'    => Controls_Manager::NUMBER,
				'min'     => 1,
				'max'     => 48,
				'default' => 12,
			)
		);

		$this->add_control(
			'show_toolbar',
			array(
				'label'        => esc_html__('Show toolbar', 'storzen'),
				'type'         => Controls_Manager::SWITCHER,
				'return_value' => 'yes',
				'default'      => 'yes',
			)
		);

		$this->add_control(
			'show_grid_list_icons',
			array(
				'label'        => esc_html__('Grid / list toggle', 'storzen'),
				'type'         => Controls_Manager::SWITCHER,
				'return_value' => 'yes',
				'default'      => 'yes',
				'condition'    => array('show_toolbar' => 'yes'),
			)
		);

		$this->end_controls_section();

		$this->start_controls_section(
			'query_section',
			array(
				'label' => esc_html__('Query', 'storzen'),
			)
		);

		$this->add_control(
			'select_cat',
			array(
				'label'    => esc_html__('Product categories', 'storzen'),
				'type'     => Controls_Manager::SELECT2,
				'multiple' => true,
				'options'  => storzen_post_category(),
			)
		);

		$this->add_control(
			'exclude_cat',
			array(
				'label'    => esc_html__('Exclude categories', 'storzen'),
				'type'     => Controls_Manager::SELECT2,
				'multiple' => true,
				'options'  => storzen_post_category(),
			)
		);

		$this->add_control(
			'wc_orderby',
			array(
				'label'   => esc_html__('Sort products by', 'storzen'),
				'type'    => Controls_Manager::SELECT,
				'options' => array(
					'menu_order' => esc_html__('Default sorting', 'storzen'),
					'popularity' => esc_html__('Popularity', 'storzen'),
					'rating'     => esc_html__('Average rating', 'storzen'),
					'date'       => esc_html__('Latest', 'storzen'),
					'price'      => esc_html__('Price: low to high', 'storzen'),
					'price-desc' => esc_html__('Price: high to low', 'storzen'),
				),
				'default' => 'menu_order',
			)
		);

		$this->add_control(
			'order',
			array(
				'label'   => esc_html__('Order', 'storzen'),
				'type'    => Controls_Manager::SELECT,
				'options' => array(
					'ASC'  => esc_html__('ASC', 'storzen'),
					'DESC' => esc_html__('DESC', 'storzen'),
				),
				'default' => 'DESC',
			)
		);

		$this->end_controls_section();

		$this->start_controls_section(
			'title_settings',
			array(
				'label' => esc_html__('Title', 'storzen'),
			)
		);

		$this->add_control(
			'dtitle',
			array(
				'label'   => esc_html__('Product title', 'storzen'),
				'type'    => Controls_Manager::SELECT,
				'options' => array(
					'full'    => esc_html__('Full', 'storzen'),
					'excerpt' => esc_html__('Excerpt', 'storzen'),
				),
				'default' => 'full',
			)
		);

		$this->add_control(
			'title_excerpt_length',
			array(
				'label'     => esc_html__('Title excerpt words', 'storzen'),
				'type'      => Controls_Manager::NUMBER,
				'default'   => 8,
				'condition' => array('dtitle' => 'excerpt'),
			)
		);

		$this->add_control(
			'titltag',
			array(
				'label'   => esc_html__('Title HTML tag', 'storzen'),
				'type'    => Controls_Manager::SELECT,
				'options' => array(
					'h1' => 'H1',
					'h2' => 'H2',
					'h3' => 'H3',
					'h4' => 'H4',
					'h5' => 'H5',
					'h6' => 'H6',
				),
				'default' => 'h6',
			)
		);

		$this->add_control(
			'open-url',
			array(
				'label'   => esc_html__('Open product in', 'storzen'),
				'type'    => Controls_Manager::SELECT,
				'options' => array(
					'same-window' => esc_html__('Same window', 'storzen'),
					'new-window'  => esc_html__('New window', 'storzen'),
				),
				'default' => 'same-window',
			)
		);

		$this->end_controls_section();

		$this->start_controls_section(
			'pagination_section',
			array(
				'label' => esc_html__('Pagination', 'storzen'),
			)
		);

		$this->add_control(
			'enable_pagination',
			array(
				'label'        => esc_html__('Enable pagination', 'storzen'),
				'type'         => Controls_Manager::SWITCHER,
				'return_value' => 'yes',
				'default'      => 'yes',
			)
		);

		$this->end_controls_section();

		$this->start_controls_section(
			'modules_section',
			array(
				'label' => esc_html__('Modules', 'storzen'),
			)
		);

		$this->add_control(
			'modules_info',
			array(
				'type'            => Controls_Manager::RAW_HTML,
				'raw'             => sprintf(
					wp_kses(
						/* translators: %s: URL to module settings page */
						__( 'Each toggle below overrides the global module setting <strong>for this widget only</strong>. A module must be enabled on the <a href="%s" target="_blank">Storzen Modules page</a> before it can be activated here.', 'storzen' ),
						array(
							'strong' => array(),
							'a'      => array( 'href' => array(), 'target' => array() ),
						)
					),
					esc_url( admin_url( 'admin.php?page=storzen-modules' ) )
				),
				'content_classes' => 'elementor-panel-alert elementor-panel-alert-info',
			)
		);

		// ── On-card modules ─────────────────────────────────────────────────

		$this->add_control(
			'module_sale_badge',
			array(
				'label'        => esc_html__( 'Sale Badge', 'storzen' ),
				'description'  => esc_html__( 'Show Hot, New, and Sale % badges on each product card.', 'storzen' ),
				'type'         => Controls_Manager::SWITCHER,
				'return_value' => 'yes',
				'default'      => 'yes',
			)
		);

		$this->add_control(
			'module_quick_view',
			array(
				'label'        => esc_html__( 'Quick View', 'storzen' ),
				'description'  => esc_html__( 'Show a Quick View eye icon on each product card.', 'storzen' ),
				'type'         => Controls_Manager::SWITCHER,
				'return_value' => 'yes',
				'default'      => 'yes',
			)
		);

		$this->add_control(
			'module_wishlist',
			array(
				'label'        => esc_html__( 'Wishlist', 'storzen' ),
				'description'  => esc_html__( 'Show a Wishlist heart icon on each product card.', 'storzen' ),
				'type'         => Controls_Manager::SWITCHER,
				'return_value' => 'yes',
				'default'      => 'yes',
			)
		);

		$this->add_control(
			'module_compare',
			array(
				'label'        => esc_html__( 'Compare Products', 'storzen' ),
				'description'  => esc_html__( 'Show a Compare icon on each product card.', 'storzen' ),
				'type'         => Controls_Manager::SWITCHER,
				'return_value' => 'yes',
				'default'      => 'yes',
			)
		);

		$this->add_control(
			'module_flash_countdown',
			array(
				'label'        => esc_html__( 'Flash Sale Countdown', 'storzen' ),
				'description'  => esc_html__( 'Show a sale countdown timer below the price on each product card.', 'storzen' ),
				'type'         => Controls_Manager::SWITCHER,
				'return_value' => 'yes',
				'default'      => 'yes',
			)
		);

		$this->add_control(
			'module_stock_scarcity',
			array(
				'label'        => esc_html__( 'Stock Scarcity', 'storzen' ),
				'description'  => esc_html__( 'Show "Only X left!" urgency messages below the price on each product card.', 'storzen' ),
				'type'         => Controls_Manager::SWITCHER,
				'return_value' => 'yes',
				'default'      => 'yes',
			)
		);

		$this->add_control(
			'module_variation_swatches',
			array(
				'label'        => esc_html__( 'Variation Swatches', 'storzen' ),
				'description'  => esc_html__( 'Show color / image / button swatches on variable product cards.', 'storzen' ),
				'type'         => Controls_Manager::SWITCHER,
				'return_value' => 'yes',
				'default'      => 'yes',
			)
		);

		$this->add_control(
			'module_preorder',
			array(
				'label'        => esc_html__( 'Pre-Order', 'storzen' ),
				'description'  => esc_html__( 'Show the Pre-Order badge on each product card. (Pro)', 'storzen' ),
				'type'         => Controls_Manager::SWITCHER,
				'return_value' => 'yes',
				'default'      => 'yes',
			)
		);

		$this->add_control(
			'module_quick_checkout',
			array(
				'label'        => esc_html__( 'Quick Checkout', 'storzen' ),
				'description'  => esc_html__( 'Show the Quick Checkout button on each product card. (Pro)', 'storzen' ),
				'type'         => Controls_Manager::SWITCHER,
				'return_value' => 'yes',
				'default'      => 'yes',
			)
		);

		$this->end_controls_section();

		$this->start_controls_section(
			'content_style',
			array(
				'label' => esc_html__('Content Style', 'storzen'),
				'tab'   => Controls_Manager::TAB_STYLE,
			)
		);

		storzen_elementor_style_options($this, 'Title', '{{WRAPPER}} .content .woo-title', array('style-1'));
		storzen_elementor_style_options($this, 'Category', '{{WRAPPER}} .content .category', array('style-1'));
		storzen_elementor_style_options($this, 'Pricing', '{{WRAPPER}} .prices span', array('style-1'));
		storzen_elementor_style_options($this, 'Action Icons', '{{WRAPPER}} .social-style-two i', array('style-1'));
		storzen_elementor_style_options($this, 'New Badge', '{{WRAPPER}} .bgc-black', array('style-1'));
		storzen_elementor_style_options($this, 'New Badge Background', '{{WRAPPER}} .bgc-black', array('style-1'), 'background-color', false, true);
		storzen_elementor_style_options($this, 'Sale Badge', '{{WRAPPER}} .bgc-primary', array('style-1'));
		storzen_elementor_style_options($this, 'Sale Badge Background', '{{WRAPPER}} .bgc-primary', array('style-1'), 'background-color', false, true);
		storzen_elementor_style_options($this, 'Pagination Link', '{{WRAPPER}} .szp-pagination button.szp-page-btn', array('style-1'));
		storzen_elementor_style_options($this, 'Pagination Active', '{{WRAPPER}} .szp-pagination button.number.current', array('style-1'));
		storzen_elementor_style_options($this, 'Pagination Active Background', '{{WRAPPER}} .szp-pagination button.number.current', array('style-1'), 'background-color', false, true);

		$this->end_controls_section();
	}

	protected function get_current_page_url()
	{
		if (is_singular() && get_queried_object_id()) {
			return get_permalink(get_queried_object_id());
		}
		global $post;
		if ($post && is_a($post, 'WP_Post')) {
			return get_permalink($post);
		}
		return home_url('/');
	}

	protected function render()
	{
		if (! function_exists('WC')) {
			echo '<p>' . esc_html__('WooCommerce is required for this widget.', 'storzen') . '</p>';
			return;
		}

		if (! function_exists('storzen_shop_sidebar_build_query_args')) {
			echo '<p>' . esc_html__('Shop sidebar helpers are missing.', 'storzen') . '</p>';
			return;
		}

		$settings = $this->get_settings_for_display();
		$paged = is_front_page() ? (int) get_query_var('page') : (int) get_query_var('paged');
		if ($paged < 1) {
			$paged = 1;
		}

		$query_settings = storzen_shop_sidebar_sanitize_settings($settings);

		$filters = array(
			'paged'             => $paged,
			'orderby'           => $query_settings['wc_orderby'],
			'order'             => $query_settings['order'],
			'product_cat_slugs' => array(),
			'attribute_slugs'   => array(),
			'stock_states'      => array(),
			'rating_values'     => array(),
		);
		$filters = storzen_shop_sidebar_filters_from_request($filters, $query_settings);

		$args                     = storzen_shop_sidebar_build_query_args($query_settings, $filters);
		$storzen_posts_query = new \WP_Query($args);

		$szp_shop_sidebar_base_url = $this->get_current_page_url();
		$szp_element_id            = $this->get_id();
		$szp_filters               = $filters;

		$szp_inline = array(
			'elementId'      => $szp_element_id,
			'settings'       => $query_settings,
			'initialFilters' => $szp_filters,
			'pageUrl'        => $szp_shop_sidebar_base_url,
		);
		wp_add_inline_script(
			'storzen-shop-sidebar',
			'window.WcommeroProShopSidebarCfg=window.WcommeroProShopSidebarCfg||{};window.WcommeroProShopSidebarCfg[' . wp_json_encode($szp_element_id) . ']=' . wp_json_encode($szp_inline) . ';',
			'after'
		);

		self::set_active_module_settings( $settings );

		include storzen_get_template('archive-grid.php');

		self::clear_active_module_settings();
	}

	/**
	 * Active module settings for the widget currently being rendered.
	 * Keyed by module slug (e.g. 'sale_badge') → bool.
	 * Null means no widget context is active (global module state applies).
	 *
	 * @var array<string,bool>|null
	 */
	private static $active_module_settings = null;

	/**
	 * Page-level module decisions accumulated across all widget renders on
	 * this request. Used by footer-rendered modules (Sale Notification, Sticky
	 * ATC, Shipping Bar, Variation Swatches) that cannot be guarded inside the
	 * card loop because they render via wp_footer / wp_enqueue_scripts.
	 *
	 * Once ANY widget on the page enables a module → it renders page-wide.
	 * If every widget on the page has the toggle OFF → the module is suppressed.
	 * If no Archive Products Grid widget is present → falls back to global state.
	 *
	 * @var array<string,bool>|null  null = no widget on page yet.
	 */
	private static $page_module_decisions = null;

	/**
	 * Map of widget setting keys to Storzen module keys.
	 *
	 * @return array<string,string>
	 */
	public static function module_map() {
		return array(
			'module_variation_swatches' => 'variation_swatches',
			'module_quick_view'         => 'quick_view',
			'module_sale_badge'         => 'sale_badge',
			'module_wishlist'           => 'wishlist',
			'module_compare'            => 'compare',
			'module_flash_countdown'    => 'flash_countdown',
			'module_stock_scarcity'     => 'stock_scarcity',
			'module_preorder'           => 'preorder',
			'module_quick_checkout'     => 'quick_checkout',
		);
	}

	/**
	 * Store widget-level module toggles before template render.
	 *
	 * Visibility rule (both layers must be ON):
	 *   • The module must be enabled globally on the Storzen Modules admin page.
	 *   • AND the matching widget toggle must be ON ("yes").
	 * Turning off either layer hides the module for this widget.
	 *
	 * Elementor's SWITCHER stores "yes" when ON and an empty string when OFF.
	 * All toggles default to "yes", so a brand-new widget shows every globally
	 * enabled module until the editor turns specific toggles off.
	 *
	 * @param array $settings Elementor widget settings (from get_settings_for_display).
	 */
	public static function set_active_module_settings( array $settings ) {
		$resolved = array();
		foreach ( self::module_map() as $setting_key => $module_key ) {
			$widget_on   = isset( $settings[ $setting_key ] ) && 'yes' === (string) $settings[ $setting_key ];
			$globally_on = function_exists( 'storzen_module_enabled' ) && storzen_module_enabled( $module_key );

			// Both layers required.
			$resolved[ $module_key ] = ( $widget_on && $globally_on );

			// Accumulate page-level decision: any widget enabling a module → page-wide on.
			if ( null === self::$page_module_decisions ) {
				self::$page_module_decisions = array();
			}
			if ( ! isset( self::$page_module_decisions[ $module_key ] ) ) {
				self::$page_module_decisions[ $module_key ] = false;
			}
			if ( $resolved[ $module_key ] ) {
				self::$page_module_decisions[ $module_key ] = true;
			}
		}
		self::$active_module_settings = $resolved;
	}

	/**
	 * Check whether a page-level module should render on this request.
	 *
	 * Used by modules that render via wp_footer / wp_enqueue_scripts (Sale
	 * Notification, Sticky ATC, Shipping Bar, Variation Swatches) where the
	 * card-loop context is no longer active.
	 *
	 * Returns true  — if any Archive Products Grid widget on this page enabled it.
	 * Returns false — if at least one widget was present but all had the toggle off.
	 * Returns null  — no Archive Products Grid widget on this page; caller uses global state.
	 *
	 * @param string $module_key Storzen module key.
	 * @return bool|null
	 */
	public static function is_page_module_enabled( $module_key ) {
		if ( null === self::$page_module_decisions ) {
			return null;
		}
		return isset( self::$page_module_decisions[ $module_key ] )
			? self::$page_module_decisions[ $module_key ]
			: null;
	}

	/**
	 * Clear widget module context after render.
	 */
	public static function clear_active_module_settings() {
		self::$active_module_settings = null;
	}

	/**
	 * Check whether a module is active in the current widget render context.
	 *
	 * Returns true when:
	 *   - We are inside a widget render and the widget toggle is on AND
	 *     the module is globally enabled.
	 * Returns false when:
	 *   - We are inside a widget render and the widget toggle is off.
	 * Returns null when:
	 *   - No widget context is active (caller should fall back to global state).
	 *
	 * @param string $module_key Storzen module key.
	 * @return bool|null
	 */
	public static function is_module_active( $module_key ) {
		if ( null === self::$active_module_settings ) {
			return null;
		}
		return isset( self::$active_module_settings[ $module_key ] )
			? self::$active_module_settings[ $module_key ]
			: null;
	}
}

plugin::instance()->widgets_manager->register(new Storzen_Archive_Grid());
