<?php

namespace WPSecurityNinja\Plugin;

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

class Wf_Sn_Woo_Protection {
	private static $json_response_sent = false;

	public static function init() {
		// Only proceed if WooCommerce is active
		if ( ! class_exists( 'WooCommerce' ) ) {
			return;
		}

		$options = \WPSecurityNinja\Plugin\wf_sn_cf::get_options();
		if ( \WPSecurityNinja\Plugin\wf_sn_cf::is_active() && isset( $options['countryblock_loginonly'] ) && ( 1 === intval( $options['countryblock_loginonly'] ) ) ) {
			// Add hooks for WooCommerce login/register forms (display messages)
			add_action( 'woocommerce_login_form_start', array( __CLASS__, 'check_country_restriction' ) );
			add_action( 'woocommerce_register_form_start', array( __CLASS__, 'check_country_restriction' ) );

			// Add hooks to actually intercept login/registration attempts
			add_filter( 'authenticate', array( __CLASS__, 'intercept_login_attempt' ), 30, 3 );
			add_filter( 'woocommerce_process_registration_errors', array( __CLASS__, 'intercept_registration_attempt' ), 10, 4 );

			// Hook into WooCommerce registration auth to prevent auto-login
			add_filter( 'woocommerce_registration_auth_new_customer', array( __CLASS__, 'prevent_auto_login_for_restricted_countries' ), 10, 2 );
		}

		// Rate limiting for WooCommerce actions
		if ( self::is_woo_rate_limiting_enabled() ) {
			add_action( 'woocommerce_checkout_process', array( __CLASS__, 'check_checkout_rate_limit' ) );
			add_action( 'woocommerce_add_to_cart', array( __CLASS__, 'check_add_to_cart_rate_limit' ), 10, 6 );
			add_action( 'woocommerce_after_checkout_validation', array( __CLASS__, 'check_order_rate_limit' ), 10, 2 );
		}

		// Coupon protection
		if ( self::is_woo_coupon_protection_enabled() ) {

			// Core WooCommerce coupon validation hooks
			add_filter( 'woocommerce_coupon_is_valid_for_cart', array( __CLASS__, 'check_coupon_brute_force' ), 99, 2 );
			add_filter( 'woocommerce_coupon_is_valid', array( __CLASS__, 'check_coupon_brute_force' ), 99, 2 );
			add_filter( 'woocommerce_coupon_is_valid_for_product', array( __CLASS__, 'check_coupon_brute_force_for_product' ), 99, 4 );

			// Checkout validation hooks
			add_action( 'woocommerce_after_checkout_validation', array( __CLASS__, 'check_coupon_attempts' ), 10, 2 );

			// AJAX hooks for traditional forms
			add_action( 'wp_ajax_woocommerce_apply_coupon', array( __CLASS__, 'check_coupon_attempts_ajax' ), 5 );
			add_action( 'wp_ajax_nopriv_woocommerce_apply_coupon', array( __CLASS__, 'check_coupon_attempts_ajax' ), 5 );

			// Success hook to reset counter
			add_action( 'woocommerce_applied_coupon', array( __CLASS__, 'reset_coupon_attempts' ), 10, 1 );

			// Hook into all coupon validation attempts
			add_filter( 'woocommerce_coupon_error', array( __CLASS__, 'check_coupon_error' ), 10, 3 );

			// Store API hooks for blocks
			add_filter( 'woocommerce_store_api_cart_coupon_errors', array( __CLASS__, 'check_blocks_coupon_errors' ), 10, 2 );
			add_filter( 'woocommerce_store_api_cart_apply_coupon', array( __CLASS__, 'check_blocks_coupon_apply' ), 10, 2 );

			// Hook into WooCommerce blocks initialization
			add_action( 'woocommerce_blocks_loaded', array( __CLASS__, 'init_blocks_protection' ) );

			// Fallback hooks in case blocks_loaded doesn't fire
			add_action( 'wp_loaded', array( __CLASS__, 'init_blocks_protection' ) );
			add_action( 'woocommerce_init', array( __CLASS__, 'init_blocks_protection' ) );

			// Override coupon message when banned
			add_filter( 'woocommerce_checkout_coupon_message', array( __CLASS__, 'override_coupon_message' ), 10 );

			// Override coupon field HTML output
			add_filter( 'woocommerce_form_field', array( __CLASS__, 'override_coupon_field_output' ), PHP_INT_MAX - 1, 4 );

			// Add JavaScript for blocks support
			add_action( 'wp_enqueue_scripts', array( __CLASS__, 'enqueue_blocks_js' ) );
		}
	}



	/**
	 * Check if WooCommerce rate limiting is enabled
	 */
	private static function is_woo_rate_limiting_enabled() {
		$firewall_options = Wf_sn_cf::get_options();
		return Wf_sn_cf::is_active() && ! empty( $firewall_options['woo_rate_limiting_enabled'] );
	}

	/**
	 * Check if WooCommerce coupon protection is enabled
	 */
	private static function is_woo_coupon_protection_enabled() {
		$firewall_options = Wf_sn_cf::get_options();
		return Wf_sn_cf::is_active() && ! empty( $firewall_options['woo_coupon_protection_enabled'] );
	}

	/**
	 * Rate limiting for checkout process
	 */
	public static function check_checkout_rate_limit() {
		$ip = Wf_sn_cf::get_user_ip();
		if ( ! $ip ) {
			return;
		}

		$firewall_options = Wf_sn_cf::get_options();

		$checkout_limit  = $firewall_options['woo_checkout_rate_limit'] ?? 3; // 3 checkouts per window
		$checkout_window = $firewall_options['woo_checkout_window'] ?? 300; // 5 minutes

		// Check if IP is already banned from checkout
		if ( get_transient( 'wf_sn_woo_checkout_banned_' . md5( $ip ) ) ) {
			if ( secnin_fs()->can_use_premium_code__premium_only() ) {
				\WPSecurityNinja\Plugin\wf_sn_el_modules::log_event(
					'security_ninja',
					'woo_checkout_blocked',
					'Checkout blocked - IP banned',
					array(
						'ip' => $ip,
					)
				);
			}

			wc_add_notice( __( 'Too many checkout attempts. Please wait before trying again.', 'security-ninja' ), 'error' );
			wp_safe_redirect( wc_get_cart_url() );
			exit;
		}

		$transient_key = 'wf_sn_woo_checkout_' . md5( $ip );
		$count         = (int) get_transient( $transient_key );

		if ( $count >= $checkout_limit ) {
			// Ban the IP for a period
			$ban_time = $firewall_options['woo_checkout_ban_time'] ?? 600; // 10 minutes
			set_transient( 'wf_sn_woo_checkout_banned_' . md5( $ip ), 1, $ban_time );

			if ( secnin_fs()->can_use_premium_code__premium_only() ) {
				\WPSecurityNinja\Plugin\wf_sn_el_modules::log_event(
					'security_ninja',
					'woo_checkout_ip_banned',
					'IP banned for checkout rate limit',
					array(
						'ip'       => $ip,
						'count'    => $count,
						'limit'    => $checkout_limit,
						'ban_time' => $ban_time,
					)
				);
			}

			wc_add_notice( __( 'Too many checkout attempts. Please wait before trying again.', 'security-ninja' ), 'error' );
			wp_safe_redirect( wc_get_cart_url() );
			exit;
		}

		++$count;
		set_transient( $transient_key, $count, $checkout_window );
	}

	/**
	 * Rate limiting for add to cart
	 */
	public static function check_add_to_cart_rate_limit( $cart_item_key, $product_id, $quantity, $variation_id, $variation, $cart_item_data ) {
		$ip = Wf_sn_cf::get_user_ip();
		if ( ! $ip ) {
			return;
		}

		$firewall_options = Wf_sn_cf::get_options();

		$add_to_cart_limit  = $firewall_options['woo_add_to_cart_limit'] ?? 10; // 10 additions per window
		$add_to_cart_window = $firewall_options['woo_add_to_cart_window'] ?? 60; // 1 minute

		// Check if IP is already banned from add to cart
		if ( get_transient( 'wf_sn_woo_add_to_cart_banned_' . md5( $ip ) ) ) {
			if ( secnin_fs()->can_use_premium_code__premium_only() ) {
				\WPSecurityNinja\Plugin\wf_sn_el_modules::log_event(
					'security_ninja',
					'woo_add_to_cart_blocked',
					'Add to cart blocked - IP banned',
					array(
						'ip'         => $ip,
						'product_id' => $product_id,
					)
				);
			}

			// Remove the item that was just added
			WC()->cart->remove_cart_item( $cart_item_key );
			wc_add_notice( __( 'Too many add to cart attempts. Please wait before trying again.', 'security-ninja' ), 'error' );
			return;
		}

		$transient_key = 'wf_sn_woo_add_to_cart_' . md5( $ip );
		$count         = (int) get_transient( $transient_key );

		if ( $count >= $add_to_cart_limit ) {
			// Ban the IP for a period
			$ban_time = $firewall_options['woo_add_to_cart_ban_time'] ?? 300; // 5 minutes
			set_transient( 'wf_sn_woo_add_to_cart_banned_' . md5( $ip ), 1, $ban_time );

			if ( secnin_fs()->can_use_premium_code__premium_only() ) {
				\WPSecurityNinja\Plugin\wf_sn_el_modules::log_event(
					'security_ninja',
					'woo_add_to_cart_ip_banned',
					'IP banned for add to cart rate limit',
					array(
						'ip'         => $ip,
						'count'      => $count,
						'limit'      => $add_to_cart_limit,
						'ban_time'   => $ban_time,
						'product_id' => $product_id,
					)
				);
			}

			// Remove the item that was just added
			WC()->cart->remove_cart_item( $cart_item_key );
			wc_add_notice( __( 'Too many add to cart attempts. Please wait before trying again.', 'security-ninja' ), 'error' );
			return;
		}

		++$count;
		set_transient( $transient_key, $count, $add_to_cart_window );
	}

	/**
	 * Rate limiting for order placement
	 */
	public static function check_order_rate_limit( $data, $errors ) {
		if ( ! empty( $errors->errors ) ) {
			return; // Don't rate limit if there are validation errors
		}

		$ip = Wf_sn_cf::get_user_ip();
		if ( ! $ip ) {
			return;
		}

		$firewall_options = Wf_sn_cf::get_options();

		$order_limit  = $firewall_options['woo_order_rate_limit'] ?? 2; // 2 orders per window
		$order_window = $firewall_options['woo_order_window'] ?? 600; // 10 minutes

		// Check if IP is already banned from order placement
		if ( get_transient( 'wf_sn_woo_order_banned_' . md5( $ip ) ) ) {
			if ( secnin_fs()->can_use_premium_code__premium_only() ) {
				\WPSecurityNinja\Plugin\wf_sn_el_modules::log_event(
					'security_ninja',
					'woo_order_blocked',
					'Order blocked - IP banned',
					array(
						'ip' => $ip,
					)
				);
			}

			$errors->add( 'rate_limit', __( 'Too many order attempts. Please wait before trying again.', 'security-ninja' ) );
			return;
		}

		$transient_key = 'wf_sn_woo_order_' . md5( $ip );
		$count         = (int) get_transient( $transient_key );

		if ( $count >= $order_limit ) {
			// Ban the IP for a period
			$ban_time = $firewall_options['woo_order_ban_time'] ?? 900; // 15 minutes
			set_transient( 'wf_sn_woo_order_banned_' . md5( $ip ), 1, $ban_time );

			if ( secnin_fs()->can_use_premium_code__premium_only() ) {
				\WPSecurityNinja\Plugin\wf_sn_el_modules::log_event(
					'security_ninja',
					'woo_order_ip_banned',
					'IP banned for order rate limit',
					array(
						'ip'       => $ip,
						'count'    => $count,
						'limit'    => $order_limit,
						'ban_time' => $ban_time,
					)
				);
			}

			$errors->add( 'rate_limit', __( 'Too many order attempts. Please wait before trying again.', 'security-ninja' ) );
			return;
		}

		++$count;
		set_transient( $transient_key, $count, $order_window );
	}

	/**
	 * Check if the current user's country is restricted
	 */
	public static function check_country_restriction() {
		$user_ip = Wf_sn_cf::get_user_ip();

		$blocked_country = Wf_sn_cf::is_banned_country__premium_only( $user_ip );
		if ( $blocked_country ) {
			// Display restriction message
			echo '<div class="woocommerce-info">' .
				esc_html__( 'Access to this form is restricted in your country.', 'security-ninja' ) .
				'</div>';

			// Log the attempt
			$data = array(
				'ip'      => $user_ip,
				'country' => $blocked_country,
			);
		}
	}

	/**
	 * Intercept WooCommerce login attempts for restricted countries
	 *
	 * @param null|WP_User|WP_Error $user
	 * @param string $username
	 * @param string $password
	 * @return null|WP_User|WP_Error
	 */
	public static function intercept_login_attempt( $user, $username, $password ) {
		// Only intercept if we don't already have an error and credentials are provided
		if ( is_wp_error( $user ) || empty( $username ) || empty( $password ) ) {
			return $user;
		}

		// Check if this is a WooCommerce login attempt
		if ( ! self::is_woocommerce_login_page() ) {
			return $user;
		}

		$user_ip = Wf_sn_cf::get_user_ip();

		$blocked_country = Wf_sn_cf::is_banned_country__premium_only( $user_ip );
		if ( $blocked_country ) {
			// Log the blocked attempt
			$data = array(
				'ip'       => $user_ip,
				'country'  => $blocked_country,
				'username' => $username,
			);
			\WPSecurityNinja\Plugin\wf_sn_el_modules::log_event( 'security_ninja', 'woo_login_blocked', 'Blocked WooCommerce login attempt from restricted country', $data );
			return new \WP_Error(
				'country_restricted_login',
				esc_html__( 'Login is not allowed from your country.', 'security-ninja' )
			);
		}

		return $user;
	}

	/**
	 * Intercept WooCommerce registration attempts for restricted countries
	 *
	 * @param \WP_Error $validation_error
	 * @param string $username
	 * @param string $password
	 * @param string $email
	 * @return \WP_Error
	 */
	public static function intercept_registration_attempt( $validation_error, $username, $password, $email ) {
		$user_ip = Wf_sn_cf::get_user_ip();

		$blocked_country = Wf_sn_cf::is_banned_country__premium_only( $user_ip );
		if ( $blocked_country ) {
			// Log the blocked attempt
			$data = array(
				'ip'       => $user_ip,
				'country'  => $blocked_country,
				'username' => $username,
				'email'    => $email,
			);
			\WPSecurityNinja\Plugin\wf_sn_el_modules::log_event( 'security_ninja', 'woo_registration_blocked', 'Blocked WooCommerce registration attempt from restricted country', $data );

			$validation_error->add(
				'country_restricted_registration',
				esc_html__( 'Registration is not allowed from your country.', 'security-ninja' )
			);
		}

		return $validation_error;
	}

	/**
	 * Prevent auto-login after registration for restricted countries
	 *
	 * @param bool $auth_new_customer
	 * @param int $new_customer_id
	 * @return bool
	 */
	public static function prevent_auto_login_for_restricted_countries( $auth_new_customer, $new_customer_id ) {
		$user_ip = Wf_sn_cf::get_user_ip();

		if ( Wf_sn_cf::is_banned_country__premium_only( $user_ip ) ) {
			// Prevent auto-login for restricted countries
			return false;
		}

		return $auth_new_customer;
	}

	/**
	 * Check if the current request is for a WooCommerce login page
	 *
	 * @return bool
	 */
	private static function is_woocommerce_login_page() {
		// Check if we're on WooCommerce my-account page or processing WooCommerce login
		if ( function_exists( 'is_account_page' ) && is_account_page() ) {
			return true;
		}

		// Check if this is a WooCommerce login form submission
		if ( isset( $_POST['woocommerce-login-nonce'] ) || isset( $_POST['login'] ) ) {
			return true;
		}

		// Check if we're processing WooCommerce login via AJAX or standard form
		if (
			isset( $_POST['username'] ) && isset( $_POST['password'] ) &&
			( strpos( $_SERVER['REQUEST_URI'], 'my-account' ) !== false ||
				strpos( $_SERVER['HTTP_REFERER'], 'my-account' ) !== false )
		) {
			return true;
		}

		return false;
	}

	/**
	 * Check for coupon brute force attempts
	 */
	public static function check_coupon_brute_force( $is_valid, $coupon ) {
		$ip = Wf_sn_cf::get_user_ip();
		if ( ! $ip ) {
			return $is_valid;
		}

		// Ensure we have a valid coupon object with get_code method
		if ( ! is_object( $coupon ) || ! method_exists( $coupon, 'get_code' ) ) {
			return $is_valid;
		}

		// Check if IP is already banned from coupon usage
		if ( get_transient( 'wf_sn_woo_coupon_banned_' . md5( $ip ) ) ) {
			if ( secnin_fs()->can_use_premium_code__premium_only() ) {
				\WPSecurityNinja\Plugin\wf_sn_el_modules::log_event(
					'security_ninja',
					'woo_coupon_blocked',
					'Coupon attempt blocked - IP banned',
					array(
						'ip'          => $ip,
						'coupon_code' => $coupon->get_code(),
					)
				);
			}

			// Return false to indicate invalid coupon, but don't show the actual error
			if ( function_exists( 'wc_add_notice' ) ) {
				wc_add_notice( __( 'This coupon code is not valid.', 'security-ninja' ), 'error' );
			}
			return false;
		}

		$firewall_options      = Wf_sn_cf::get_options();
		$failed_attempts_limit = $firewall_options['woo_coupon_failed_attempts'] ?? 5;
		$window                = $firewall_options['woo_coupon_window'] ?? 300;

		$transient_key = 'wf_sn_woo_coupon_failed_' . md5( $ip );
		$failed_count  = (int) get_transient( $transient_key );

		// Log the attempt
		if ( secnin_fs()->can_use_premium_code__premium_only() ) {
			$log_data = array(
				'ip'            => $ip,
				'coupon_code'   => $coupon->get_code(),
				'attempt_count' => $failed_count,
				'limit'         => $failed_attempts_limit,
				'is_valid'      => $is_valid,
			);

			if ( ! $is_valid ) {
				\WPSecurityNinja\Plugin\wf_sn_el_modules::log_event( 'security_ninja', 'woo_coupon_failed', 'Failed coupon attempt', $log_data );
			} else {
				\WPSecurityNinja\Plugin\wf_sn_el_modules::log_event( 'security_ninja', 'woo_coupon_success', 'Successful coupon attempt', $log_data );
			}
		}

		if ( $is_valid ) {
			// Reset failed attempts counter for successful coupons
			if ( $failed_count > 0 ) {
				delete_transient( $transient_key );
			}
			return $is_valid;
		} else {
			// Increment failed attempts counter for invalid coupons
			++$failed_count;
			set_transient( $transient_key, $failed_count, $window );

			// Check if we should ban this IP
			if ( $failed_count >= $failed_attempts_limit ) {
				$ban_time = $firewall_options['woo_coupon_ban_time'] ?? 900; // 15 minutes
				set_transient( 'wf_sn_woo_coupon_banned_' . md5( $ip ), 1, $ban_time );

				if ( secnin_fs()->can_use_premium_code__premium_only() ) {
					\WPSecurityNinja\Plugin\wf_sn_el_modules::log_event(
						'security_ninja',
						'woo_coupon_ip_banned',
						'IP banned for coupon brute force',
						array(
							'ip'           => $ip,
							'failed_count' => $failed_count,
							'ban_time'     => $ban_time,
						)
					);
				}

				// Return false to block the attempt
				if ( function_exists( 'wc_add_notice' ) ) {
					wc_add_notice( __( 'Too many invalid coupon attempts. Please wait before trying again.', 'security-ninja' ), 'error' );
				}
				return false;
			}
		}

		return $is_valid; // Return original validity
	}

	/**
	 * Check for coupon brute force attempts (for product-specific validation)
	 * This function handles the woocommerce_coupon_is_valid_for_product filter which has 4 parameters
	 */
	public static function check_coupon_brute_force_for_product( $is_valid, $product, $coupon, $values ) {
		// For product-specific validation, we still want to check brute force protection
		// but we need to ensure we have a valid coupon object
		if ( ! is_object( $coupon ) || ! method_exists( $coupon, 'get_code' ) ) {
			return $is_valid;
		}

		// Call the main brute force check function
		return self::check_coupon_brute_force( $is_valid, $coupon );
	}

	/**
	 * Check for coupon brute force attempts
	 */
	public static function check_coupon_attempts( $data, $errors ) {
		$ip = Wf_sn_cf::get_user_ip();

		if ( ! empty( $errors->errors ) ) {
			return; // Don't rate limit if there are validation errors
		}

		// Only check ban status, don't increment counter here
		if ( get_transient( 'wf_sn_woo_coupon_banned_' . md5( $ip ) ) ) {
			$errors->add( 'rate_limit', __( 'Too many coupon attempts. Please wait before trying again.', 'security-ninja' ) );

			if ( secnin_fs()->can_use_premium_code__premium_only() ) {
				\WPSecurityNinja\Plugin\wf_sn_el_modules::log_event(
					'security_ninja',
					'woo_coupon_rate_limited',
					'Coupon rate limited',
					array(
						'ip' => $ip,
					)
				);
			}
			return;
		}
	}

	/**
	 * Check for coupon brute force attempts during AJAX requests
	 */
	public static function check_coupon_attempts_ajax() {
		$ip = Wf_sn_cf::get_user_ip();

		// Only check ban status, don't increment counter here
		if ( get_transient( 'wf_sn_woo_coupon_banned_' . md5( $ip ) ) ) {
			if ( secnin_fs()->can_use_premium_code__premium_only() ) {
				\WPSecurityNinja\Plugin\wf_sn_el_modules::log_event(
					'security_ninja',
					'woo_coupon_rate_limited',
					'Coupon rate limited',
					array(
						'ip' => $ip,
					)
				);
			}

			// Send error response safely
			if ( ! self::$json_response_sent ) {
				self::$json_response_sent = true;
				wp_send_json_error(
					array(
						'error' => __( 'Too many coupon attempts. Please wait before trying again.', 'security-ninja' ),
					)
				);
			}
		}
	}

	/**
	 * Reset coupon brute force attempts when a valid coupon is applied
	 */
	public static function reset_coupon_attempts( $coupon_code ) {

		$ip = Wf_sn_cf::get_user_ip();
		if ( ! $ip ) {
			return;
		}

		$transient_key = 'wf_sn_woo_coupon_failed_' . md5( $ip );
		$failed_count  = (int) get_transient( $transient_key );

		// Reset the failed attempts counter when a valid coupon is applied
		if ( $failed_count > 0 ) {
			delete_transient( $transient_key );

			if ( secnin_fs()->can_use_premium_code__premium_only() ) {
				\WPSecurityNinja\Plugin\wf_sn_el_modules::log_event(
					'security_ninja',
					'woo_coupon_reset',
					'Coupon attempts reset after successful application',
					array(
						'ip'                    => $ip,
						'coupon_code'           => $coupon_code,
						'previous_failed_count' => $failed_count,
					)
				);
			}
		}
	}



	/**
	 * Hook into WooCommerce blocks initialization
	 */
	public static function init_blocks_protection() {
		static $initialized = false;

		if ( $initialized ) {
			return; // Already initialized
		}

		// Add filters for blocks
		add_filter( 'woocommerce_store_api_cart_coupon_errors', array( __CLASS__, 'check_blocks_coupon_errors' ), 10, 2 );
		add_filter( 'woocommerce_store_api_cart_apply_coupon', array( __CLASS__, 'check_blocks_coupon_apply' ), 10, 2 );

		$initialized = true;
	}

	/**
	 * Hook into all coupon validation attempts
	 */
	public static function check_coupon_error( $error, $coupon_code, $coupon ) {

		$ip = Wf_sn_cf::get_user_ip();

		if ( ! $ip ) {
			return $error;
		}

		// Only increment counter if there's an actual error
		if ( $error ) {
			$firewall_options      = Wf_sn_cf::get_options();
			$failed_attempts_limit = $firewall_options['woo_coupon_failed_attempts'] ?? 5;
			$window                = $firewall_options['woo_coupon_window'] ?? 300;

			$transient_key = 'wf_sn_woo_coupon_failed_' . md5( $ip );
			$failed_count  = (int) get_transient( $transient_key );
			++$failed_count;
			set_transient( $transient_key, $failed_count, $window );

			// Check if we should ban this IP
			if ( $failed_count >= $failed_attempts_limit ) {
				$ban_time = $firewall_options['woo_coupon_ban_time'] ?? 900; // 15 minutes
				set_transient( 'wf_sn_woo_coupon_banned_' . md5( $ip ), 1, $ban_time );

				if ( secnin_fs()->can_use_premium_code__premium_only() ) {
					\WPSecurityNinja\Plugin\wf_sn_el_modules::log_event(
						'security_ninja',
						'woo_coupon_ip_banned',
						'IP banned for coupon errors',
						array(
							'ip'           => $ip,
							'failed_count' => $failed_count,
							'ban_time'     => $ban_time,
							'coupon_code'  => $coupon_code,
						)
					);
				}
				\WPSecurityNinja\Plugin\Wf_sn_cf::kill_request( $ip, 'Blocked due to excessive coupon attempts' );
				// Reload page to ensure ban takes effect
				// Removed redirect since request is via AJAX
				return __( 'Too many invalid coupon attempts. Please wait before trying again.', 'security-ninja' );
			}
		}

		return $error;
	}

	/**
	 * Check blocks coupon errors
	 */
	public static function check_blocks_coupon_errors( $errors, $coupon_code ) {

		$ip = Wf_sn_cf::get_user_ip();
		if ( ! $ip ) {
			return $errors;
		}

		// Check if IP is banned
		if ( get_transient( 'wf_sn_woo_coupon_banned_' . md5( $ip ) ) ) {
			$errors[] = __( 'Too many invalid coupon attempts. Please wait before trying again.', 'security-ninja' );
			return $errors;
		}

		// If there are errors, increment failed attempts
		if ( ! empty( $errors ) ) {
			$firewall_options      = Wf_sn_cf::get_options();
			$failed_attempts_limit = $firewall_options['woo_coupon_failed_attempts'] ?? 5;
			$window                = $firewall_options['woo_coupon_window'] ?? 300;

			$transient_key = 'wf_sn_woo_coupon_failed_' . md5( $ip );
			$failed_count  = (int) get_transient( $transient_key );
			++$failed_count;
			set_transient( $transient_key, $failed_count, $window );

			// Check if we should ban this IP
			if ( $failed_count >= $failed_attempts_limit ) {
				$ban_time = $firewall_options['woo_coupon_ban_time'] ?? 900; // 15 minutes
				set_transient( 'wf_sn_woo_coupon_banned_' . md5( $ip ), 1, $ban_time );

				if ( secnin_fs()->can_use_premium_code__premium_only() ) {
					\WPSecurityNinja\Plugin\wf_sn_el_modules::log_event(
						'security_ninja',
						'woo_coupon_ip_banned',
						'IP banned for blocks coupon errors',
						array(
							'ip'           => $ip,
							'failed_count' => $failed_count,
							'ban_time'     => $ban_time,
							'coupon_code'  => $coupon_code,
						)
					);
				}

				$errors[] = __( 'Too many invalid coupon attempts. Please wait before trying again.', 'security-ninja' );
			}
		}

		return $errors;
	}

	/**
	 * Check blocks coupon apply
	 */
	public static function check_blocks_coupon_apply( $result, $coupon_code ) {

		$ip = Wf_sn_cf::get_user_ip();
		if ( ! $ip ) {
			return $result;
		}

		// Check if IP is banned
		if ( get_transient( 'wf_sn_woo_coupon_banned_' . md5( $ip ) ) ) {
			return new \WP_Error( 'coupon_banned', __( 'Too many invalid coupon attempts. Please wait before trying again.', 'security-ninja' ) );
		}

		return $result;
	}






	/**
	 * Override coupon message when banned
	 */
	public static function override_coupon_message( $message ) {
		$ip = Wf_sn_cf::get_user_ip();
		if ( ! $ip ) {
			return $message;
		}

		if ( get_transient( 'wf_sn_woo_coupon_banned_' . md5( $ip ) ) ) {
			$ban_time    = self::get_remaining_ban_time( $ip );
			$ban_message = self::get_ban_message_with_duration( $ban_time );
			return '<div class="woocommerce-info">' . $ban_message . '</div>';
		}
		return $message;
	}

	/**
	 * Get remaining ban time in seconds
	 */
	private static function get_remaining_ban_time( $ip ) {
		$transient_key     = 'wf_sn_woo_coupon_banned_' . md5( $ip );
		$transient_timeout = get_option( '_transient_timeout_' . $transient_key );

		if ( ! $transient_timeout ) {
			return 0; // No ban active
		}

		$remaining_time = $transient_timeout - time();
		return max( 0, $remaining_time );
	}

	/**
	 * Get ban message with duration
	 */
	private static function get_ban_message_with_duration( $remaining_seconds ) {
		if ( $remaining_seconds <= 0 ) {
			return esc_html__( 'Coupon application is temporarily disabled due to too many invalid attempts. Please wait before trying again.', 'security-ninja' );
		}

		$minutes = floor( $remaining_seconds / 60 );
		$seconds = $remaining_seconds % 60;

		if ( $minutes > 0 ) {
			if ( $seconds > 0 ) {
				/* translators: 1: minutes, 2: seconds */
				return sprintf(
					esc_html__( 'Coupon application is temporarily disabled due to too many invalid attempts. Please wait %1$d minutes and %2$d seconds before trying again.', 'security-ninja' ),
					$minutes,
					$seconds
				);
			} else {
				/* translators: %d: number of minutes */
				return sprintf(
					esc_html__( 'Coupon application is temporarily disabled due to too many invalid attempts. Please wait %d minutes before trying again.', 'security-ninja' ),
					$minutes
				);
			}
		} else {
			/* translators: %d: number of seconds */
			return sprintf(
				esc_html__( 'Coupon application is temporarily disabled due to too many invalid attempts. Please wait %d seconds before trying again.', 'security-ninja' ),
				$seconds
			);
		}
	}

	/**
	 * Override coupon field output to show a message instead of input
	 */
	public static function override_coupon_field_output( $field, $key, $args, $value ) {
		// Only process coupon-related fields
		if ( 'coupon_code' !== $key && 'apply_coupon' !== $key ) {
			return $field;
		}

		$ip = Wf_sn_cf::get_user_ip();
		if ( ! $ip ) {
			return $field;
		}

		if ( get_transient( 'wf_sn_woo_coupon_banned_' . md5( $ip ) ) ) {
			$ban_time    = self::get_remaining_ban_time( $ip );
			$ban_message = self::get_ban_message_with_duration( $ban_time );
			return '<div class="woocommerce-info">' . $ban_message . '</div>';
		}
		return $field;
	}

	/**
	 * Enqueue JavaScript for blocks support
	 */
	public static function enqueue_blocks_js() {
		// Only enqueue on pages that might have blocks
		if ( ! is_cart() && ! is_checkout() ) {
			return;
		}

		if ( class_exists( __NAMESPACE__ . '\\Wf_Sn' ) ) {
			Wf_Sn::enqueue_sn_dialog();
		}

		wp_enqueue_script(
			'security-ninja-blocks-coupon',
			plugins_url( 'js/blocks-coupon.js', __FILE__ ),
			array( 'jquery', 'sn-dialog' ),
			'1.0.0',
			true
		);

		// Add ban status to JavaScript
		$ip             = Wf_sn_cf::get_user_ip();
		$is_banned      = false;
		$ban_message    = '';
		$remaining_time = 0;

		if ( $ip && get_transient( 'wf_sn_woo_coupon_banned_' . md5( $ip ) ) ) {
			$is_banned      = true;
			$remaining_time = self::get_remaining_ban_time( $ip );
			$ban_message    = self::get_ban_message_with_duration( $remaining_time );
		}

		wp_localize_script(
			'security-ninja-blocks-coupon',
			'security_ninja_coupon',
			array(
				'is_banned'      => $is_banned,
				'ban_message'    => $ban_message,
				'remaining_time' => $remaining_time,
			)
		);
	}

	/**
	 * Get currently banned IPs for WooCommerce protection features
	 *
	 * @return array Array of banned IPs with their protection type and expiry times
	 */
	public static function get_currently_banned_ips() {
		global $wpdb;
		$banned_ips = array();

		// Get all transients that match our block prefixes
		$transient_prefixes = array(
			'wf_sn_woo_coupon_banned_'      => 'coupon',
			'wf_sn_woo_checkout_banned_'    => 'checkout',
			'wf_sn_woo_add_to_cart_banned_' => 'add_to_cart',
			'wf_sn_woo_order_banned_'       => 'order',
		);

		foreach ( $transient_prefixes as $prefix => $type ) {
			$transient_prefix = '_transient_' . $prefix;
			$query            = $wpdb->prepare(
				"SELECT option_name, option_value FROM {$wpdb->options} 
                WHERE option_name LIKE %s AND option_value != ''",
				$transient_prefix . '%'
			);

			$results = $wpdb->get_results( $query );

			foreach ( $results as $row ) {
				$ip = str_replace( $transient_prefix, '', $row->option_name );

				// Get the expiry time from the _transient_timeout_ option
				$timeout_option_name = '_transient_timeout_' . $prefix . $ip;
				$expiry_time         = get_option( $timeout_option_name );

				if ( $expiry_time && $expiry_time > time() ) {
					if ( ! isset( $banned_ips[ $ip ] ) ) {
						$banned_ips[ $ip ] = array();
					}
					$banned_ips[ $ip ][ $type ] = $expiry_time;
				}
			}
		}

		return $banned_ips;
	}

	/**
	 * Get IPs currently being monitored for WooCommerce protection features
	 *
	 * @return array Array of monitored IPs with their current counts and expiry times
	 */
	public static function get_monitored_ips() {
		global $wpdb;
		$monitored_ips = array();

		// Get all transients that match our count prefixes
		$transient_prefixes = array(
			'wf_sn_woo_coupon_failed_' => 'coupon',
			'wf_sn_woo_checkout_'      => 'checkout',
			'wf_sn_woo_add_to_cart_'   => 'add_to_cart',
			'wf_sn_woo_order_'         => 'order',
		);

		$firewall_options = Wf_sn_cf::get_options();

		foreach ( $transient_prefixes as $prefix => $type ) {
			$transient_prefix = '_transient_' . $prefix;
			$query            = $wpdb->prepare(
				"SELECT option_name, option_value FROM {$wpdb->options} 
                WHERE option_name LIKE %s AND option_value != ''",
				$transient_prefix . '%'
			);

			$results = $wpdb->get_results( $query );

			foreach ( $results as $row ) {
				$ip    = str_replace( $transient_prefix, '', $row->option_name );
				$count = (int) $row->option_value;

				// Get the appropriate threshold for this type
				$threshold = 0;
				switch ( $type ) {
					case 'coupon':
						$threshold = $firewall_options['woo_coupon_failed_attempts'] ?? 5;
						break;
					case 'checkout':
						$threshold = $firewall_options['woo_checkout_rate_limit'] ?? 3;
						break;
					case 'add_to_cart':
						$threshold = $firewall_options['woo_add_to_cart_limit'] ?? 10;
						break;
					case 'order':
						$threshold = $firewall_options['woo_order_rate_limit'] ?? 2;
						break;
				}

				// Check if this IP is currently banned for this type
				$block_timeout_option = '_transient_timeout_wf_sn_woo_' . $type . '_banned_' . $ip;
				$ban_expiry           = get_option( $block_timeout_option );
				$is_banned            = $ban_expiry && $ban_expiry > time();

				// Only include if below threshold and not banned
				if ( $count > 0 && $count < $threshold && ! $is_banned ) {
					// Get expiry time for this count transient
					$count_timeout_option = '_transient_timeout_' . $prefix . $ip;
					$expiry_time          = get_option( $count_timeout_option );

					if ( ! isset( $monitored_ips[ $ip ] ) ) {
						$monitored_ips[ $ip ] = array();
					}
					$monitored_ips[ $ip ][ $type ] = array(
						'count'     => $count,
						'threshold' => $threshold,
						'expiry'    => $expiry_time,
					);
				}
			}
		}

		return $monitored_ips;
	}

	/**
	 * Get WooCommerce protection statistics
	 *
	 * @return array Array with comprehensive statistics
	 */
	public static function get_statistics() {
		$banned_ips    = self::get_currently_banned_ips();
		$monitored_ips = self::get_monitored_ips();

		// Get IPs expiring soon (within next 5 minutes)
		$expiring_soon = array();
		$current_time  = time();
		$five_minutes  = 5 * 60;

		foreach ( $banned_ips as $ip => $ban_types ) {
			foreach ( $ban_types as $type => $expiry_time ) {
				$time_until_expiry = $expiry_time - $current_time;
				if ( $time_until_expiry <= $five_minutes && $time_until_expiry > 0 ) {
					if ( ! isset( $expiring_soon[ $ip ] ) ) {
						$expiring_soon[ $ip ] = array();
					}
					$expiring_soon[ $ip ][ $type ] = $time_until_expiry;
				}
			}
		}

		// Sort expiring soon by time remaining (closest to expiring first)
		uasort(
			$expiring_soon,
			function ( $a, $b ) {
				$min_a = min( array_values( $a ) );
				$min_b = min( array_values( $b ) );
				return $min_a <=> $min_b;
			}
		);
		// Limit to top 5
		$expiring_soon = array_slice( $expiring_soon, 0, 5, true );

		// Get the 5 oldest monitored IPs (closest to expiry)
		$oldest_monitored = $monitored_ips;
		// Remove any with no expiry (shouldn't happen, but just in case)
		$oldest_monitored = array_filter(
			$oldest_monitored,
			function ( $item ) {
				return ! empty( $item ) && is_array( $item );
			}
		);
		// Sort by expiry ascending (oldest first)
		uasort(
			$oldest_monitored,
			function ( $a, $b ) {
				$min_a = min( array_column( $a, 'expiry' ) );
				$min_b = min( array_column( $b, 'expiry' ) );
				return $min_a <=> $min_b;
			}
		);
		$oldest_monitored = array_slice( $oldest_monitored, 0, 5, true );

		// Get recent WooCommerce protection events count (last 24 hours)
		$recent_events_count = self::get_recent_events_count();

		// Get all-time statistics
		$all_time_stats = self::get_all_time_statistics();

		return array(
			'banned_count'         => count( $banned_ips ),
			'monitored_count'      => count( $monitored_ips ),
			'expiring_soon_ips'    => $expiring_soon,
			'oldest_monitored_ips' => $oldest_monitored,
			'recent_events_count'  => $recent_events_count,
			'all_time_stats'       => $all_time_stats,
		);
	}

	/**
	 * Get count of recent WooCommerce protection events (last 24 hours)
	 *
	 * @return array Array with counts for different event types
	 */
	public static function get_recent_events_count() {
		global $wpdb;

		$table_name  = $wpdb->prefix . 'wf_sn_el';
		$event_types = array(
			'woo_checkout_rate_limited',
			'woo_checkout_ip_banned',
			'woo_checkout_blocked',
			'woo_add_to_cart_rate_limited',
			'woo_add_to_cart_ip_banned',
			'woo_add_to_cart_blocked',
			'woo_order_rate_limited',
			'woo_order_ip_banned',
			'woo_order_blocked',
			'woo_coupon_failed',
			'woo_coupon_success',
			'woo_coupon_ip_banned',
			'woo_coupon_blocked',
			'woo_coupon_rate_limited',
			'woo_coupon_reset',
			'woo_login_blocked',
			'woo_registration_blocked',
		);

		$placeholders = implode( ',', array_fill( 0, count( $event_types ), '%s' ) );
		$query        = $wpdb->prepare(
			"SELECT action, COUNT(*) as count FROM {$table_name} 
            WHERE module = %s AND action IN ({$placeholders}) 
            AND timestamp >= DATE_SUB(NOW(), INTERVAL 24 HOUR)
            GROUP BY action",
			array_merge( array( 'security_ninja' ), $event_types )
		);

		$results = $wpdb->get_results( $query );
		$counts  = array();

		foreach ( $event_types as $event_type ) {
			$counts[ $event_type ] = 0;
		}

		foreach ( $results as $row ) {
			$counts[ $row->action ] = (int) $row->count;
		}

		return $counts;
	}

	/**
	 * Get all-time statistics for WooCommerce protection
	 *
	 * @return array Array with all-time statistics
	 */
	public static function get_all_time_statistics() {
		global $wpdb;

		$table_name  = $wpdb->prefix . 'wf_sn_el';
		$event_types = array(
			'woo_checkout_rate_limited',
			'woo_checkout_ip_banned',
			'woo_checkout_blocked',
			'woo_add_to_cart_rate_limited',
			'woo_add_to_cart_ip_banned',
			'woo_add_to_cart_blocked',
			'woo_order_rate_limited',
			'woo_order_ip_banned',
			'woo_order_blocked',
			'woo_coupon_failed',
			'woo_coupon_success',
			'woo_coupon_ip_banned',
			'woo_coupon_blocked',
			'woo_coupon_rate_limited',
			'woo_coupon_reset',
			'woo_login_blocked',
			'woo_registration_blocked',
		);

		$placeholders = implode( ',', array_fill( 0, count( $event_types ), '%s' ) );
		$query        = $wpdb->prepare(
			"SELECT action, COUNT(*) as count FROM {$table_name} 
            WHERE module = %s AND action IN ({$placeholders})
            GROUP BY action",
			array_merge( array( 'security_ninja' ), $event_types )
		);

		$results = $wpdb->get_results( $query );
		$counts  = array();

		foreach ( $event_types as $event_type ) {
			$counts[ $event_type ] = 0;
		}

		foreach ( $results as $row ) {
			$counts[ $row->action ] = (int) $row->count;
		}

		// Calculate totals by category
		$totals = array(
			'total_rate_limited'  => $counts['woo_checkout_rate_limited'] + $counts['woo_add_to_cart_rate_limited'] + $counts['woo_order_rate_limited'],
			'total_coupon_events' => $counts['woo_coupon_failed'] + $counts['woo_coupon_success'] + $counts['woo_coupon_ip_banned'] + $counts['woo_coupon_blocked'] + $counts['woo_coupon_rate_limited'] + $counts['woo_coupon_reset'],
			'total_auth_blocked'  => $counts['woo_login_blocked'] + $counts['woo_registration_blocked'],
			'total_events'        => array_sum( $counts ),
		);

		return array_merge( $counts, $totals );
	}

	/**
	 * Format time remaining in human readable format
	 *
	 * @param int $seconds Seconds remaining
	 * @return string Formatted time string
	 */
	public static function format_time_remaining( $seconds ) {
		if ( $seconds < 60 ) {
			/* translators: %d: number of seconds */
			return sprintf( _n( '%d second', '%d seconds', $seconds, 'security-ninja' ), $seconds );
		} elseif ( $seconds < 3600 ) {
			$minutes = floor( $seconds / 60 );
			/* translators: %d: number of minutes */
			return sprintf( _n( '%d minute', '%d minutes', $minutes, 'security-ninja' ), $minutes );
		} else {
			$hours = floor( $seconds / 3600 );
			/* translators: %d: number of hours */
			return sprintf( _n( '%d hour', '%d hours', $hours, 'security-ninja' ), $hours );
		}
	}

	/**
	 * Check if WooCommerce protection is loaded and enabled
	 * This can be called from other parts of the system
	 */
	public static function is_loaded_and_enabled() {
		return class_exists( __CLASS__ ) && ( self::is_woo_rate_limiting_enabled() || self::is_woo_coupon_protection_enabled() );
	}

	/**
	 * Load WooCommerce protection on demand
	 * This can be called from other parts of the system if needed
	 */
	public static function load_on_demand() {
		if ( ! class_exists( __CLASS__ ) ) {
			require_once WF_SN_PLUGIN_DIR . 'modules/woocommerce/class-wf-sn-woo-protection.php';
		}
		if ( ! self::is_loaded_and_enabled() ) {
			return false;
		}
		return true;
	}
}

// Initialize the class
add_action( 'init', array( 'WPSecurityNinja\Plugin\Wf_Sn_Woo_Protection', 'init' ) );
