<?php
/**
 * Google reCAPTCHA Service.
 *
 * @package automation-web-platform
 */

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


/**
 * Class WAWP_Google_Recaptcha
 * Handles Google reCAPTCHA integration.
 *
 * @package automation-web-platform
 */
class WAWP_Google_Recaptcha {
	use WAWP_Security_Trait;
	use WAWP_Settings_Handler;

	/**
	 * Option group.
	 *
	 * @var string
	 */
	private $option_group = WAWP_Settings_Registry::_SETTINGS_GROUP;

	/**
	 * Verification result cache.
	 *
	 * @var bool|null
	 */
	private $verification_result = null;

	/**
	 * Instance.
	 *
	 * @var WAWP_Google_Recaptcha|null
	 */
	private static $instance = null;

	/**
	 * Get instance.
	 *
	 * @return WAWP_Google_Recaptcha
	 */
	public static function get_instance() {
		if ( null === self::$instance ) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	/**
	 * Constructor.
	 */
	public function __construct() {
		add_action( 'admin_init', array( $this, 'register_settings' ) );
		add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_recaptcha_scripts' ) );
		add_action( 'login_enqueue_scripts', array( $this, 'enqueue_recaptcha_scripts' ) );

		// Login Forms.
		add_action( 'login_form', array( $this, 'display_recaptcha_v2' ) );
		add_action( 'woocommerce_login_form', array( $this, 'display_recaptcha_v2' ) );

		// Registration Forms.
		add_action( 'register_form', array( $this, 'display_recaptcha_v2' ) );
		add_action( 'woocommerce_register_form', array( $this, 'display_recaptcha_v2' ) );

		// Lost Password.
		add_action( 'lostpassword_form', array( $this, 'display_recaptcha_v2' ) );
		add_action( 'woocommerce_lostpassword_form', array( $this, 'display_recaptcha_v2' ) );

		// Verification Hooks.
		add_filter( 'authenticate', array( $this, 'verify_login_recaptcha' ), 21 );
		add_filter( 'woocommerce_process_login_errors', array( $this, 'verify_wc_login_recaptcha' ), 10 );
		add_filter( 'woocommerce_process_registration_errors', array( $this, 'verify_wc_registration_recaptcha' ), 10 );
		add_action( 'lostpassword_post', array( $this, 'verify_lostpassword_recaptcha' ) );
		add_filter( 'registration_errors', array( $this, 'verify_registration_recaptcha' ), 10 );

		// WooCommerce Checkout.
		add_action( 'woocommerce_after_checkout_form', array( $this, 'display_recaptcha_v2' ) );
		add_action( 'woocommerce_checkout_process', array( $this, 'verify_checkout_recaptcha' ) );

		// Global Footer Fallback.
		add_action( 'wp_footer', array( $this, 'maybe_render_global_recaptcha' ) );
	}

	/**
	 * Get React settings data.
	 *
	 * @return array
	 */
	public function get_react_settings_data() {
		return array(
			'settings'             => array(
				'site_key'            => $this->get_wawp_setting( WAWP_Settings_Registry::_SITE_KEY, '' ),
				'secret_key'          => $this->get_wawp_setting( WAWP_Settings_Registry::_SECRET_KEY, '' ),
				'type'                => $this->get_wawp_setting( WAWP_Settings_Registry::_TYPE, 'v2_invisible' ),
				'score'               => $this->get_wawp_setting( WAWP_Settings_Registry::_SCORE, '0.5' ),
				'enable_login'        => (int) $this->get_wawp_setting( WAWP_Settings_Registry::_ENABLE_LOGIN, 0 ),
				'enable_register'     => (int) $this->get_wawp_setting( WAWP_Settings_Registry::_ENABLE_REGISTER, 0 ),
				'enable_lostpassword' => (int) $this->get_wawp_setting( WAWP_Settings_Registry::_ENABLE_LOSTPASS, 0 ),
				'enable_checkout'     => (int) $this->get_wawp_setting( WAWP_Settings_Registry::_ENABLE_CHECKOUT, 0 ),
				'enable_wawp_login'   => (int) $this->get_wawp_setting( WAWP_Settings_Registry::_ENABLE_WAWP_LOGIN, 0 ),
				'enable_wawp_signup'  => (int) $this->get_wawp_setting( WAWP_Settings_Registry::_ENABLE_WAWP_SIGNUP, 0 ),
			),
			'optionNames'          => array(
				'site_key'            => WAWP_Settings_Registry::_SITE_KEY,
				'secret_key'          => WAWP_Settings_Registry::_SECRET_KEY,
				'type'                => WAWP_Settings_Registry::_TYPE,
				'score'               => WAWP_Settings_Registry::_SCORE,
				'enable_login'        => WAWP_Settings_Registry::_ENABLE_LOGIN,
				'enable_register'     => WAWP_Settings_Registry::_ENABLE_REGISTER,
				'enable_lostpassword' => WAWP_Settings_Registry::_ENABLE_LOSTPASS,
				'enable_checkout'     => WAWP_Settings_Registry::_ENABLE_CHECKOUT,
				'enable_wawp_login'   => WAWP_Settings_Registry::_ENABLE_WAWP_LOGIN,
				'enable_wawp_signup'  => WAWP_Settings_Registry::_ENABLE_WAWP_SIGNUP,
			),
			'replaceWcFormsActive' => (int) $this->get_wawp_setting( WAWP_Settings_Registry::REPLACE_WC_FORMS, 0 ),
			'nonce'                => wp_create_nonce( 'wp_rest' ),
			'restUrl'              => esc_url_raw( rest_url( 'wawp/v1' ) ),
			'i18n'                 => array(
				'title'                => esc_html__( 'Google reCAPTCHA', 'automation-web-platform' ),
				'subtitle'             => esc_html__( 'Protect your website from spam and abuse with Google reCAPTCHA.', 'automation-web-platform' ),
				'learnMore'            => esc_html__( 'Learn more', 'automation-web-platform' ),
				'apiConfig'            => esc_html__( 'API Configuration', 'automation-web-platform' ),
				'apiConfigDesc'        => esc_html__( 'Enter your reCAPTCHA keys and select the type.', 'automation-web-platform' ),
				'getKeys'              => esc_html__( 'Get keys here', 'automation-web-platform' ),
				'siteKey'              => esc_html__( 'Site Key', 'automation-web-platform' ),
				'secretKey'            => esc_html__( 'Secret Key', 'automation-web-platform' ),
				'type'                 => esc_html__( 'reCAPTCHA Type', 'automation-web-platform' ),
				'v2Invisible'          => esc_html__( 'V2 Invisible', 'automation-web-platform' ),
				'v2Checkbox'           => esc_html__( 'V2 Checkbox', 'automation-web-platform' ),
				'autoApplied'          => esc_html__( 'Auto-applied', 'automation-web-platform' ),
				'testConnection'       => esc_html__( 'Test Connection', 'automation-web-platform' ),
				'displayLocations'     => esc_html__( 'Display Locations', 'automation-web-platform' ),
				'displayLocationsDesc' => esc_html__( 'Choose where to display the reCAPTCHA widget.', 'automation-web-platform' ),
				'general'              => esc_html__( 'General', 'automation-web-platform' ),
				'locations'            => esc_html__( 'Locations', 'automation-web-platform' ),
				'wawpLoginLabel'       => esc_html__( 'Wawp Login Forms', 'automation-web-platform' ),
				'wawpLoginDesc'        => esc_html__( 'Protect custom Wawp OTP and Password login forms.', 'automation-web-platform' ),
				'wawpSignupLabel'      => esc_html__( 'Wawp Signup Form', 'automation-web-platform' ),
				'wawpSignupDesc'       => esc_html__( 'Protect the custom Wawp Signup form.', 'automation-web-platform' ),
				'wcCheckoutLabel'      => esc_html__( 'WooCommerce Checkout', 'automation-web-platform' ),
				'wcCheckoutDesc'       => esc_html__( 'Add reCAPTCHA to the WooCommerce Checkout page.', 'automation-web-platform' ),
				'wpLoginLabel'         => __( 'Login Forms (WP & WC)', 'automation-web-platform' ),
				'wpLoginDesc'          => esc_html__( 'Protect standard WordPress and WooCommerce login forms.', 'automation-web-platform' ),
				'wpRegisterLabel'      => __( 'Registration Forms (WP & WC)', 'automation-web-platform' ),
				'wpRegisterDesc'       => esc_html__( 'Protect standard WordPress and WooCommerce registration forms.', 'automation-web-platform' ),
				'lostPasswordLabel'    => esc_html__( 'Lost Password Forms', 'automation-web-platform' ),
				'lostPasswordDesc'     => esc_html__( 'Protect standard WordPress and WooCommerce lost password forms.', 'automation-web-platform' ),
				'disabledNotice'       => esc_html__( 'Disabled because "Replace WC Forms" is active. Wawp OTP Forms are currently replacing these standard forms.', 'automation-web-platform' ),
				'replaceWcForms'       => esc_html__( 'Replace WC Forms', 'automation-web-platform' ),
				'testing'              => esc_html__( 'Testing...', 'automation-web-platform' ),
				'settingsSaved'        => esc_html__( 'Settings saved successfully!', 'automation-web-platform' ),
				'configValidation'     => esc_html__( 'Configuration Validation', 'automation-web-platform' ),
				'configValidationDesc' => esc_html__( 'Test your integration directly before enabling it on live forms.', 'automation-web-platform' ),
				'keysRequired'         => esc_html__( 'Enter a site key to load the test widget.', 'automation-web-platform' ),
				'googleConsole'        => esc_html__( 'Google Console', 'automation-web-platform' ),
				'verifying'            => esc_html__( 'Verifying with Google...', 'automation-web-platform' ),
				'testSuccess'          => esc_html__( 'Success! Your reCAPTCHA configuration is valid and active.', 'automation-web-platform' ),
				'credentialsActive'    => esc_html__( 'reCAPTCHA credentials are configured and ready for validation.', 'automation-web-platform' ),
				'credentialsError'     => esc_html__( 'Site Key and Secret Key are required to enable bot protection.', 'automation-web-platform' ),
				/* translators: %s: number of forms */
				'protectionActive'     => esc_html__( 'Protection is active on <b>%s</b> specific forms.', 'automation-web-platform' ),
				'protectionWarning'    => esc_html__( 'No protection rules are enabled. Your forms are currently vulnerable to bots.', 'automation-web-platform' ),
				'syncFailed'           => esc_html__( 'Synchronization failed.', 'automation-web-platform' ),
				'networkError'         => esc_html__( 'Network error during synchronization.', 'automation-web-platform' ),
				'triggerChallenge'     => esc_html__( 'Trigger Invisible Challenge', 'automation-web-platform' ),
				'requiresWcForms'      => esc_html__( 'Requires WooCommerce Forms', 'automation-web-platform' ),
				'saving'               => esc_html__( 'Saving Changes...', 'automation-web-platform' ),
				'synchronized'         => esc_html__( 'All Changes Saved', 'automation-web-platform' ),
				'unsaved'              => esc_html__( 'Unsaved Changes', 'automation-web-platform' ),
				'saveChanges'          => esc_html__( 'Save Settings', 'automation-web-platform' ),
			),
		);
	}

	/**
	 * Register settings.
	 */
	public function register_settings() {
		register_setting(
			$this->option_group,
			WAWP_Settings_Registry::_SITE_KEY,
			array(
				'type'              => 'string',
				'sanitize_callback' => 'sanitize_text_field',
			)
		);
		register_setting(
			$this->option_group,
			WAWP_Settings_Registry::_SECRET_KEY,
			array(
				'type'              => 'string',
				'sanitize_callback' => 'sanitize_text_field',
			)
		);
		register_setting(
			$this->option_group,
			WAWP_Settings_Registry::_TYPE,
			array(
				'type'              => 'string',
				'default'           => 'v2_invisible',
				'sanitize_callback' => 'sanitize_key',
			)
		);
		register_setting(
			$this->option_group,
			WAWP_Settings_Registry::_SCORE,
			array(
				'type'              => 'string',
				'default'           => '0.5',
				'sanitize_callback' => 'sanitize_text_field',
			)
		);

		// Locations.
		register_setting(
			$this->option_group,
			WAWP_Settings_Registry::_ENABLE_LOGIN,
			array(
				'type'              => 'integer',
				'sanitize_callback' => 'absint',
			)
		);
		register_setting(
			$this->option_group,
			WAWP_Settings_Registry::_ENABLE_REGISTER,
			array(
				'type'              => 'integer',
				'sanitize_callback' => 'absint',
			)
		);
		register_setting(
			$this->option_group,
			WAWP_Settings_Registry::_ENABLE_LOSTPASS,
			array(
				'type'              => 'integer',
				'sanitize_callback' => 'absint',
			)
		);
		register_setting(
			$this->option_group,
			WAWP_Settings_Registry::_ENABLE_CHECKOUT,
			array(
				'type'              => 'integer',
				'sanitize_callback' => 'absint',
			)
		);
		register_setting(
			$this->option_group,
			WAWP_Settings_Registry::_ENABLE_WAWP_LOGIN,
			array(
				'type'              => 'integer',
				'sanitize_callback' => 'absint',
			)
		);
		register_setting(
			$this->option_group,
			WAWP_Settings_Registry::_ENABLE_WAWP_SIGNUP,
			array(
				'type'              => 'integer',
				'sanitize_callback' => 'absint',
			)
		);
	}

	/**
	 * Enqueue scripts.
	 */
	public function enqueue_recaptcha_scripts() {
		$site_key = $this->get_wawp_setting( WAWP_Settings_Registry::_SITE_KEY );
		if ( ! $site_key ) {
			return;
		}

		$is_active = false;

		// Always enqueue on login page if enabled.
		if ( 'wp-login.php' === $GLOBALS['pagenow'] ) {
			$is_active = true;
		}

		if ( ! $is_active && function_exists( 'is_checkout' ) && is_checkout() && $this->get_wawp_setting( WAWP_Settings_Registry::_ENABLE_CHECKOUT ) ) {
			$is_active = true;
		}

		if ( ! $is_active && ( is_account_page() || is_checkout() ) ) {
			$is_active = true;
		}

		if ( $is_active ) {
			wp_enqueue_style( 'wawp-frontend-css', WAWP_PLUGIN_URL . 'assets/css/wawp-frontend.css', array(), WAWP_PLUGIN_VERSION );
			wp_enqueue_script( 'google-recaptcha', 'https://www.google.com/recaptcha/api.js', array(), WAWP_PLUGIN_VERSION, true );
			wp_enqueue_script( 'wawp-recaptcha-frontend', WAWP_PLUGIN_URL . 'assets/js/wawp-recaptcha-frontend.js', array( 'jquery', 'google-recaptcha' ), WAWP_PLUGIN_VERSION, true );
		}
	}

	/**
	 * Display reCAPTCHA V2.
	 *
	 * @param bool $force Force display.
	 */
	public function display_recaptcha_v2( $force = false ) {
		$site_key = $this->get_wawp_setting( WAWP_Settings_Registry::_SITE_KEY );
		if ( ! $site_key ) {
			return;
		}

		$current_filter = current_filter();
		$enabled        = $force;
		if ( ! $enabled ) {
			if ( false !== strpos( $current_filter, 'login' ) && $this->get_wawp_setting( WAWP_Settings_Registry::_ENABLE_LOGIN ) ) {
				$enabled = true;
			}
			if ( false !== strpos( $current_filter, 'register' ) && $this->get_wawp_setting( WAWP_Settings_Registry::_ENABLE_REGISTER ) ) {
				$enabled = true;
			}
			if ( false !== strpos( $current_filter, 'lostpassword' ) && $this->get_wawp_setting( WAWP_Settings_Registry::_ENABLE_LOSTPASS ) ) {
				$enabled = true;
			}
			if ( ( false !== strpos( $current_filter, 'checkout' ) || false !== strpos( $current_filter, 'footer' ) ) && $this->get_wawp_setting( WAWP_Settings_Registry::_ENABLE_CHECKOUT ) ) {
				$enabled = true;
			}
		}

		if ( ! $enabled ) {
			return;
		}

		global $wawp_recaptcha_rendered;
		if ( ! empty( $wawp_recaptcha_rendered['global_v2'] ) ) {
			return;
		}

		$type      = $this->get_wawp_setting( WAWP_Settings_Registry::_TYPE, 'v2_invisible' );
		$badge_pos = is_rtl() ? 'bottomleft' : 'bottomright';
		if ( 'v2_checkbox' === $type ) {
			echo '<div class="g-recaptcha" data-sitekey="' . esc_attr( $site_key ) . '"></div>';
		} else {
			echo '<div class="g-recaptcha" data-sitekey="' . esc_attr( $site_key ) . '" data-size="invisible" data-badge="' . esc_attr( $badge_pos ) . '" data-callback="wawpInvisibleCallback"></div>';
		}

		$wawp_recaptcha_rendered['global_v2'] = true;
	}

	/**
	 * Maybe render global reCAPTCHA.
	 */
	public function maybe_render_global_recaptcha() {
		if ( is_admin() ) {
			return;
		}
		if ( ! $this->get_wawp_setting( WAWP_Settings_Registry::_ENABLE_CHECKOUT ) ) {
			return;
		}

		$is_checkout_context = false;
		if ( function_exists( 'is_checkout' ) && is_checkout() ) {
			$is_checkout_context = true;
		}

		if ( ! $is_checkout_context && is_page() ) {
			global $post;
			if ( isset( $post->post_content ) ) {
				if ( has_block( 'woocommerce/checkout', $post ) || has_shortcode( $post->post_content, 'woocommerce_checkout' ) ) {
					$is_checkout_context = true;
				}
			}
		}

		if ( $is_checkout_context ) {
			$this->display_recaptcha_v2( true );
		}
	}

	/**
	 * Verify login reCAPTCHA.
	 *
	 * @param WP_User|WP_Error $user User object.
	 * @return WP_User|WP_Error
	 */
	public function verify_login_recaptcha( $user ) {
		if ( ! $this->get_wawp_setting( WAWP_Settings_Registry::_ENABLE_LOGIN ) || ! filter_has_var( INPUT_POST, 'log' ) ) {
			return $user;
		}
		if ( ! $this->verify_token() ) {
			return new WP_Error( 'recaptcha_failed', esc_html__( '<strong>Error</strong>: reCAPTCHA verification failed. Please try again.', 'automation-web-platform' ) );
		}
		return $user;
	}

	/**
	 * Verify WC login reCAPTCHA.
	 *
	 * @param WP_Error $validation_error Validation error.
	 * @return WP_Error
	 */
	public function verify_wc_login_recaptcha( $validation_error ) {
		if ( ! $this->get_wawp_setting( WAWP_Settings_Registry::_ENABLE_LOGIN ) ) {
			return $validation_error;
		}
		if ( ! $this->verify_token() ) {
			$validation_error->add( 'recaptcha_failed', esc_html__( '<strong>Error</strong>: reCAPTCHA verification failed. Please try again.', 'automation-web-platform' ) );
		}
		return $validation_error;
	}

	/**
	 * Verify registration reCAPTCHA.
	 *
	 * @param WP_Error $errors Errors.
	 * @return WP_Error
	 */
	public function verify_registration_recaptcha( $errors ) {
		if ( ! $this->get_wawp_setting( WAWP_Settings_Registry::_ENABLE_REGISTER ) ) {
			return $errors;
		}
		if ( ! $this->verify_token() ) {
			$errors->add( 'recaptcha_failed', esc_html__( '<strong>Error</strong>: reCAPTCHA verification failed. Please try again.', 'automation-web-platform' ) );
		}
		return $errors;
	}

	/**
	 * Verify WC registration reCAPTCHA.
	 *
	 * @param WP_Error $validation_error Validation error.
	 * @return WP_Error
	 */
	public function verify_wc_registration_recaptcha( $validation_error ) {
		if ( ! $this->get_wawp_setting( WAWP_Settings_Registry::_ENABLE_REGISTER ) ) {
			return $validation_error;
		}
		if ( ! $this->verify_token() ) {
			$validation_error->add( 'recaptcha_failed', esc_html__( '<strong>Error</strong>: reCAPTCHA verification failed. Please try again.', 'automation-web-platform' ) );
		}
		return $validation_error;
	}

	/**
	 * Verify lost password reCAPTCHA.
	 */
	public function verify_lostpassword_recaptcha() {
		if ( ! $this->get_wawp_setting( WAWP_Settings_Registry::_ENABLE_LOSTPASS ) ) {
			return;
		}
		if ( ! $this->verify_token() ) {
			wp_die( esc_html__( 'Error: reCAPTCHA verification failed. Please try again.', 'automation-web-platform' ) );
		}
	}

	/**
	 * Verify checkout reCAPTCHA.
	 */
	public function verify_checkout_recaptcha() {
		if ( ! $this->get_wawp_setting( WAWP_Settings_Registry::_ENABLE_CHECKOUT ) ) {
			return;
		}
		if ( ! $this->verify_token() ) {
			wc_add_notice( esc_html__( '<strong>Error</strong>: reCAPTCHA verification failed. Please try again.', 'automation-web-platform' ), 'error' );
		}
	}

	/**
	 * Verify token.
	 *
	 * @param string|null $token Optional token to verify.
	 * @return bool
	 */
	public function verify_token( $token = null ) {
		if ( ! is_null( $this->verification_result ) ) {
			return $this->verification_result;
		}

		$secret = $this->get_wawp_setting( WAWP_Settings_Registry::_SECRET_KEY );
		if ( ! $secret ) {
			$this->verification_result = true;
			return true;
		}

		if ( is_null( $token ) ) {
			$request_method = isset( $_SERVER['REQUEST_METHOD'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REQUEST_METHOD'] ) ) : '';
			if ( 'POST' !== $request_method ) {
				return true;
			}

			$token = filter_input( INPUT_POST, 'g-recaptcha-response', FILTER_SANITIZE_SPECIAL_CHARS );
			if ( ! $token ) {
				$token = '';
			}
		}

		if ( ! $token ) {
			$relevant_fields = array( 'log', 'username', 'user_login', 'email', 'phone', 'billing_email' );
			$is_relevant     = false;
			foreach ( $relevant_fields as $field ) {
				if ( filter_has_var( INPUT_POST, $field ) ) {
					$is_relevant = true;
					break;
				}
			}
			if ( ! $is_relevant ) {
				return true;
			}
			$this->verification_result = false;
			return false;
		}

		$cache_key = 'wawp_recaptcha_' . md5( $token );
		$cached    = wp_cache_get( $cache_key, 'wawp_database' );
		if ( false !== $cached ) {
			$this->verification_result = (bool) $cached;
			return $this->verification_result;
		}

		$url      = 'https://www.google.com/recaptcha/api/siteverify';
		$response = wp_remote_post(
			$url,
			array(
				'body' => array(
					'secret'   => $secret,
					'response' => $token,
					'remoteip' => isset( $_SERVER['REMOTE_ADDR'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ) : '',
				),
			)
		);

		if ( is_wp_error( $response ) ) {
			$this->verification_result = false;
			return false;
		}

		$body                      = json_decode( wp_remote_retrieve_body( $response ), true );
		$this->verification_result = ! empty( $body['success'] );

		wp_cache_set( $cache_key, $this->verification_result, 'wawp_database', 60 ); // Cache for 1 minute.

		return $this->verification_result;
	}
}
