<?php

namespace Quicker\Core\Frontend;

defined( 'ABSPATH' ) || exit;

use Quicker\Utils\Singleton;

/**
 * Base Class
 *
 * @since 1.0.0
 */
class DirectCheckout {

	use Singleton;

	/**
	 * Initialize all modules.
	 *
	 * @since 1.0.0
	 *
	 * @return void
	 */

	public function init() {
		if ( ! class_exists( 'WooCommerce' ) ) {
			return;
		}
		$settings = \Quicker\Utils\Helper::get_settings();
		add_filter( 'woocommerce_loop_add_to_cart_link', array( $this, 'replace_cart_url' ), 10, 2 );

		if ( 'yes' == $settings['enable_single_buy_now'] ) {
			add_action(
				'wp_footer',
				function () {
					if ( is_product() ) {
						$settings = \Quicker\Utils\Helper::get_settings();
						global $product;
						if ( ! $product instanceof \WC_Product ) {
							return;
						}
						// Respect scoping: only apply if product matches selected IDs or categories (if any selected)
						$should_apply = $this->should_apply_direct_checkout_for_product( $product, $settings );
						if ( ! $should_apply ) {
							return;
						}

						$product_id = $product->get_id();
						$add_to_cart_url = '';
						if ( $settings['enable_buy_now'] === 'checkout' ) {
							$add_to_cart_url = wc_get_checkout_url() . '?add-to-cart=' . $product_id;
						} elseif ( $settings['enable_buy_now'] === 'custom_url' ) {
							$add_to_cart_url = $settings['custom_cart_url'];
						}
						if ( ! empty( $add_to_cart_url ) ) :
							?>
							<script>
								document.addEventListener('DOMContentLoaded', function () {
									const form = document.querySelector('form.cart');
									if (form) {
										form.action = "<?php echo esc_url( $add_to_cart_url ); ?>";
									}
								});
							</script>
							<?php
						endif;
					}
				}
			);
		}

		add_filter( 'woocommerce_product_add_to_cart_text', array( $this, 'custom_buy_now_single_product' ), 10, 1 );
		add_filter( 'woocommerce_product_single_add_to_cart_text', array( $this, 'custom_buy_now_single_product' ), 10, 1 );
		// customize checkout field (classic checkout)
		add_filter( 'woocommerce_checkout_fields', array( $this, 'customize_checkout_fields' ) );
		// customize checkout field (block checkout) - CSS fallback for themes that don't support locale hidden.
		add_action( 'wp_head', array( $this, 'block_checkout_hide_fields_css' ) );
		// Disable validation for hidden fields in Block Checkout.
		add_filter( 'woocommerce_get_default_address_fields', array( $this, 'block_checkout_disable_required_fields' ), 99 );
		add_filter( 'woocommerce_billing_fields', array( $this, 'block_checkout_disable_billing_required' ), 99 );
		add_filter( 'woocommerce_shipping_fields', array( $this, 'block_checkout_disable_shipping_required' ), 99 );

		// Block Checkout Store API filters.
		add_filter( 'woocommerce_store_api_checkout_order_processed', array( $this, 'block_checkout_skip_validation' ), 5 );

		// Make phone/company/address_2 fields hidden if disabled in settings.
		add_filter( 'woocommerce_checkout_phone_field', array( $this, 'maybe_hide_phone_field' ) );
		add_filter( 'woocommerce_checkout_company_field', array( $this, 'maybe_hide_company_field' ) );
		add_filter( 'woocommerce_checkout_address_2_field', array( $this, 'maybe_hide_address_2_field' ) );
		add_filter( 'default_option_woocommerce_checkout_phone_field', array( $this, 'maybe_hide_phone_field' ) );
		add_filter( 'default_option_woocommerce_checkout_company_field', array( $this, 'maybe_hide_company_field' ) );
		add_filter( 'default_option_woocommerce_checkout_address_2_field', array( $this, 'maybe_hide_address_2_field' ) );

		// Store API schema filters for Block Checkout validation.
		add_filter( 'woocommerce_get_country_locale', array( $this, 'modify_country_locale_for_disabled_fields' ), 99 );
		add_filter( 'woocommerce_default_address_fields', array( $this, 'modify_default_address_fields' ), 99 );

		// Set default country if country field is disabled.
		add_filter( 'default_checkout_billing_country', array( $this, 'set_default_country' ), 99 );
		add_filter( 'default_checkout_shipping_country', array( $this, 'set_default_country' ), 99 );
	}

	/**
	 * Set default country if country field is disabled.
	 *
	 * @param string $country Default country.
	 * @return string Modified country.
	 */
	public function set_default_country( $country ) {
		$checkout_fields = \Quicker\Utils\Helper::get_checkout_fields( -1 );
		$disabled_fields = $this->get_disabled_field_names( $checkout_fields );

		if ( in_array( 'billing_country', $disabled_fields, true ) ) {
			// Return WooCommerce base country as default.
			return WC()->countries->get_base_country();
		}

		return $country;
	}

	/**
	 * Modify country locale to make disabled fields optional and hidden.
	 * This is the correct way to hide fields in Block Checkout.
	 *
	 * @param array $locale Country locale settings.
	 * @return array Modified locale.
	 */
	public function modify_country_locale_for_disabled_fields( $locale ) {
		$checkout_fields = \Quicker\Utils\Helper::get_checkout_fields( -1 );
		$disabled_fields = $this->get_disabled_field_names( $checkout_fields );

		if ( empty( $disabled_fields ) ) {
			return $locale;
		}

		// Map billing field names to locale keys.
		$field_to_locale = array(
			'billing_postcode'   => 'postcode',
			'billing_city'       => 'city',
			'billing_state'      => 'state',
			'billing_address_1'  => 'address_1',
			'billing_address_2'  => 'address_2',
			'billing_first_name' => 'first_name',
			'billing_last_name'  => 'last_name',
			'billing_company'    => 'company',
			'billing_phone'      => 'phone',
		);

		// Apply to all countries in locale - set both required: false and hidden: true.
		foreach ( $locale as $country_code => $fields ) {
			foreach ( $field_to_locale as $billing_field => $locale_key ) {
				if ( in_array( $billing_field, $disabled_fields, true ) ) {
					$locale[ $country_code ][ $locale_key ] = array(
						'required' => false,
						'hidden'   => true,
					);
				}
			}
		}

		return $locale;
	}

	/**
	 * Modify default address fields to make disabled fields optional.
	 *
	 * @param array $fields Default address fields.
	 * @return array Modified fields.
	 */
	public function modify_default_address_fields( $fields ) {
		$checkout_fields = \Quicker\Utils\Helper::get_checkout_fields( -1 );
		$disabled_fields = $this->get_disabled_field_names( $checkout_fields );

		if ( empty( $disabled_fields ) ) {
			return $fields;
		}

		// Map billing field names to address field keys.
		$field_map = array(
			'billing_first_name' => 'first_name',
			'billing_last_name'  => 'last_name',
			'billing_company'    => 'company',
			'billing_address_1'  => 'address_1',
			'billing_address_2'  => 'address_2',
			'billing_city'       => 'city',
			'billing_state'      => 'state',
			'billing_postcode'   => 'postcode',
			'billing_country'    => 'country',
			'billing_phone'      => 'phone',
		);

		foreach ( $field_map as $billing_field => $address_key ) {
			if ( in_array( $billing_field, $disabled_fields, true ) && isset( $fields[ $address_key ] ) ) {
				$fields[ $address_key ]['required'] = false;
			}
		}

		return $fields;
	}

	/**
	 * Hide phone field if disabled in Quicker settings.
	 *
	 * @param string $value Field setting value.
	 * @return string Modified setting.
	 */
	public function maybe_hide_phone_field( $value ) {
		$checkout_fields = \Quicker\Utils\Helper::get_checkout_fields( -1 );
		$disabled_fields = $this->get_disabled_field_names( $checkout_fields );

		if ( in_array( 'billing_phone', $disabled_fields, true ) ) {
			return 'hidden';
		}

		return $value;
	}

	/**
	 * Hide company field if disabled in Quicker settings.
	 *
	 * @param string $value Field setting value.
	 * @return string Modified setting.
	 */
	public function maybe_hide_company_field( $value ) {
		$checkout_fields = \Quicker\Utils\Helper::get_checkout_fields( -1 );
		$disabled_fields = $this->get_disabled_field_names( $checkout_fields );

		if ( in_array( 'billing_company', $disabled_fields, true ) ) {
			return 'hidden';
		}

		return $value;
	}

	/**
	 * Hide address_2 field if disabled in Quicker settings.
	 *
	 * @param string $value Field setting value.
	 * @return string Modified setting.
	 */
	public function maybe_hide_address_2_field( $value ) {
		$checkout_fields = \Quicker\Utils\Helper::get_checkout_fields( -1 );
		$disabled_fields = $this->get_disabled_field_names( $checkout_fields );

		if ( in_array( 'billing_address_2', $disabled_fields, true ) ) {
			return 'hidden';
		}

		return $value;
	}

	/**
	 * Clear validation errors for disabled fields in Block Checkout.
	 *
	 * @param \WC_Order $order The order being processed.
	 */
	public function block_checkout_skip_validation( $order ) {
		// Clear any notices for disabled fields.
		$checkout_fields = \Quicker\Utils\Helper::get_checkout_fields( -1 );
		$disabled_fields = $this->get_disabled_field_names( $checkout_fields );

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

		// Get all notices and filter out ones for disabled fields.
		$notices = wc_get_notices( 'error' );
		if ( ! empty( $notices ) ) {
			wc_clear_notices();
			foreach ( $notices as $notice ) {
				$notice_message = is_array( $notice ) ? ( $notice['notice'] ?? '' ) : $notice;
				$should_keep = true;

				foreach ( $disabled_fields as $field_name ) {
					$field_label = $this->get_field_label( $field_name );
					if ( ! empty( $field_label ) && stripos( $notice_message, $field_label ) !== false ) {
						$should_keep = false;
						break;
					}
				}

				if ( $should_keep ) {
					wc_add_notice( $notice_message, 'error' );
				}
			}
		}
	}

	/**
	 * Get field label from field name.
	 *
	 * @param string $field_name Field name.
	 * @return string Field label.
	 */
	private function get_field_label( $field_name ) {
		$labels = array(
			'billing_phone'      => __( 'Phone', 'quicker' ),
			'billing_email'      => __( 'Email', 'quicker' ),
			'billing_first_name' => __( 'First name', 'quicker' ),
			'billing_last_name'  => __( 'Last name', 'quicker' ),
			'billing_company'    => __( 'Company', 'quicker' ),
			'billing_address_1'  => __( 'Address', 'quicker' ),
			'billing_address_2'  => __( 'Apartment', 'quicker' ),
			'billing_city'       => __( 'City', 'quicker' ),
			'billing_state'      => __( 'State', 'quicker' ),
			'billing_postcode'   => __( 'Postcode', 'quicker' ),
			'billing_country'    => __( 'Country', 'quicker' ),
		);

		return $labels[ $field_name ] ?? '';
	}

	/**
	 * Disable required validation for hidden fields in Block Checkout (address fields).
	 *
	 * @param array $fields Default address fields.
	 * @return array Modified address fields.
	 */
	public function block_checkout_disable_required_fields( $fields ) {
		$checkout_fields = \Quicker\Utils\Helper::get_checkout_fields( -1 );
		$disabled_fields = $this->get_disabled_field_names( $checkout_fields );

		// Map address field keys to checkout field names.
		$address_to_billing = array(
			'first_name' => 'billing_first_name',
			'last_name'  => 'billing_last_name',
			'company'    => 'billing_company',
			'address_1'  => 'billing_address_1',
			'address_2'  => 'billing_address_2',
			'city'       => 'billing_city',
			'state'      => 'billing_state',
			'postcode'   => 'billing_postcode',
			'country'    => 'billing_country',
			'phone'      => 'billing_phone',
		);

		foreach ( $address_to_billing as $address_key => $billing_key ) {
			if ( in_array( $billing_key, $disabled_fields, true ) && isset( $fields[ $address_key ] ) ) {
				$fields[ $address_key ]['required'] = false;
			}
		}

		return $fields;
	}

	/**
	 * Disable required validation for hidden billing fields.
	 *
	 * @param array $fields Billing fields.
	 * @return array Modified billing fields.
	 */
	public function block_checkout_disable_billing_required( $fields ) {
		$checkout_fields = \Quicker\Utils\Helper::get_checkout_fields( -1 );
		$disabled_fields = $this->get_disabled_field_names( $checkout_fields );

		foreach ( $disabled_fields as $field_name ) {
			if ( isset( $fields[ $field_name ] ) ) {
				$fields[ $field_name ]['required'] = false;
			}
		}

		return $fields;
	}

	/**
	 * Disable required validation for hidden shipping fields.
	 *
	 * @param array $fields Shipping fields.
	 * @return array Modified shipping fields.
	 */
	public function block_checkout_disable_shipping_required( $fields ) {
		$checkout_fields = \Quicker\Utils\Helper::get_checkout_fields( -1 );
		$disabled_fields = $this->get_disabled_field_names( $checkout_fields );

		// Convert billing field names to shipping.
		$shipping_disabled = array();
		foreach ( $disabled_fields as $field_name ) {
			$shipping_name = str_replace( 'billing_', 'shipping_', $field_name );
			$shipping_disabled[] = $shipping_name;
		}

		foreach ( $shipping_disabled as $field_name ) {
			if ( isset( $fields[ $field_name ] ) ) {
				$fields[ $field_name ]['required'] = false;
			}
		}

		return $fields;
	}

	/**
	 * Get array of disabled field names.
	 *
	 * @param array $checkout_fields Checkout fields configuration.
	 * @return array Array of disabled field names.
	 */
	private function get_disabled_field_names( $checkout_fields ) {
		$disabled = array();
		foreach ( $checkout_fields as $key => $value ) {
			if ( empty( $value['field_name'] ) || ! empty( $value['field_position'] ) ) {
				continue;
			}
			// Only treat a field as disabled when field_enabled is explicitly "no".
			// An unset/empty value must NOT hide the default WC field (e.g. billing_company).
			$raw_enabled = $value['field_enabled'] ?? '';
			if ( '' === $raw_enabled ) {
				continue;
			}
			if ( false === \Quicker\Utils\Helper::format_input_value( $raw_enabled ) ) {
				$disabled[] = $value['field_name'];
			}
		}
		return $disabled;
	}


	public function custom_buy_now_single_product( $text ) {
		// Only change the text on single product pages when the form action (checkout URL) is overridden.
		if ( ! is_product() ) {
			return $text;
		}
		$settings = \Quicker\Utils\Helper::get_settings();
		if ( empty( $settings['enable_single_buy_now'] ) || $settings['enable_single_buy_now'] !== 'yes' ) {
			return $text;
		}
		if ( empty( $settings['enable_buy_now'] ) || $settings['enable_buy_now'] === 'no' ) {
			return $text;
		}
		global $product;
		if ( ! $product instanceof \WC_Product ) {
			return $text;
		}
		if ( ! $this->should_apply_direct_checkout_for_product( $product, $settings ) ) {
			return $text;
		}
		// At this point, the checkout URL is being changed for the button; apply custom label if provided.
		if ( ! empty( $settings['direct_checkout_button_text'] ) ) {
			return $settings['direct_checkout_button_text'];
		}
		return $text;
	}

	/**
	 * Add product link
	 *
	 * @param [type] $add_to_cart_html
	 * @param [type] $product
	 * @param [type] $args
	 */
	public function replace_cart_url( $button, $product ) {
		$settings = \Quicker\Utils\Helper::get_settings();
		if ( $settings['enable_buy_now'] !== 'no' && (
			is_shop() || is_product_category() || is_product_tag()
		) ) {
			// Respect scoping: only apply if product matches selected IDs or categories (if any selected)
			if ( ! $this->should_apply_direct_checkout_for_product( $product, $settings ) ) {
				return $button;
			}
			if ( $product->is_purchasable() && $product->is_in_stock() && ! $product->is_type( 'variable' ) ) {
				$product_id      = $product->get_id();
				$add_to_cart_url = '';
				if ( $settings['enable_buy_now'] === 'checkout' ) {
					$add_to_cart_url = wc_get_checkout_url() . '?add-to-cart=' . $product_id;
				} elseif ( $settings['enable_buy_now'] === 'custom_url' ) {
					$add_to_cart_url = $settings['custom_cart_url'];
				}
				if ( empty( $add_to_cart_url ) ) {
					return $button;
				}
				$button_text = ! empty( $settings['direct_checkout_button_text'] ) ? esc_html( $settings['direct_checkout_button_text'] ) : $product->add_to_cart_text();
				return '<a href="' . esc_url( $add_to_cart_url ) . '" class="button add_to_cart_button">' . $button_text . '</a>';
			}
		}

		return $button;
	}


	/**
	 * Add text in button
	 *
	 * @param [type] $product
	 * @param string $btn_class
	 */
	public function get_checkout_btn( $product, $btn_class = '' ) {
		$btn = '';

		extract( \Quicker\Utils\Helper::get_settings() );
		$btn_text = $add_cart_text == '' ? esc_html__( 'Buy Now', 'quicker' ) : $add_cart_text;
		if ( $product->is_type( 'simple' ) ) {
			$btn = '<a href="' . wc_get_checkout_url() . '?add-to-cart=' . $product->get_id() . '" class="' . $btn_class . ' button">' . $btn_text . '</a>';
		}

		return $btn;
	}

	/**
	 * Over Ridding, Removing, Creating New Fields.
	 *
	 * @param [type] $fields
	 * @return void
	 */
	public function customize_checkout_fields( $fields ) {
		$change_fields = $this->change_checkout_fields( $fields );
		$result_fields = $this->new_checkout_fields( $change_fields );

		return $result_fields;
	}

	/**
	 * Build a WooCommerce-compatible field array from a checkout field config.
	 *
	 * @param array $value Checkout field configuration.
	 * @return array WooCommerce field data.
	 */
	private function build_wc_field_data( $value ) {
		$input_type = ! empty( $value['input_type'] ) ? $value['input_type'] : 'text';

		// Map plugin input types to WooCommerce form field types.
		$type_map = array(
			'phone'       => 'tel',
			'multiselect' => 'select',
			'date'        => 'text',
			'time'        => 'text',
			'heading'     => 'text',
		);
		$wc_type = isset( $type_map[ $input_type ] ) ? $type_map[ $input_type ] : $input_type;

		$field_data = array(
			'type'        => $wc_type,
			'label'       => $value['field_label'],
			'placeholder' => $value['field_placeholder'],
			'required'    => \Quicker\Utils\Helper::format_input_value( $value['field_required'] ),
			'class'       => array( 'form-row-wide' ),
			'clear'       => true,
		);

		// Add date/time input attributes.
		if ( 'date' === $input_type ) {
			$field_data['custom_attributes'] = array( 'type' => 'date' );
		} elseif ( 'time' === $input_type ) {
			$field_data['custom_attributes'] = array( 'type' => 'time' );
		}

		// Add multiple attribute for multiselect.
		if ( 'multiselect' === $input_type ) {
			$field_data['custom_attributes'] = array( 'multiple' => 'multiple' );
		}

		// Add options for select, radio, and multiselect fields.
		if ( in_array( $input_type, array( 'select', 'radio', 'multiselect' ), true ) && ! empty( $value['field_options'] ) ) {
			$options = $value['field_options'];
			if ( is_string( $options ) ) {
				$options = json_decode( $options, true );
			}
			if ( is_array( $options ) ) {
				$parsed = array();

				foreach ( $options as $opt ) {
					$opt_value = isset( $opt['value'] ) ? $opt['value'] : '';
					$opt_label = isset( $opt['label'] ) ? $opt['label'] : $opt_value;
					$parsed[ $opt_value ] = $opt_label;
				}
				$field_data['options'] = $parsed;
			}
		}

		return $field_data;
	}

	public function change_checkout_fields( $fields ) {
		$checkout_fields = \Quicker\Utils\Helper::get_checkout_fields( -1 );
		foreach ( $checkout_fields as $key => $value ) {
			// Skip if field_name is empty or field_position is set (custom fields are handled elsewhere)
			if ( $value['field_name'] === '' || ! empty( $value['field_position'] ) ) {
				continue;
			}

			$raw_enabled = $value['field_enabled'] ?? '';
			$enabled     = \Quicker\Utils\Helper::format_input_value( $raw_enabled );

			if ( true === $enabled ) {
				// Explicitly enabled — rebuild with plugin settings (label, required, etc.).
				$fields[ $value['field_type'] ][ $value['field_name'] ] = $this->build_wc_field_data( $value );
			} elseif ( false === $enabled ) {
				// Explicitly disabled — remove from checkout.
				unset( $fields[ $value['field_type'] ][ $value['field_name'] ] );
			}
			// Empty/unset field_enabled: leave the WC default in place (don't unset).
		}

		return $fields;
	}

	public function new_checkout_fields( $fields ) {
		$checkout_fields  = \Quicker\Utils\Helper::get_checkout_fields( -1 );
		$position_mapping = \Quicker\Utils\Helper::checkout_field_type( 'all' );


		foreach ( $checkout_fields as $value ) {
			// Only process custom fields that have a field_position set.
			if ( empty( $value['field_position'] ) || empty( $value['field_name'] ) ) {
				continue;
			}

			$enabled_raw   = $value['field_enabled'];
			$enabled_check = \Quicker\Utils\Helper::format_input_value( $enabled_raw );

			if ( $enabled_check != true ) {
				continue;
			}

			$roles_raw = $value['field_user_roles'];

			// Check user role restriction.
			if ( ! empty( $roles_raw ) ) {
				$allowed_roles = is_array( $roles_raw ) ? $roles_raw : array( $roles_raw );
				$allowed_roles = array_filter( $allowed_roles ); // Remove empty strings from empty multiselect saves.
				if ( ! empty( $allowed_roles ) ) {
					$user       = wp_get_current_user();
					$user_roles = $user->ID ? $user->roles : array();
					$intersect  = array_intersect( $allowed_roles, $user_roles );
					if ( ! $intersect ) {
						continue;
					}
				}
			}

			// Determine which field group this belongs to based on position.
			$group = 'billing';
			if ( isset( $position_mapping[ $value['field_position'] ] ) ) {
				$group = $position_mapping[ $value['field_position'] ]['type'];
			}

			$field_data             = $this->build_wc_field_data( $value );
			$field_data['priority'] = 200 + (int) $value['ID'];

			$fields[ $group ][ $value['field_name'] ] = $field_data;
		}

		return $fields;
	}

	/**
	 * Output CSS to hide disabled fields in Block Checkout
	 *
	 * @return void
	 */
	public function block_checkout_hide_fields_css() {
		if ( ! is_checkout() ) {
			return;
		}

		$checkout_fields = \Quicker\Utils\Helper::get_checkout_fields( -1 );
		$hidden_selectors = array();

		// Map field names to Block Checkout CSS selectors (target wrapper containers)
		$field_selector_map = array(
			'billing_phone'      => '#phone, #contact-fields__phone, .wc-block-components-address-form__phone',
			'billing_email'      => '#email, #contact-fields__email, .wc-block-components-address-form__email',
			'billing_first_name' => '#billing-first_name, .wc-block-components-address-form__first_name',
			'billing_last_name'  => '#billing-last_name, .wc-block-components-address-form__last_name',
			'billing_company'    => '#billing-company, .wc-block-components-address-form__company',
			'billing_address_1'  => '#billing-address_1, .wc-block-components-address-form__address_1',
			'billing_address_2'  => '#billing-address_2, .wc-block-components-address-form__address_2',
			'billing_city'       => '#billing-city, .wc-block-components-address-form__city',
			'billing_state'      => '#billing-state, .wc-block-components-address-form__state',
			'billing_postcode'   => '#billing-postcode, .wc-block-components-address-form__postcode',
			'billing_country'    => '#billing-country, .wc-block-components-address-form__country',
		);

		foreach ( $checkout_fields as $key => $value ) {
			// Skip if field_name is empty or field_position is set (custom fields)
			if ( $value['field_name'] === '' || ! empty( $value['field_position'] ) ) {
				continue;
			}

			// Only hide when the admin explicitly set field_enabled to "no".
			// An empty / unset value must NOT hide the default WC field (e.g. billing_company).
			$raw_enabled = $value['field_enabled'] ?? '';
			if ( '' === $raw_enabled ) {
				continue;
			}
			if ( false === \Quicker\Utils\Helper::format_input_value( $raw_enabled ) ) {
				$field_name = $value['field_name'];
				if ( isset( $field_selector_map[ $field_name ] ) ) {
					$hidden_selectors[] = $field_selector_map[ $field_name ];
				}
			}
		}

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

		// Build CSS with parent wrapper targeting for Block Checkout
		$all_selectors = array();
		foreach ( $hidden_selectors as $selectors ) {
			$parts = array_map( 'trim', explode( ',', $selectors ) );
			foreach ( $parts as $selector ) {
				$all_selectors[] = $selector;
				// Also target parent wrapper for text inputs
				$all_selectors[] = '.wc-block-components-text-input:has(' . $selector . ')';
			}
		}

		$css = implode( ', ', $all_selectors ) . ' { display: none !important; }';
		// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- CSS selectors are hardcoded, not user input
		echo '<style id="quicker-block-checkout-fields">' . $css . '</style>';
	}

	/**
	 * Output JavaScript to disable validation for hidden fields in Block Checkout.
	 *
	 * @return void
	 */
	public function block_checkout_disable_validation_js() {
		if ( ! is_checkout() ) {
			return;
		}

		$checkout_fields = \Quicker\Utils\Helper::get_checkout_fields( -1 );
		$disabled_fields = $this->get_disabled_field_names( $checkout_fields );

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

		// Map field names to input IDs used in Block Checkout.
		$field_input_map = array(
			'billing_phone'      => array( 'phone', 'billing-phone' ),
			'billing_email'      => array( 'email', 'billing-email' ),
			'billing_first_name' => array( 'billing-first_name' ),
			'billing_last_name'  => array( 'billing-last_name' ),
			'billing_company'    => array( 'billing-company' ),
			'billing_address_1'  => array( 'billing-address_1' ),
			'billing_address_2'  => array( 'billing-address_2' ),
			'billing_city'       => array( 'billing-city' ),
			'billing_state'      => array( 'billing-state' ),
			'billing_postcode'   => array( 'billing-postcode' ),
			'billing_country'    => array( 'billing-country' ),
		);

		$input_ids = array();
		foreach ( $disabled_fields as $field_name ) {
			if ( isset( $field_input_map[ $field_name ] ) ) {
				$input_ids = array_merge( $input_ids, $field_input_map[ $field_name ] );
			}
		}

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

		$input_ids_json = wp_json_encode( $input_ids );
		?>
		<script id="quicker-block-checkout-validation">
		(function() {
			var disabledFields = <?php echo $input_ids_json; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- JSON encoded array of hardcoded IDs ?>;

			console.log('[Quicker Debug] Disabled fields:', disabledFields);

			// Fill hidden fields with placeholder values to pass validation.
			function fillHiddenFields() {
				console.log('[Quicker Debug] Running fillHiddenFields...');

				// Get WooCommerce store country from settings if available.
				var storeCountry = typeof wcBlocksCheckoutData !== 'undefined' && wcBlocksCheckoutData.storeCountry
					? wcBlocksCheckoutData.storeCountry
					: '<?php echo esc_js( WC()->countries->get_base_country() ); ?>';

				disabledFields.forEach(function(fieldId) {
					var input = document.getElementById(fieldId);
					// Also try alternative selectors for Block Checkout.
					if (!input) {
						input = document.querySelector('[name="' + fieldId + '"]');
					}
					if (!input) {
						input = document.querySelector('[id*="' + fieldId + '"]');
					}

					console.log('[Quicker Debug] Field:', fieldId, 'Found:', !!input, 'Value:', input ? input.value : 'N/A');

					if (input && !input.value) {
						var fillValue = '-';

						if (fieldId.includes('email')) {
							fillValue = 'guest@placeholder.local';
						} else if (fieldId.includes('phone')) {
							fillValue = '0000000000';
						} else if (fieldId.includes('country')) {
							fillValue = storeCountry;
						} else if (fieldId.includes('state')) {
							fillValue = '';
						} else if (fieldId.includes('postcode') || fieldId.includes('zip')) {
							fillValue = '00000';
						} else if (fieldId.includes('city')) {
							fillValue = '-';
						} else if (fieldId.includes('first_name') || fieldId.includes('first-name')) {
							fillValue = 'Guest';
						} else if (fieldId.includes('last_name') || fieldId.includes('last-name')) {
							fillValue = 'Customer';
						}

						console.log('[Quicker Debug] Filled field:', fieldId, 'with:', fillValue);

						// Trigger React state update.
						try {
							if (input.tagName === 'INPUT') {
								var nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value').set;
								nativeInputValueSetter.call(input, fillValue);
							} else if (input.tagName === 'SELECT') {
								var nativeSelectValueSetter = Object.getOwnPropertyDescriptor(window.HTMLSelectElement.prototype, 'value').set;
								nativeSelectValueSetter.call(input, fillValue);
							} else {
								input.value = fillValue;
							}
						} catch(e) {
							input.value = fillValue;
							console.log('[Quicker Debug] Fallback value set for:', fieldId);
						}

						var event = new Event('input', { bubbles: true });
						input.dispatchEvent(event);
						var changeEvent = new Event('change', { bubbles: true });
						input.dispatchEvent(changeEvent);
						var blurEvent = new Event('blur', { bubbles: true });
						input.dispatchEvent(blurEvent);
					}
				});

				// Also fill select elements (like country/state dropdowns).
				document.querySelectorAll('select[style*="display: none"], select.hidden').forEach(function(select) {
					if (!select.value && select.options.length > 0) {
						select.value = select.options[0].value;
						console.log('[Quicker Debug] Filled select:', select.id || select.name, 'with:', select.value);
						var event = new Event('change', { bubbles: true });
						select.dispatchEvent(event);
					}
				});
			}

			// Run on page load and periodically.
			if (document.readyState === 'loading') {
				document.addEventListener('DOMContentLoaded', function() {
					console.log('[Quicker Debug] DOMContentLoaded - scheduling fillHiddenFields');
					setTimeout(fillHiddenFields, 1000);
					setTimeout(fillHiddenFields, 2000);
				});
			} else {
				console.log('[Quicker Debug] Document ready - scheduling fillHiddenFields');
				setTimeout(fillHiddenFields, 1000);
				setTimeout(fillHiddenFields, 2000);
			}

			// Also run before form submission.
			document.addEventListener('click', function(e) {
				if (e.target && e.target.closest('.wc-block-components-checkout-place-order-button')) {
					console.log('[Quicker Debug] Place order button clicked');
					fillHiddenFields();
					// Try to clear validation errors.
					clearValidationErrors();
				}
			}, true);

			// Clear validation error messages for hidden fields.
			function clearValidationErrors() {
				console.log('[Quicker Debug] Clearing validation errors...');
				// Remove error classes and messages.
				disabledFields.forEach(function(fieldId) {
					var wrapper = document.querySelector('[id*="' + fieldId + '"]');
					if (wrapper) {
						var parent = wrapper.closest('.wc-block-components-text-input');
						if (parent) {
							parent.classList.remove('has-error');
							var errorMsg = parent.querySelector('.wc-block-components-validation-error');
							if (errorMsg) {
								errorMsg.remove();
								console.log('[Quicker Debug] Removed error for:', fieldId);
							}
						}
					}
				});

				// Also remove any general validation errors for our fields.
				document.querySelectorAll('.wc-block-components-validation-error').forEach(function(error) {
					var errorText = error.textContent.toLowerCase();
					if (errorText.includes('phone') || errorText.includes('postcode') ||
						errorText.includes('city') || errorText.includes('last name') ||
						errorText.includes('state') || errorText.includes('zip')) {
						error.closest('.wc-block-components-text-input')?.classList.remove('has-error');
						error.remove();
						console.log('[Quicker Debug] Removed validation error:', errorText);
					}
				});
			}

			// Intercept WooCommerce Blocks checkout store to set field values.
			function updateCheckoutStore() {
				console.log('[Quicker Debug] Attempting to update checkout store...');

				// Try to access WooCommerce Blocks data stores.
				if (typeof wp !== 'undefined' && wp.data && wp.data.dispatch) {
					try {
						var storeCountry = '<?php echo esc_js( WC()->countries->get_base_country() ); ?>';
						var checkoutStore = wp.data.dispatch('wc/store/checkout');
						var cartStore = wp.data.dispatch('wc/store/cart');

						console.log('[Quicker Debug] WP data stores found');

						// Set billing address with placeholder values.
						if (cartStore && cartStore.setBillingAddress) {
							var billingData = {};
							disabledFields.forEach(function(fieldId) {
								if (fieldId.includes('phone')) billingData.phone = '0000000000';
								if (fieldId.includes('postcode')) billingData.postcode = '00000';
								if (fieldId.includes('city')) billingData.city = '-';
								if (fieldId.includes('last_name') || fieldId.includes('last-name')) billingData.last_name = 'Customer';
								if (fieldId.includes('state')) billingData.state = '';
								if (fieldId.includes('country')) billingData.country = storeCountry;
							});

							if (Object.keys(billingData).length > 0) {
								console.log('[Quicker Debug] Setting billing data:', billingData);
								cartStore.setBillingAddress(billingData);
							}
						}
					} catch(e) {
						console.log('[Quicker Debug] Store update error:', e);
					}
				}
			}

			// Run store update.
			setTimeout(updateCheckoutStore, 1500);
			setTimeout(updateCheckoutStore, 3000);

			// Monitor AJAX/Fetch requests for checkout
			var originalFetch = window.fetch;
			window.fetch = function(url, options) {
				if (url && url.toString().includes('checkout')) {
					console.log('[Quicker Debug] Checkout fetch request:', url);
					console.log('[Quicker Debug] Request options:', options);
					return originalFetch.apply(this, arguments).then(function(response) {
						var clonedResponse = response.clone();
						clonedResponse.json().then(function(data) {
							console.log('[Quicker Debug] Checkout response:', data);
							if (data.code || data.message) {
								console.error('[Quicker Debug] Checkout error:', data.code, data.message);
							}
						}).catch(function() {});
						return response;
					}).catch(function(error) {
						console.error('[Quicker Debug] Checkout fetch error:', error);
						throw error;
					});
				}
				return originalFetch.apply(this, arguments);
			};

			console.log('[Quicker Debug] Block checkout validation script loaded');
		})();
		</script>
		<?php
	}

	/**
	 * Whether Direct Checkout should apply for a given product according to settings scopes.
	 * Rules:
	 * - If both lists are empty: apply globally.
	 * - If products list has values: product ID must be in the list.
	 * - Else if categories list has values: product must belong to at least one selected category.
	 */
	protected function should_apply_direct_checkout_for_product( $product, $settings ) {
		// Scope control: entire | categories | products
		$scope = isset( $settings['direct_checkout_scope'] ) ? $settings['direct_checkout_scope'] : 'entire';
		// Categories/Products scoping is Pro-only; fallback to entire in free
		if ( in_array( $scope, array( 'categories', 'products' ), true ) && ! \Quicker\Utils\Helper::is_pro_active() ) {
			$scope = 'entire';
		}
		if ( $scope === 'entire' ) {
			return true;
		}
		$product_ids = isset( $settings['direct_checkout_products'] ) ? (array) $settings['direct_checkout_products'] : array();
		$category_ids = isset( $settings['direct_checkout_categories'] ) ? (array) $settings['direct_checkout_categories'] : array();

		// Normalize to ints/strings as saved
		$product_id = (int) $product->get_id();
		$product_ids = array_filter( array_map( 'intval', $product_ids ) );
		$category_ids = array_filter( array_map( 'intval', $category_ids ) );

		if ( class_exists('QuickerPro') && $scope === 'products' ) {
			return in_array( $product_id, $product_ids, true );
		}
		if ( class_exists('QuickerPro') && $scope === 'categories' ) {
			$terms = wc_get_product_term_ids( $product_id, 'product_cat' );
			if ( empty( $terms ) ) {
				return false;
			}
			foreach ( $terms as $tid ) {
				if ( in_array( (int) $tid, $category_ids, true ) ) {
					return true;
				}
			}
			return false;
		}

		return true;
	}
}
