<?php
/**
 * Lite form-plugin integrations — Pro overlay only.
 *
 * Secure design (rafter-secure-design / auth + ingestion):
 * - Identity: site visitors submitting third-party forms. No new auth primitive.
 * - AuthZ: This file is absent from the wordpress.org Lite zip. Lite keeps
 *   WP + WooCommerce surfaces. Overlay + license unlocks CF7, WPForms,
 *   Formidable, Fluent, and Basic Forms. Elementor stays in module.php
 *   (field class is already an overlay).
 * - Ingestion: posted CAPTCHA key/answer are sanitized via Module wrappers
 *   (sanitize_text_field, length cap). Verification is a one-time transient
 *   compare — no new parser or network endpoint.
 *
 * @package SimpleCaptcha
 */

namespace SimpleCaptcha;

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

final class FormIntegrations {

	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['cf7'] ) && class_exists( 'WPCF7' ) ) {
			add_filter(
				'wpcf7_form_elements',
				static function ( string $content ) use ( $m ): string {
					ob_start();
					$m->renderWidget( 'cf7' );
					return self::injectBeforeSubmit( $content, (string) ob_get_clean() );
				},
				20
			);
			add_filter(
				'wpcf7_spam',
				static function ( bool $spam, $submission ) use ( $m ): bool {
					unset( $submission );
					if ( $spam ) {
						return true;
					}
					return ! $m->validateSimpleCaptchaRequest();
				},
				10,
				2
			);
		}

		if ( ! empty( $s['wpforms'] ) && function_exists( 'wpforms' ) ) {
			add_action(
				'wpforms_display_submit_before',
				static function ( $form_data ) use ( $m ): void {
					if ( ! is_array( $form_data ) || empty( $form_data['id'] ) ) {
						return;
					}
					$fid = absint( $form_data['id'] );
					$m->renderWidget( 'wpforms_' . $fid, false, '-wpf-' . $fid );
				},
				10,
				1
			);
			add_filter(
				'wpforms_process_initial_errors',
				static function ( array $errors, array $form_data ) use ( $m ): array {
					$form_id = isset( $form_data['id'] ) ? absint( $form_data['id'] ) : 0;
					if ( $form_id <= 0 ) {
						return $errors;
					}
					if ( $m->validateSimpleCaptchaRequest() ) {
						return $errors;
					}
					if ( ! isset( $errors[ $form_id ] ) || ! is_array( $errors[ $form_id ] ) ) {
						$errors[ $form_id ] = [];
					}
					$errors[ $form_id ]['footer'] = $m->failedCaptchaMessage();
					return $errors;
				},
				10,
				2
			);
		}

		if ( ! empty( $s['formidable'] ) && class_exists( 'FrmFormsController' ) ) {
			add_filter(
				'frm_submit_button_html',
				static function ( $button, $args ) use ( $m ) {
					$form = ( is_array( $args ) && ! empty( $args['form'] ) && is_object( $args['form'] ) ) ? $args['form'] : null;
					if ( $form === null || ! isset( $form->id ) ) {
						return (string) $button;
					}
					ob_start();
					$m->renderWidget( 'formidable_' . (int) $form->id );
					return (string) ob_get_clean() . $button;
				},
				10,
				2
			);
			add_filter(
				'frm_validate_entry',
				static function ( array $errors, array $values, $args = null ) use ( $m ): array {
					unset( $args, $values );
					if ( ! $m->validateSimpleCaptchaRequest() ) {
						$errors['captcha'] = $m->failedCaptchaMessage();
					}
					return $errors;
				},
				20,
				3
			);
		}

		if ( ! empty( $s['fluent_forms'] ) && defined( 'FLUENTFORM' ) ) {
			add_action(
				'fluentform/render_item_submit_button',
				static function ( $submit_button, $form ) use ( $m ): void {
					unset( $submit_button );
					if ( ! is_object( $form ) ) {
						return;
					}
					$suffix = isset( $form->id ) ? '-ff-' . (int) $form->id : '';
					echo '<div class="ff-el-group wpps-fluent-simple-captcha" style="margin-bottom:12px;">';
					$m->renderWidget( isset( $form->id ) ? 'fluent_' . (int) $form->id : 'fluent_form', false, $suffix );
					echo '</div>';
				},
				5,
				2
			);
			add_filter(
				'fluentform/validation_errors',
				static function ( array $errors, array $form_data, $form, array $fields ) use ( $m ): array {
					unset( $fields, $form );
					if ( $m->shouldSkip() ) {
						return $errors;
					}
					list( $key, $answer ) = $m->captchaPairFromFluent( $form_data );
					if ( $m->verifyPostedCaptcha( $key, $answer ) ) {
						return $errors;
					}
					$errors['wpps_simple_captcha'] = $m->failedCaptchaMessage( $key, $answer );
					return $errors;
				},
				10,
				4
			);
		}

		if ( ! empty( $s['basic_forms'] ) ) {
			add_action(
				'wpps_basic_forms_before_submit',
				static function ( int $form_id, array $settings ) use ( $m ): void {
					if ( empty( $settings['enable_spam_protection'] ) ) {
						return;
					}
					if ( ( $settings['captcha_provider'] ?? '' ) !== 'simple' ) {
						return;
					}
					$m->renderWidget( 'basic_forms_' . $form_id, true );
				},
				10,
				2
			);
			add_filter(
				'wpps_basic_forms_entry_data',
				static function ( array $data, int $form_id, array $settings ) use ( $m ): array {
					unset( $form_id );
					if ( ( $settings['captcha_provider'] ?? '' ) !== 'simple' ) {
						return $data;
					}
					if ( ( $m->getCaptchaSettings()['captcha_type'] ?? 'math' ) !== 'text' ) {
						return $data;
					}
					$q = isset( $_POST['wpps_simple_captcha_question'] ) ? (string) wp_unslash( $_POST['wpps_simple_captcha_question'] ) : '';
					$q = sanitize_text_field( substr( $q, 0, 500 ) );
					if ( $q === '' ) {
						return $data;
					}
					$label = __( 'CAPTCHA question', 'wp-powersuite' );
					$key   = $label;
					$n     = 1;
					while ( array_key_exists( $key, $data ) ) {
						$n++;
						$key = $label . ' (' . $n . ')';
					}
					$data[ $key ] = $q;
					return $data;
				},
				10,
				3
			);
			add_filter(
				'wpps_verify_basic_forms_captcha',
				static function ( bool $verified, int $form_id, array $settings ) use ( $m ): bool {
					unset( $form_id );
					if ( ( $settings['captcha_provider'] ?? '' ) !== 'simple' ) {
						return $verified;
					}
					return $m->verifyPostedCaptcha();
				},
				10,
				3
			);
		}
	}

	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;
	}
}
