<?php
/**
 * Extra form/membership integrations (Gravity, Jetpack, bbPress, etc.).
 *
 * @package SimpleCaptcha
 */

namespace SimpleCaptcha;

final class ExtendedIntegrations {

	private static bool $booted = false;

	public static function boot( Module $m ): void {
		if ( self::$booted ) {
			return;
		}
		self::$booted = true;

		$s = $m->getCaptchaSettings();

		if ( ! empty( $s['integration_gravity'] ) && class_exists( 'GFForms' ) ) {
			add_filter(
				'gform_submit_button',
				static function ( $button, $form ) use ( $m ) {
					if ( ! is_array( $form ) || empty( $form['id'] ) ) {
						return $button;
					}
					ob_start();
					$m->renderWidget( 'gravity_' . absint( $form['id'] ) );
					return (string) ob_get_clean() . $button;
				},
				10,
				2
			);
			add_filter(
				'gform_validation',
				static function ( $result ) use ( $m ) {
					if ( empty( $result['form']['id'] ) ) {
						return $result;
					}
					$form_id = absint( $result['form']['id'] );
					$page    = isset( $_POST[ 'gform_target_page_number_' . $form_id ] )
						? (int) sanitize_text_field( wp_unslash( $_POST[ 'gform_target_page_number_' . $form_id ] ) )
						: 0;
					if ( ! isset( $_POST['wpps_simple_captcha_key'] ) && $page !== 0 ) {
						return $result;
					}
					if ( ! $m->validateSimpleCaptchaRequest() ) {
						$result['is_valid'] = false;
					}
					return $result;
				},
				10
			);
		}

		if ( ! empty( $s['integration_jetpack'] ) ) {
			add_filter(
				'jetpack_contact_form_html',
				static function ( $html ) use ( $m ) {
					if ( ! is_string( $html ) || $html === '' ) {
						return $html;
					}
					ob_start();
					$m->renderWidget( 'jetpack_contact' );
					$inject = (string) ob_get_clean();

					return self::injectBeforeSubmit( $html, $inject );
				},
				10
			);
			add_filter(
				'jetpack_contact_form_is_spam',
				static function ( $spam ) use ( $m ) {
					if ( $spam ) {
						return $spam;
					}
					return ! $m->validateSimpleCaptchaRequest();
				},
				10
			);
		}

		if ( ! empty( $s['integration_bbpress'] ) ) {
			add_action(
				'bbp_theme_before_topic_form_submit_wrapper',
				static function () use ( $m ) {
					$m->renderWidget( 'bbpress_topic' );
				}
			);
			add_action(
				'bbp_theme_before_reply_form_submit_wrapper',
				static function () use ( $m ) {
					$m->renderWidget( 'bbpress_reply' );
				}
			);
			add_action(
				'bbp_new_topic_pre_extras',
				static function () use ( $m ) {
					if ( 'POST' !== strtoupper( sanitize_text_field( wp_unslash( $_SERVER['REQUEST_METHOD'] ?? '' ) ) ) ) {
						return;
					}
					if ( ! $m->validateSimpleCaptchaRequest() ) {
						bbp_add_error( 'bbp_simple_captcha', $m->getSimpleCaptchaRequestErrorMessage() );
					}
				}
			);
			add_action(
				'bbp_new_reply_pre_extras',
				static function () use ( $m ) {
					if ( 'POST' !== strtoupper( sanitize_text_field( wp_unslash( $_SERVER['REQUEST_METHOD'] ?? '' ) ) ) ) {
						return;
					}
					if ( ! $m->validateSimpleCaptchaRequest() ) {
						bbp_add_error( 'bbp_simple_captcha', $m->getSimpleCaptchaRequestErrorMessage() );
					}
				}
			);
		}

		if ( ! empty( $s['integration_buddypress'] ) && class_exists( 'BuddyPress' ) ) {
			add_action(
				'bp_before_registration_submit_buttons',
				static function () use ( $m ) {
					$m->renderWidget( 'buddypress_register' );
				}
			);
			add_action(
				'bp_signup_validate',
				static function () use ( $m ) {
					if ( 'POST' !== strtoupper( sanitize_text_field( wp_unslash( $_SERVER['REQUEST_METHOD'] ?? '' ) ) ) ) {
						return;
					}
					if ( ! $m->validateSimpleCaptchaRequest() ) {
						wp_die( esc_html( $m->getSimpleCaptchaRequestErrorMessage() ), '', [ 'response' => 403, 'back_link' => true ] );
					}
				}
			);
		}

		if ( ! empty( $s['integration_ultimate_member'] ) && class_exists( 'UM' ) ) {
			add_action( 'um_after_login_fields', static fn () => $m->renderWidget( 'ultimate_member_login' ) );
			add_action( 'um_after_register_fields', static fn () => $m->renderWidget( 'ultimate_member_register' ) );
			add_action( 'um_after_password_reset_fields', static fn () => $m->renderWidget( 'ultimate_member_reset' ) );
			add_action(
				'um_submit_form_errors_hook_login',
				static function () use ( $m ) {
					if ( ! $m->validateSimpleCaptchaRequest() ) {
						UM()->form()->add_error( 'simple_captcha', $m->getSimpleCaptchaRequestErrorMessage() );
					}
				},
				20
			);
			add_action(
				'um_submit_form_errors_hook__registration',
				static function () use ( $m ) {
					if ( ! $m->validateSimpleCaptchaRequest() ) {
						UM()->form()->add_error( 'simple_captcha', $m->getSimpleCaptchaRequestErrorMessage() );
					}
				},
				20
			);
			add_action(
				'um_reset_password_errors_hook',
				static function () use ( $m ) {
					if ( ! $m->validateSimpleCaptchaRequest() ) {
						UM()->form()->add_error( 'simple_captcha', $m->getSimpleCaptchaRequestErrorMessage() );
					}
				},
				20
			);
		}

		if ( ! empty( $s['integration_memberpress'] ) && class_exists( 'MeprAppCtrl' ) ) {
			add_action( 'mepr-login-form-before-submit', static fn () => $m->renderWidget( 'memberpress_login' ) );
			add_action( 'mepr-checkout-before-submit', static fn () => $m->renderWidget( 'memberpress_checkout' ) );
			add_filter(
				'mepr-validate-login',
				static function ( $errors ) use ( $m ) {
					if ( ! $m->validateSimpleCaptchaRequest() ) {
						$errors[] = $m->getSimpleCaptchaRequestErrorMessage();
					}
					return $errors;
				}
			);
			add_filter(
				'mepr-validate-signup',
				static function ( $errors ) use ( $m ) {
					if ( ! $m->validateSimpleCaptchaRequest() ) {
						$errors[] = $m->getSimpleCaptchaRequestErrorMessage();
					}
					return $errors;
				},
				20
			);
		}

		if ( ! empty( $s['integration_edd'] ) && function_exists( 'EDD' ) ) {
			add_action( 'edd_login_fields_after', static fn () => $m->renderWidget( 'edd_login' ) );
			add_action( 'edd_register_form_fields_before_submit', static fn () => $m->renderWidget( 'edd_register' ) );
			add_action( 'edd_purchase_form_before_submit', static fn () => $m->renderWidget( 'edd_checkout' ) );
			add_filter(
				'authenticate',
				static function ( $user ) use ( $m ) {
					if ( isset( $_POST['edd_login_nonce'] ) && function_exists( 'edd_is_checkout' ) && ! edd_is_checkout() ) {
						if ( ! $m->validateSimpleCaptchaRequest() ) {
							return new \WP_Error( 'simple_captcha_failed', $m->getSimpleCaptchaRequestErrorMessage() );
						}
					}
					return $user;
				},
				21,
				1
			);
			add_action(
				'edd_process_register_form',
				static function () use ( $m ) {
					if ( function_exists( 'edd_is_checkout' ) && edd_is_checkout() ) {
						return;
					}
					if ( ! $m->validateSimpleCaptchaRequest() ) {
						edd_set_error( 'simple_captcha', $m->getSimpleCaptchaRequestErrorMessage() );
					}
				}
			);
			add_action(
				'edd_pre_process_purchase',
				static function () use ( $m ) {
					if ( ! isset( $_POST['edd-process-checkout-nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['edd-process-checkout-nonce'] ) ), 'edd-process-checkout' ) ) {
						return;
					}
					if ( ! $m->validateSimpleCaptchaRequest() ) {
						edd_set_error( 'simple_captcha', $m->getSimpleCaptchaRequestErrorMessage() );
					}
				}
			);
		}

		if ( ! empty( $s['integration_pmp'] ) && defined( 'PMPRO_VERSION' ) ) {
			add_action( 'pmpro_checkout_before_submit_button', static fn () => $m->renderWidget( 'pmp' ) );
			add_action(
				'pmpro_checkout_after_parameters_set',
				static function () use ( $m ) {
					if ( ! $m->validateSimpleCaptchaRequest() ) {
						pmpro_setMessage( $m->getSimpleCaptchaRequestErrorMessage(), 'pmpro_error' );
					}
				}
			);
		}

		if ( ! empty( $s['integration_mc4wp'] ) && defined( 'MC4WP_VERSION' ) ) {
			add_filter(
				'mc4wp_form_content',
				static function ( $content ) use ( $m ) {
					if ( ! is_string( $content ) || $content === '' ) {
						return $content;
					}
					ob_start();
					$m->renderWidget( 'mc4wp' );
					$inject = (string) ob_get_clean();

					return self::injectBeforeSubmit( $content, $inject );
				},
				40
			);
			add_filter(
				'mc4wp_form_errors',
				static function ( $errors ) use ( $m ) {
					if ( ! $m->validateSimpleCaptchaRequest() ) {
						$errors[] = $m->getSimpleCaptchaRequestErrorMessage();
					}
					return $errors;
				},
				10,
				2
			);
		}
	}

	/**
	 * Insert CAPTCHA markup immediately before the first submit control.
	 */
	private static function injectBeforeSubmit( string $html, string $inject ): string {
		if ( $inject === '' ) {
			return $html;
		}
		if ( preg_match( '/<input\b[^>]*\btype\s*=\s*["\']submit["\'][^>]*\/?>/i', $html ) ) {
			return (string) preg_replace(
				'/(<input\b[^>]*\btype\s*=\s*["\']submit["\'][^>]*\/?>)/i',
				$inject . '$1',
				$html,
				1
			);
		}
		if ( preg_match( '/<button\b[^>]*\btype\s*=\s*["\']submit["\'][^>]*>/i', $html ) ) {
			return (string) preg_replace(
				'/(<button\b[^>]*\btype\s*=\s*["\']submit["\'][^>]*>)/i',
				$inject . '$1',
				$html,
				1
			);
		}
		if ( stripos( $html, '</form>' ) !== false ) {
			return (string) preg_replace( '/(<\/form>)/i', $inject . '$1', $html, 1 );
		}

		return $html . $inject;
	}
}
