<?php
/**
 * PowerPack WooCommerce Add To Cart Button.
 *
 * @package PowerPack
 */

namespace PowerpackElements\Modules\Woocommerce\Widgets;

use PowerpackElements\Base\Powerpack_Widget;
use PowerpackElements\Classes\PP_Helper;
use PowerpackElements\Classes\PP_Woo_Helper;

use Elementor\Controls_Manager;
use Elementor\Icons_Manager;
use Elementor\Core\Kits\Documents\Tabs\Global_Colors;
use Elementor\Core\Kits\Documents\Tabs\Global_Typography;
use Elementor\Group_Control_Typography;
use Elementor\Group_Control_Background;
use Elementor\Group_Control_Border;
use Elementor\Group_Control_Box_Shadow;

if ( ! defined( 'ABSPATH' ) ) {
	exit;   // Exit if accessed directly.
}

/**
 * Woo - Add To Cart widget
 *
 * @since 1.4.3
 */
class Woo_Add_To_Cart extends Powerpack_Widget {

	/**
	 * Retrieve Woo - Add To Cart widget categories.
	 *
	 * @access public
	 *
	 * @return array Widget categories.
	 */
	public function get_categories() {
		return parent::get_woo_categories();
	}

	/**
	 * Retrieve Woo - Add To Cart Widget name.
	 *
	 * @since 1.4.3
	 * @access public
	 *
	 * @return string Widget name.
	 */
	public function get_name() {
		return parent::get_widget_name( 'Woo_Add_To_Cart' );
	}

	/**
	 * Retrieve Woo - Add To Cart Widget title.
	 *
	 * @since 1.4.3
	 * @access public
	 *
	 * @return string Widget title.
	 */
	public function get_title() {
		return parent::get_widget_title( 'Woo_Add_To_Cart' );
	}

	/**
	 * Retrieve Woo - Add To Cart Widget icon.
	 *
	 * @since 1.4.3
	 * @access public
	 *
	 * @return string Widget icon.
	 */
	public function get_icon() {
		return parent::get_widget_icon( 'Woo_Add_To_Cart' );
	}

	/**
	 * Get widget keywords.
	 *
	 * Retrieve the list of keywords the Woo - Add To Cart widget belongs to.
	 *
	 * @since 1.4.13.1
	 * @access public
	 *
	 * @return array Widget keywords.
	 */
	public function get_keywords() {
		return parent::get_widget_keywords( 'Woo_Add_To_Cart' );
	}

	/**
	 * Retrieve the list of scripts the Woo - Add to Cart widget depended on.
	 *
	 * @since 1.4.3
	 * @access public
	 *
	 * @return array Widget script dependencies.
	 */
	public function get_script_depends() {
		return [ 'pp-woo-add-to-cart' ];
	}

	/**
	 * Retrieve the list of styles the Woo - Add to Cart widget depended on.
	 *
	 * Used to set style dependencies required to run the widget.
	 *
	 * @since 1.4.3
	 * @access public
	 *
	 * @return array Widget style dependencies.
	 */
	public function get_style_depends() {
		return [
			'pp-woocommerce',
		];
	}

	/**
	 * Whether the widget should be wrapped in Elementor's inner container.
	 *
	 * Dropped when the Optimized Markup experiment is active, so the widget
	 * does not emit a wrapper Elementor has already removed.
	 *
	 * @since 2.11.8
	 * @access public
	 *
	 * @return bool
	 */
	public function has_widget_inner_wrapper(): bool {
		return ! PP_Helper::is_feature_active( 'e_optimized_markup' );
	}

	/**
	 * Register Woo - Add to Cart widget controls.
	 *
	 * Adds different input fields to allow the user to change and customize the widget settings.
	 *
	 * @since 2.0.3
	 * @access protected
	 */
	protected function register_controls() {
		/* Product Control */
		$this->register_content_product_controls();

		/* Button Control */
		$this->register_content_button_controls();

		/* Button Style */
		$this->register_style_button_controls();

		/* Quantity Style */
		$this->register_style_quantity_controls();

		/* Variations Style */
		$this->register_style_variations_controls();
	}

	/**
	 * Register Content Product Controls.
	 *
	 * @since 1.4.3
	 * @access protected
	 *
	 * @return void
	 */
	protected function register_content_product_controls() {

		$this->start_controls_section(
			'section_product_field',
			[
				'label' => esc_html__( 'Product', 'powerpack' ),
				'tab'   => Controls_Manager::TAB_CONTENT,
			]
		);

		$this->add_control(
			'dynamic_product',
			[
				'label'        => esc_html__( 'Dynamic Product?', 'powerpack' ),
				'type'         => Controls_Manager::SWITCHER,
				'return_value' => 'yes',
				'default'      => '',
				'description'  => esc_html__( 'Enable this option and can use on single product page.', 'powerpack' ),
			]
		);

		$this->add_control(
			'product_id',
			[
				'label'     => esc_html__( 'Select Product', 'powerpack' ),
				'type'      => 'pp-query-posts',
				'post_type' => 'product',
				'condition' => [
					'dynamic_product' => '',
				],
			]
		);

		$this->add_control(
			'show_quantity',
			[
				'label'     => esc_html__( 'Show Quantity', 'powerpack' ),
				'type'      => Controls_Manager::SWITCHER,
				'label_off' => esc_html__( 'Hide', 'powerpack' ),
				'label_on'  => esc_html__( 'Show', 'powerpack' ),
				'condition' => [
					'dynamic_product' => '',
				],
			]
		);

		$this->add_control(
			'quantity',
			[
				'label'     => esc_html__( 'Quantity', 'powerpack' ),
				'type'      => Controls_Manager::NUMBER,
				'default'   => 1,
				'min'       => 1,
				'condition' => [
					'show_quantity' => '',
					'dynamic_product' => '',
				],
			]
		);

		$this->add_control(
			'enable_redirect',
			[
				'label'        => esc_html__( 'Auto Redirect', 'powerpack' ),
				'type'         => Controls_Manager::SWITCHER,
				'return_value' => 'yes',
				'default'      => '',
				'description'  => esc_html__( 'Enable this option to redirect cart page after the product gets added to cart', 'powerpack' ),
				'condition'    => [
					'show_quantity' => '',
					'dynamic_product' => '',
				],
			]
		);

		$this->end_controls_section();
	}

	/**
	 * Register Content Button Controls.
	 *
	 * @since 1.4.3
	 * @access protected
	 *
	 * @return void
	 */
	protected function register_content_button_controls() {
		$this->start_controls_section(
			'section_button_field',
			[
				'label' => esc_html__( 'Button', 'powerpack' ),
				'tab'   => Controls_Manager::TAB_CONTENT,
			]
		);
			$this->add_control(
				'btn_text',
				[
					'label'   => esc_html__( 'Text', 'powerpack' ),
					'type'    => Controls_Manager::TEXT,
					'default' => esc_html__( 'Add to cart', 'powerpack' ),
					'dynamic' => [
						'active' => true,
					],
					'condition'    => [
						'dynamic_product' => '',
					],
				]
			);
			$this->add_responsive_control(
				'align',
				[
					'label'        => esc_html__( 'Alignment', 'powerpack' ),
					'type'         => Controls_Manager::CHOOSE,
					'options'      => [
						'left'    => [
							'title' => esc_html__( 'Left', 'powerpack' ),
							'icon'  => 'eicon-text-align-left',
						],
						'center'  => [
							'title' => esc_html__( 'Center', 'powerpack' ),
							'icon'  => 'eicon-text-align-center',
						],
						'right'   => [
							'title' => esc_html__( 'Right', 'powerpack' ),
							'icon'  => 'eicon-text-align-right',
						],
						'justify' => [
							'title' => esc_html__( 'Justified', 'powerpack' ),
							'icon'  => 'eicon-text-align-justify',
						],
					],
					'prefix_class' => 'pp-add-to-cart%s-align-',
					'default'      => 'left',
					/**
					 * The prefix class is kept for saved page data and for the
					 * variations rules in pp-woocommerce.css, which only ship
					 * tablet and mobile breakpoints. These selectors are what
					 * make the alignment itself respond on every registered
					 * breakpoint, including custom ones.
					 */
					'selectors'    => [
						'{{WRAPPER}}' => 'text-align: {{VALUE}};',
					],
				]
			);
			$this->add_control(
				'btn_size',
				[
					'label'   => esc_html__( 'Size', 'powerpack' ),
					'type'    => Controls_Manager::SELECT,
					'default' => 'sm',
					'options' => [
						'xs' => esc_html__( 'Extra Small', 'powerpack' ),
						'sm' => esc_html__( 'Small', 'powerpack' ),
						'md' => esc_html__( 'Medium', 'powerpack' ),
						'lg' => esc_html__( 'Large', 'powerpack' ),
						'xl' => esc_html__( 'Extra Large', 'powerpack' ),
					],
				]
			);
			$this->add_responsive_control(
				'btn_padding',
				[
					'label'      => esc_html__( 'Padding', 'powerpack' ),
					'type'       => Controls_Manager::DIMENSIONS,
					'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
					'selectors'  => [
						'{{WRAPPER}} .elementor-button' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
					],

				]
			);
			$this->add_control(
				'select_btn_icon',
				[
					'label'            => esc_html__( 'Icon', 'powerpack' ),
					'type'             => Controls_Manager::ICONS,
					'fa4compatibility' => 'btn_icon',
					'default'          => [
						'value'   => 'fas fa-shopping-cart',
						'library' => 'fa-solid',
					],
					'condition'    => [
						'dynamic_product' => '',
					],
				]
			);
			$this->add_control(
				'btn_icon_align',
				[
					'label'                => esc_html__( 'Icon Position', 'powerpack' ),
					'type'                 => Controls_Manager::SELECT,
					'default'              => is_rtl() ? 'right' : 'left',
					'options'              => [
						'left'  => esc_html__( 'Before', 'powerpack' ),
						'right' => esc_html__( 'After', 'powerpack' ),
					],
					'selectors_dictionary' => [
						'left'  => is_rtl() ? 'row-reverse' : 'row',
						'right' => is_rtl() ? 'row' : 'row-reverse',
					],
					'selectors'            => [
						'{{WRAPPER}} .elementor-button-content-wrapper' => 'flex-direction: {{VALUE}};',
					],
					'condition'            => [
						'dynamic_product' => '',
					],
				]
			);
			$this->add_control(
				'btn_icon_indent',
				[
					'label'      => esc_html__( 'Icon Spacing', 'powerpack' ),
					'type'       => Controls_Manager::SLIDER,
					'size_units' => [ 'px', 'em', 'rem', 'custom' ],
					'range'      => [
						'px' => [
							'max' => 50,
						],
					],
					'selectors'  => [
						'{{WRAPPER}} .elementor-button-content-wrapper' => 'gap: {{SIZE}}{{UNIT}};',
					],
					'condition'  => [
						'dynamic_product' => '',
					],
				]
			);
		$this->end_controls_section();
	}

	/**
	 * Register Style Button Controls.
	 *
	 * @since 1.4.3
	 * @access protected
	 *
	 * @return void
	 */
	protected function register_style_button_controls() {

		$this->start_controls_section(
			'section_design_button',
			[
				'label' => esc_html__( 'Button', 'powerpack' ),
				'tab'   => Controls_Manager::TAB_STYLE,
			]
		);

		$this->add_group_control(
			Group_Control_Typography::get_type(),
			[
				'name'     => 'button_typography',
				'selector' => '{{WRAPPER}} .pp-button',
				'global'                => [
					'default' => Global_Typography::TYPOGRAPHY_ACCENT,
				],
			]
		);

		$this->start_controls_tabs( 'button_tabs_style' );

			$this->start_controls_tab(
				'button_normal',
				[
					'label' => esc_html__( 'Normal', 'powerpack' ),
				]
			);

				$this->add_control(
					'button_color',
					[
						'label'     => esc_html__( 'Text Color', 'powerpack' ),
						'type'      => Controls_Manager::COLOR,
						'selectors' => [
							'{{WRAPPER}} .pp-button'     => 'color: {{VALUE}};',
							'{{WRAPPER}} .pp-button svg' => 'fill: {{VALUE}};',
						],
					]
				);

				$this->add_group_control(
					Group_Control_Background::get_type(),
					[
						'name'           => 'button_background_color',
						'label'          => esc_html__( 'Background Color', 'powerpack' ),
						'types'          => [ 'classic', 'gradient' ],
						'selector'       => '{{WRAPPER}} .pp-button',
						'fields_options' => [
							'color' => [
								'global'                => [
									'default' => Global_Colors::COLOR_ACCENT,
								],
							],
						],
					]
				);

				$this->add_group_control(
					Group_Control_Border::get_type(),
					[
						'name'        => 'button_border',
						'placeholder' => '',
						'default'     => '',
						'selector'    => '{{WRAPPER}} .pp-button',
					]
				);

				$this->add_control(
					'border_radius',
					[
						'label'      => esc_html__( 'Border Radius', 'powerpack' ),
						'type'       => Controls_Manager::DIMENSIONS,
						'size_units' => [ 'px', '%', 'em', 'rem', 'custom' ],
						'selectors'  => [
							'{{WRAPPER}} .pp-button' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
						],
					]
				);

				$this->add_group_control(
					Group_Control_Box_Shadow::get_type(),
					[
						'name'     => 'button_box_shadow',
						'selector' => '{{WRAPPER}} .pp-button',
					]
				);

				$this->add_control(
					'view_cart_color',
					[
						'label'     => esc_html__( 'View Cart Text Color', 'powerpack' ),
						'type'      => Controls_Manager::COLOR,
						'global'    => [
							'default' => Global_Colors::COLOR_SECONDARY,
						],
						'selectors' => [
							'{{WRAPPER}} .added_to_cart' => 'color: {{VALUE}};',
						],
					]
				);
			$this->end_controls_tab();

			$this->start_controls_tab(
				'button_hover',
				[
					'label' => esc_html__( 'Hover', 'powerpack' ),
				]
			);

				$this->add_control(
					'button_hover_color',
					[
						'label'     => esc_html__( 'Text Color', 'powerpack' ),
						'type'      => Controls_Manager::COLOR,
						'selectors' => [
							'{{WRAPPER}} .pp-button:focus, {{WRAPPER}} .pp-button:hover' => 'color: {{VALUE}};',
							'{{WRAPPER}} .pp-button:focus svg, {{WRAPPER}} .pp-button:hover svg' => 'fill: {{VALUE}};',
						],
					]
				);

				$this->add_group_control(
					Group_Control_Background::get_type(),
					[
						'name'           => 'button_background_hover_color',
						'label'          => esc_html__( 'Background Color', 'powerpack' ),
						'types'          => [ 'classic', 'gradient' ],
						'selector'       => '{{WRAPPER}} .pp-button:focus, {{WRAPPER}} .pp-button:hover',
						'fields_options' => [
							'color' => [
								'global'                => [
									'default' => Global_Colors::COLOR_ACCENT,
								],
							],
						],
					]
				);

				$this->add_control(
					'button_border_hover_color',
					[
						'label'     => esc_html__( 'Border Hover Color', 'powerpack' ),
						'type'      => Controls_Manager::COLOR,
						'global'                => [
							'default' => Global_Colors::COLOR_ACCENT,
						],
						'condition' => [
							'button_border_border!' => '',
						],
						'selectors' => [
							'{{WRAPPER}} .pp-button:focus, {{WRAPPER}} .pp-button:hover' => 'border-color: {{VALUE}};',
						],
					]
				);

				$this->add_control(
					'hover_animation',
					[
						'label' => esc_html__( 'Hover Animation', 'powerpack' ),
						'type'  => Controls_Manager::HOVER_ANIMATION,
					]
				);

				$this->add_control(
					'view_cart_hover_color',
					[
						'label'     => esc_html__( 'View Cart Text Color', 'powerpack' ),
						'type'      => Controls_Manager::COLOR,
						'selectors' => [
							'{{WRAPPER}} .added_to_cart:hover' => 'color: {{VALUE}};',
						],
					]
				);

			$this->end_controls_tab();

		$this->end_controls_tabs();

		$this->end_controls_section();
	}

	/**
	 * Register Style Quantity Controls.
	 *
	 * @since 2.0.0
	 * @access protected
	 *
	 * @return void
	 */
	protected function register_style_quantity_controls() {

		$this->start_controls_section(
			'section_atc_quantity_style',
			[
				'label'      => esc_html__( 'Quantity', 'powerpack' ),
				'tab'        => Controls_Manager::TAB_STYLE,
				/**
				 * A quantity field is rendered either by WooCommerce in the
				 * dynamic product form or by this widget as the AJAX quantity
				 * input, so either setting can bring one onto the page.
				 */
				'conditions' => [
					'relation' => 'or',
					'terms'    => [
						[
							'name'     => 'dynamic_product',
							'operator' => '===',
							'value'    => 'yes',
						],
						[
							'name'     => 'show_quantity',
							'operator' => '===',
							'value'    => 'yes',
						],
					],
				],
			]
		);

		$this->add_control(
			'spacing',
			[
				'label' => esc_html__( 'Spacing', 'powerpack' ),
				'type' => Controls_Manager::SLIDER,
				'size_units' => [ 'px', 'em', 'rem', 'custom' ],
				'selectors' => [
					'{{WRAPPER}} .quantity + .button, {{WRAPPER}} .pp-add-to-cart-qty-ajax + .pp-button' => 'margin-inline-start: {{SIZE}}{{UNIT}};',
				],
			]
		);

		$this->add_group_control(
			Group_Control_Typography::get_type(),
			[
				'name' => 'quantity_typography',
				'selector' => '{{WRAPPER}} .quantity .qty, {{WRAPPER}} .pp-woo-add-to-cart .pp-add-to-cart-qty-ajax',
			]
		);

		$this->add_group_control(
			Group_Control_Border::get_type(),
			[
				'name' => 'quantity_border',
				'selector' => '{{WRAPPER}} .quantity .qty, {{WRAPPER}} .pp-woo-add-to-cart .pp-add-to-cart-qty-ajax',
				'exclude' => [ 'color' ],
			]
		);

		$this->add_control(
			'quantity_border_radius',
			[
				'label' => esc_html__( 'Border Radius', 'powerpack' ),
				'type' => Controls_Manager::DIMENSIONS,
				'size_units' => [ 'px', '%', 'em', 'rem', 'custom' ],
				'selectors' => [
					'{{WRAPPER}} .quantity .qty, {{WRAPPER}} .pp-woo-add-to-cart .pp-add-to-cart-qty-ajax' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
				],
			]
		);

		$this->add_control(
			'quantity_padding',
			[
				'label' => esc_html__( 'Padding', 'powerpack' ),
				'type' => Controls_Manager::DIMENSIONS,
				'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
				'selectors' => [
					'{{WRAPPER}} .quantity .qty, {{WRAPPER}} .pp-woo-add-to-cart .pp-add-to-cart-qty-ajax' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
				],
			]
		);

		$this->start_controls_tabs( 'quantity_style_tabs' );

		$this->start_controls_tab( 'quantity_style_normal',
			[
				'label' => esc_html__( 'Normal', 'powerpack' ),
			]
		);

		$this->add_control(
			'quantity_text_color',
			[
				'label' => esc_html__( 'Text Color', 'powerpack' ),
				'type' => Controls_Manager::COLOR,
				'selectors' => [
					'{{WRAPPER}} .quantity .qty, {{WRAPPER}} .pp-woo-add-to-cart .pp-add-to-cart-qty-ajax' => 'color: {{VALUE}}',
				],
			]
		);

		$this->add_control(
			'quantity_bg_color',
			[
				'label' => esc_html__( 'Background Color', 'powerpack' ),
				'type' => Controls_Manager::COLOR,
				'selectors' => [
					'{{WRAPPER}} .quantity .qty, {{WRAPPER}} .pp-woo-add-to-cart .pp-add-to-cart-qty-ajax' => 'background-color: {{VALUE}}',
				],
			]
		);

		$this->add_control(
			'quantity_border_color',
			[
				'label' => esc_html__( 'Border Color', 'powerpack' ),
				'type' => Controls_Manager::COLOR,
				'selectors' => [
					'{{WRAPPER}} .quantity .qty, {{WRAPPER}} .pp-woo-add-to-cart .pp-add-to-cart-qty-ajax' => 'border-color: {{VALUE}}',
				],
			]
		);

		$this->end_controls_tab();

		$this->start_controls_tab( 'quantity_style_focus',
			[
				'label' => esc_html__( 'Focus', 'powerpack' ),
			]
		);

		$this->add_control(
			'quantity_text_color_focus',
			[
				'label' => esc_html__( 'Text Color', 'powerpack' ),
				'type' => Controls_Manager::COLOR,
				'selectors' => [
					'{{WRAPPER}} .quantity .qty:focus, {{WRAPPER}} .pp-woo-add-to-cart .pp-add-to-cart-qty-ajax:focus' => 'color: {{VALUE}}',
				],
			]
		);

		$this->add_control(
			'quantity_bg_color_focus',
			[
				'label' => esc_html__( 'Background Color', 'powerpack' ),
				'type' => Controls_Manager::COLOR,
				'selectors' => [
					'{{WRAPPER}} .quantity .qty:focus, {{WRAPPER}} .pp-woo-add-to-cart .pp-add-to-cart-qty-ajax:focus' => 'background-color: {{VALUE}}',
				],
			]
		);

		$this->add_control(
			'quantity_border_color_focus',
			[
				'label' => esc_html__( 'Border Color', 'powerpack' ),
				'type' => Controls_Manager::COLOR,
				'selectors' => [
					'{{WRAPPER}} .quantity .qty:focus, {{WRAPPER}} .pp-woo-add-to-cart .pp-add-to-cart-qty-ajax:focus' => 'border-color: {{VALUE}}',
				],
			]
		);

		$this->add_control(
			'quantity_transition',
			[
				'label' => esc_html__( 'Transition Duration', 'powerpack' ),
				'type' => Controls_Manager::SLIDER,
				'default' => [
					'size' => 0.2,
				],
				'range' => [
					'px' => [
						'max' => 2,
						'step' => 0.1,
					],
				],
				'selectors' => [
					'{{WRAPPER}} .quantity .qty, {{WRAPPER}} .pp-woo-add-to-cart .pp-add-to-cart-qty-ajax' => 'transition: all {{SIZE}}s',
				],
			]
		);

		$this->end_controls_tab();

		$this->end_controls_tabs();

		$this->end_controls_section();
	}

	/**
	 * Register Style Variations Controls.
	 *
	 * @since 2.0.0
	 * @access protected
	 *
	 * @return void
	 */
	protected function register_style_variations_controls() {

		$this->start_controls_section(
			'section_atc_variations_style',
			[
				'label'     => esc_html__( 'Variations', 'powerpack' ),
				'tab'       => Controls_Manager::TAB_STYLE,
				/**
				 * Every selector in this section targets the variations table,
				 * which only woocommerce_template_single_add_to_cart() emits.
				 * That runs in the dynamic product branch alone, so gating on
				 * show_quantity as well only ever showed dead controls.
				 */
				'condition' => [
					'dynamic_product' => 'yes',
				],
			]
		);

		$this->add_control(
			'variations_width',
			[
				'label'      => esc_html__( 'Width', 'powerpack' ),
				'type'       => Controls_Manager::SLIDER,
				'size_units' => [ 'px', '%', 'em', 'rem', 'custom' ],
				'default'    => [
					'unit' => '%',
				],
				'selectors'  => [
					'{{WRAPPER}} form.cart .variations' => 'width: {{SIZE}}{{UNIT}}',
				],
			]
		);

		$this->add_control(
			'variations_spacing',
			[
				'label'      => esc_html__( 'Spacing', 'powerpack' ),
				'type'       => Controls_Manager::SLIDER,
				'size_units' => [ 'px', 'em', 'rem', 'custom' ],
				'selectors'  => [
					'{{WRAPPER}} form.cart .variations' => 'margin-bottom: {{SIZE}}{{UNIT}}',
				],
			]
		);

		$this->add_control(
			'variations_space_between',
			[
				'label'      => esc_html__( 'Space Between', 'powerpack' ),
				'type'       => Controls_Manager::SLIDER,
				'size_units' => [ 'px', 'em', 'rem', 'custom' ],
				'selectors'  => [
					'{{WRAPPER}} form.cart table.variations tr:not(:last-child)' => 'margin-bottom: {{SIZE}}{{UNIT}}',
				],
			]
		);

		$this->add_control(
			'heading_variations_label_style',
			[
				'label'      => esc_html__( 'Label', 'powerpack' ),
				'type'       => Controls_Manager::HEADING,
				'separator'  => 'before',
			]
		);

		$this->add_control(
			'variations_label_color_focus',
			[
				'label' => esc_html__( 'Color', 'powerpack' ),
				'type' => Controls_Manager::COLOR,
				'selectors' => [
					'{{WRAPPER}} form.cart table.variations label' => 'color: {{VALUE}}',
				],
			]
		);

		$this->add_control(
			'variations_label_bg_color',
			[
				'label' => esc_html__( 'Background Color', 'powerpack' ),
				'type' => Controls_Manager::COLOR,
				'selectors' => [
					'{{WRAPPER}} form.cart table.variations td.label' => 'background-color: {{VALUE}}',
				],
			]
		);

		$this->add_group_control(
			Group_Control_Typography::get_type(),
			[
				'name'       => 'variations_label_typography',
				'selector'   => '{{WRAPPER}} form.cart table.variations label',
			]
		);

		$this->add_control(
			'heading_variations_select_style',
			[
				'label'      => esc_html__( 'Select field', 'powerpack' ),
				'type'       => Controls_Manager::HEADING,
				'separator'  => 'before',
			]
		);

		$this->add_control(
			'variations_select_color',
			[
				'label' => esc_html__( 'Color', 'powerpack' ),
				'type' => Controls_Manager::COLOR,
				'selectors' => [
					'{{WRAPPER}} form.cart table.variations td.value select' => 'color: {{VALUE}}',
				],
			]
		);

		$this->add_control(
			'variations_select_bg_color',
			[
				'label' => esc_html__( 'Background Color', 'powerpack' ),
				'type' => Controls_Manager::COLOR,
				'selectors' => [
					'{{WRAPPER}} form.cart table.variations td.value' => 'background-color: {{VALUE}}',
				],
			]
		);

		$this->add_control(
			'variations_select_border_color',
			[
				'label' => esc_html__( 'Border Color', 'powerpack' ),
				'type' => Controls_Manager::COLOR,
				'selectors' => [
					'{{WRAPPER}} form.cart table.variations td.value' => 'border: 1px solid {{VALUE}}',
				],
			]
		);

		$this->add_group_control(
			Group_Control_Typography::get_type(),
			[
				'name' => 'variations_select_typography',
				'selector' => '{{WRAPPER}} form.cart table.variations td.value select, {{WRAPPER}} form.cart table.variations td.value',
			]
		);

		$this->add_control(
			'variations_select_border_radius',
			[
				'label' => esc_html__( 'Border Radius', 'powerpack' ),
				'type' => Controls_Manager::SLIDER,
				'size_units' => [ 'px', '%', 'em', 'rem', 'custom' ],
				'selectors' => [
					'{{WRAPPER}} form.cart table.variations td.value' => 'border-radius: {{SIZE}}{{UNIT}}',
				],
			]
		);

		$this->end_controls_section();
	}

	/**
	 * Render Woo - Add to Cart output on the frontend.
	 *
	 * Written in PHP and used to generate the final HTML.
	 *
	 * @since 1.4.3
	 * @access protected
	 *
	 * @return void
	 */
	protected function render() {
		$settings = $this->get_settings_for_display();

		/*
		 * Settings are stored as JSON in post meta and are writable by anyone
		 * who can edit the page, so the size is not trusted just because the
		 * panel offers a fixed list. It is spliced into a class attribute
		 * inside HTML that is echoed raw, where esc_attr() is not applied.
		 */
		$btn_size = $this->get_button_size( $settings );

		// Snapshot the global so this widget cannot leak its product into
		// whatever renders after it. See the restore at the end of render().
		$previous_product = isset( $GLOBALS['product'] ) ? $GLOBALS['product'] : null;

		if ( 'yes' === $settings['dynamic_product'] ) {
			/**
			 * Fires before a Woo builder widget renders its output.
			 *
			 * Used by the Woo builder preview to swap in a sample product
			 * while a template is being edited.
			 *
			 * @since 2.1.0
			 *
			 * @param \Elementor\Widget_Base $widget The widget being rendered.
			 */
			do_action( 'pp_woo_builder_widget_before_render', $this );
			global $product;

			$product = wc_get_product();

			if ( PP_Helper::is_edit_mode() ) {
				/*
				 * Not wp_kses_post(): the allowed post tags drop form, input and
				 * select, which is most of an add to cart form. The sibling Woo
				 * builder widgets can afford it because they preview text. This
				 * is WooCommerce template output and runs in the editor only,
				 * the same trust level as the $form echo below.
				 */
				echo PP_Woo_Helper::get_instance()->default( $this->get_name() ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- WooCommerce template output.
			} elseif ( $product instanceof \WC_Product ) {
				echo '<div class="pp-woo-add-to-cart pp-woo-product-' . esc_attr( $product->get_type() ) . '">';
					ob_start();
					woocommerce_template_single_add_to_cart();
					$form = ob_get_clean();
					$form = str_replace( 'single_add_to_cart_button', 'single_add_to_cart_button elementor-button elementor-size-' . $btn_size . ' pp-button', $form );
					echo $form; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- WooCommerce template output; the only interpolated value is the whitelisted $btn_size.
				echo '</div>';
			}
			/**
			 * Fires after a Woo builder widget has rendered its output.
			 *
			 * Counterpart to `pp_woo_builder_widget_before_render`; used by the
			 * Woo builder preview to restore the query it swapped out.
			 *
			 * @since 2.1.0
			 *
			 * @param \Elementor\Widget_Base $widget The widget that was rendered.
			 */
			do_action( 'pp_woo_builder_widget_after_render', $this );
		} else {
			$product_data = null;

			if ( ! empty( $settings['product_id'] ) ) {
				$product_data = get_post( absint( $settings['product_id'] ) );
			}

			/*
			 * post_status matters as much as post_type here. The picker only
			 * offers published products, but unpublishing one is exactly how a
			 * store pulls it from sale, and without this check the widget kept
			 * rendering a working add to cart button for a draft or trashed
			 * product long after that.
			 */
			$product = false;

			if ( $product_data instanceof \WP_Post
				&& in_array( $product_data->post_type, [ 'product', 'product_variation' ], true )
				&& 'publish' === $product_data->post_status ) {
				$product = wc_setup_product_data( $product_data );
			}

			if ( $product ) {
				if ( 'yes' === $settings['show_quantity'] ) {
					$this->render_ajax_button( $settings, $product, true );
				} else {
					$this->render_ajax_button( $settings, $product );
				}
			} else {
				$this->render_editor_placeholder(
					[
						'body' => esc_html__( 'Select a product in the widget settings.', 'powerpack' ),
					]
				);
			}
		}

		/*
		 * Both branches leave the global set: wc_setup_product_data() assigns
		 * it and wc_get_product() is assigned to it directly. Neither restores
		 * it, so without this anything rendered afterwards that reads
		 * global $product without setting it first - other PP Woo widgets,
		 * wc_get_template() calls, themes - would see this widget's product.
		 */
		$GLOBALS['product'] = $previous_product;
	}

	/**
	 * Resolve the button size setting against the sizes the control offers.
	 *
	 * @since 3.0.0
	 * @access private
	 *
	 * @param array $settings Widget settings.
	 * @return string One of the registered size keys.
	 */
	private function get_button_size( $settings ) {
		$sizes = [ 'xs', 'sm', 'md', 'lg', 'xl' ];

		return in_array( $settings['btn_size'], $sizes, true ) ? $settings['btn_size'] : 'sm';
	}

	/**
	 * Render the AJAX add to cart button for a manually selected product.
	 *
	 * Takes the settings from the caller rather than resolving them again:
	 * get_settings_for_display() re-runs the dynamic tag parser over btn_text
	 * on every call, which in the editor happens on each re-render.
	 *
	 * @since 1.4.3
	 * @access private
	 *
	 * @param array       $settings       Widget settings, already resolved by render().
	 * @param \WC_Product $product        Product the button adds to the cart.
	 * @param bool        $show_quantity  Whether to precede the button with a quantity input.
	 * @return void
	 */
	private function render_ajax_button( $settings, $product, $show_quantity = false ) {
		if ( $product ) {

			$product_id   = $product->get_id();
			$product_type = $product->get_type();

			$class = array_filter(
				[
					'pp-button',
					'elementor-button',
					$settings['hover_animation'] ? 'elementor-animation-' . $settings['hover_animation'] : '',
					'elementor-size-' . $this->get_button_size( $settings ),
					'product_type_' . $product_type,
					$product->is_purchasable() && $product->is_in_stock() ? 'add_to_cart_button' : '',
					$product->supports( 'ajax_add_to_cart' ) ? 'ajax_add_to_cart' : '',
				]
			);

			if ( 'yes' === $settings['enable_redirect'] ) {
				$class[] = 'pp-redirect';
			}

			$this->add_render_attribute(
				'button',
				[
					'rel'             => 'nofollow',
					'href'            => $product->add_to_cart_url(),
					'data-quantity'   => $settings['quantity'],
					'data-product_id' => $product_id,
					'class'           => $class,
				]
			);

			$this->add_render_attribute(
				'icon-align',
				'class',
				[
					'elementor-button-icon',
				]
			);

			if ( ! isset( $settings['btn_icon'] ) && ! Icons_Manager::is_migration_allowed() ) {
				// add old default
				$settings['btn_icon'] = 'fa fa-shopping-cart';
			}

			$has_icon = ! empty( $settings['btn_icon'] );

			if ( $has_icon ) {
				$this->add_render_attribute( 'i', 'class', $settings['btn_icon'] );
				$this->add_render_attribute( 'i', 'aria-hidden', 'true' );
			}

			if ( ! $has_icon && ! empty( $settings['select_btn_icon']['value'] ) ) {
				$has_icon = true;
			}
			$migrated = isset( $settings['__fa4_migrated']['select_btn_icon'] );
			$is_new   = ! isset( $settings['btn_icon'] ) && Icons_Manager::is_migration_allowed();
			?>
			<div class="pp-woo-add-to-cart">
				<?php
				if ( true === $show_quantity ) {
					$total_get_stock_quantity = 0;
					$min_value                = 0;

					if ( $product->is_purchasable() && $product->is_in_stock() ) {
						$total_get_stock_quantity = (int) $product->get_stock_quantity();
						$min_value                = 1;
					}

					$quantity_class = [
						'pp-add-to-cart-qty-ajax',
					];

					$quantity_attr = [
						'type'       => 'number',
						'id'         => 'pp-add-to-cart-qty-' . $this->get_id(),
						'value'      => $min_value,
						'min'        => $min_value,
						'step'       => 1,
						'inputmode'  => 'numeric',
						// Elementor escapes attribute values with esc_attr(), so this must stay unescaped.
						'aria-label' => __( 'Quantity', 'powerpack' ),
						'class'      => $quantity_class,
					];

					if ( ! empty( $total_get_stock_quantity ) ) {
						$quantity_attr['max'] = $total_get_stock_quantity;
					}

					$this->add_render_attribute(
						'input-number',
						$quantity_attr
					);
					?>
					<input <?php $this->print_render_attribute_string( 'input-number' ); ?>>
					<?php
				}
				?>
				<a <?php $this->print_render_attribute_string( 'button' ); ?>>
					<span class="elementor-button-content-wrapper">
						<?php
						if ( $has_icon ) {
							?>
							<span <?php $this->print_render_attribute_string( 'icon-align' ); ?>>
							<?php
							if ( $is_new || $migrated ) {
								Icons_Manager::render_icon( $settings['select_btn_icon'], [ 'aria-hidden' => 'true' ] );
							} elseif ( ! empty( $settings['btn_icon'] ) ) {
								?>
								<i <?php $this->print_render_attribute_string( 'i' ); ?>></i>
								<?php
							}
							?>
							</span>
							<?php
						}
						?>
						<span class="elementor-button-text"><?php echo wp_kses_post( $settings['btn_text'] ); ?></span>
					</span>
				</a>
			</div>
			<?php
		}
	}
}
