<?php

namespace SugarCalendarBookings\Antispam\Captcha\Settings;

use SugarCalendarBookings\Antispam\Captcha\CaptchaVerifierRegistry;
use SugarCalendarBookings\Antispam\Captcha\RecaptchaV2;
use SugarCalendarBookings\Antispam\Captcha\RecaptchaV3;
use SugarCalendarBookings\Options;
use SugarCalendarBookings\Plugin;
use SugarCalendarBookings\Support\Helpers\Helpers;
use SugarCalendarBookings\Support\Helpers\UI;

/**
 * Google reCAPTCHA settings — covers V2 checkbox, V2 invisible, and V3 under
 * a single card and panel.
 *
 * @since 1.5.0
 */
final class RecaptchaSettings extends AbstractCaptchaSettings {

	/**
	 * Default sub-method written when reCAPTCHA is freshly selected.
	 *
	 * @since 1.5.0
	 */
	private const DEFAULT_SUB_METHOD = 'checkbox_recaptcha_v2';

	/**
	 * Category key matching `RecaptchaV2::CATEGORY` and `RecaptchaV3::CATEGORY`.
	 *
	 * @since 1.5.0
	 *
	 * @return string
	 */
	public function get_key(): string {

		return 'recaptcha';
	}

	/**
	 * Default flat method-key written when this category is freshly selected.
	 *
	 * @since 1.5.0
	 *
	 * @return string
	 */
	public function default_method_key(): string {

		return self::DEFAULT_SUB_METHOD;
	}

	/**
	 * Card metadata for the methods-selection grid.
	 *
	 * @since 1.5.0
	 *
	 * @return array
	 */
	public function get_card(): array {

		return [
			'title'       => esc_html__( 'reCAPTCHA', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
			'icon'        => SCBOOKINGS_PLUGIN_URL . 'assets/images/icons/settings-captcha-recaptcha.svg',
			'description' => '<p>' . wp_kses(
				sprintf(
					/* translators: %1$s - link to the SCB anti-spam documentation. */
					__( 'reCAPTCHA is a free anti-spam service from Google which helps to protect your website from spam and abuse while letting real people pass through with ease. <a href="%1$s" target="_blank" rel="noopener">Learn more about method</a>.', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
					esc_url(
						Helpers::get_utm_url(
							'https://sugarcalendar.com/docs/bookings/how-to-set-up-google-recaptcha/',
							[
								'content' => 'documentation',
								'medium'  => 'plugin-settings-antispam',
							]
						)
					)
				),
				self::allowed_link_html()
			) . '</p>',
		];
	}

	/**
	 * Render the reCAPTCHA panel HTML.
	 *
	 * Output is byte-identical to the markup previously emitted by
	 * `AntispamSettingsTab::get_recaptcha_fields()`.
	 *
	 * @since 1.5.0
	 *
	 * @param string $stored_method Currently saved flat method-key.
	 *
	 * @return string
	 */
	public function render_panel( string $stored_method ): string {

		$options    = Plugin::get( Options::class );
		$sub_method = in_array( $stored_method, $this->get_method_keys(), true )
			? $stored_method
			: self::DEFAULT_SUB_METHOD;
		$is_v3      = $sub_method === 'recaptcha_v3';

		// v2 and v3 each own their site/secret slot so admins can configure
		// both without losing the other's keys when toggling sub-methods.
		$v2_stored_secret     = (string) $options->get( RecaptchaV2::SECRET_OPTION_KEY );
		$v2_resolved_secret   = RecaptchaV2::filter_secret_key( $v2_stored_secret );
		$v2_secret_overridden = self::is_secret_overridden( $v2_resolved_secret, $v2_stored_secret );

		$v3_stored_secret     = (string) $options->get( RecaptchaV3::SECRET_OPTION_KEY );
		$v3_resolved_secret   = RecaptchaV3::filter_secret_key( $v3_stored_secret );
		$v3_secret_overridden = self::is_secret_overridden( $v3_resolved_secret, $v3_stored_secret );

		ob_start();

		self::render_radio_group(
			'recaptcha.method',
			esc_html__( 'Method', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
			[
				'checkbox_recaptcha_v2'  => esc_html__( 'Checkbox reCAPTCHA v2', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
				'invisible_recaptcha_v2' => esc_html__( 'Invisible reCAPTCHA v2', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
				'recaptcha_v3'           => esc_html__( 'reCAPTCHA v3', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
			],
			esc_html__( 'Sites already using one type of reCAPTCHA will need to create new site keys before switching to a different option.', 'sugar-calendar-bookings-scheduling-appointments-lite' )
			. '<br>' . sprintf(
				wp_kses( /* translators: %1$s - link to the reCAPTCHA documentation. */
					__( '<a href="%1$s" target="_blank" rel="noopener">Read our walk through</a> to learn more and for step-by-step directions.', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
					[
						'a' => [
							'href'   => true,
							'target' => true,
							'rel'    => true,
						],
					]
				),
				esc_url(
					Helpers::get_utm_url(
						'https://sugarcalendar.com/docs/bookings/how-to-set-up-google-recaptcha/',
						[
							'content' => 'Read our walk through',
							'medium'  => 'plugin-settings-antispam',
						]
					)
				)
			),
			$sub_method
		);

		// v2 key pair — hidden when v3 is the active sub-method but still POSTs
		// so the stored value survives sub-method toggles.
		UI::text_input(
			[
				'class'       => $is_v3 ? 'scb-antispam-hide' : '',
				'type'        => 'text',
				'id'          => 'antispam_recaptcha_v2_site_key',
				'name'        => [ 'antispam', 'recaptcha_v2', 'site_key' ],
				'value'       => $options->get( RecaptchaV2::SITE_KEY_OPTION_KEY ),
				'label'       => esc_html__( 'Site Key', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
				'description' => esc_html__( 'Enter your reCAPTCHA v2 site key.', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
			]
		);

		UI::text_input(
			[
				'class'       => $is_v3 ? 'scb-antispam-hide' : '',
				'type'        => 'text',
				'id'          => 'antispam_recaptcha_v2_secret_key',
				'name'        => [ 'antispam', 'recaptcha_v2', 'secret_key' ],
				'value'       => $v2_secret_overridden ? $v2_resolved_secret : $v2_stored_secret,
				'label'       => esc_html__( 'Secret Key', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
				'disabled'    => $v2_secret_overridden,
				'description' => $v2_secret_overridden
					? esc_html__( 'Defined via filter. Edit the filter callback in code to change this value.', 'sugar-calendar-bookings-scheduling-appointments-lite' )
					: esc_html__( 'Enter your reCAPTCHA v2 secret key.', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
			]
		);

		// v3 key pair — hidden unless v3 is the active sub-method.
		UI::text_input(
			[
				'class'       => $is_v3 ? '' : 'scb-antispam-hide',
				'type'        => 'text',
				'id'          => 'antispam_recaptcha_v3_site_key',
				'name'        => [ 'antispam', 'recaptcha_v3', 'site_key' ],
				'value'       => $options->get( RecaptchaV3::SITE_KEY_OPTION_KEY ),
				'label'       => esc_html__( 'Site Key', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
				'description' => esc_html__( 'Enter your reCAPTCHA v3 site key.', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
			]
		);

		UI::text_input(
			[
				'class'       => $is_v3 ? '' : 'scb-antispam-hide',
				'type'        => 'text',
				'id'          => 'antispam_recaptcha_v3_secret_key',
				'name'        => [ 'antispam', 'recaptcha_v3', 'secret_key' ],
				'value'       => $v3_secret_overridden ? $v3_resolved_secret : $v3_stored_secret,
				'label'       => esc_html__( 'Secret Key', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
				'disabled'    => $v3_secret_overridden,
				'description' => $v3_secret_overridden
					? esc_html__( 'Defined via filter. Edit the filter callback in code to change this value.', 'sugar-calendar-bookings-scheduling-appointments-lite' )
					: esc_html__( 'Enter your reCAPTCHA v3 site secret.', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
			]
		);

		self::render_radio_group(
			'recaptcha.theme',
			esc_html__( 'Type', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
			[
				'auto'  => esc_html__( 'Auto', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
				'light' => esc_html__( 'Light', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
				'dark'  => esc_html__( 'Dark', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
			],
			esc_html__( 'Select the visual appearance of the reCAPTCHA widget.', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
			$options->get( 'antispam.recaptcha.theme' ) ?: 'auto',
			$sub_method === 'recaptcha_v3' ? 'scb-antispam-hide' : ''
		);

		$fail_message   = (string) $options->get( 'antispam.recaptcha.fail_message' );
		$verifier_class = CaptchaVerifierRegistry::all()[ $sub_method ] ?? RecaptchaV2::class;
		$verifier       = new $verifier_class();

		UI::text_input(
			[
				'type'        => 'text',
				'id'          => 'antispam_recaptcha_fail_message',
				'name'        => [ 'antispam', 'recaptcha', 'fail_message' ],
				'value'       => $fail_message !== '' ? $fail_message : $verifier->get_fail_message_default(),
				'label'       => esc_html__( 'Fail Message', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
				'description' => esc_html__( 'Displays to users who fail the verification process.', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
			]
		);

		UI::number_input(
			[
				'class'       => $sub_method !== 'recaptcha_v3' ? 'scb-antispam-hide' : '',
				'id'          => 'antispam_recaptcha_threshold',
				'name'        => [ 'antispam', 'recaptcha', 'threshold' ],
				'value'       => $options->get( 'antispam.recaptcha.threshold' ),
				'step'        => 0.1,
				'min'         => 0.0,
				'max'         => 1.0,
				'label'       => esc_html__( 'Threshold', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
				'description' => esc_html__( 'reCAPTCHA v3 returns a score (1.0 is very likely a good interaction, 0.0 is very likely a bot). If the score is less than or equal to this threshold, the booking submission will be blocked and the message above will be displayed.', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
			]
		);

		return ob_get_clean();
	}

	/**
	 * Validation rules for the reCAPTCHA panel's posted fields.
	 *
	 * @since 1.5.0
	 *
	 * @return array<string, string>
	 */
	public function get_validation_rules(): array {

		return [
			'antispam.recaptcha_v2.site_key'   => 'string',
			'antispam.recaptcha_v2.secret_key' => 'string',
			'antispam.recaptcha_v3.site_key'   => 'string',
			'antispam.recaptcha_v3.secret_key' => 'string',
			'antispam.recaptcha.theme'         => 'string|in:auto,light,dark',
			'antispam.recaptcha.threshold'     => 'numeric',
			'antispam.recaptcha.fail_message'  => 'string',
		];
	}

	/**
	 * Sanitize the reCAPTCHA slice of the submitted antispam payload.
	 *
	 * - Drops the transient `recaptcha.method` sub-radio (UI-only — the flat
	 *   method already lives at `antispam.method`).
	 * - Strips each variant's secret_key when its resolved value is
	 *   filter-overridden, preventing the override from leaking into DB.
	 *
	 * @since 1.5.0
	 *
	 * @param array $antispam Submitted `antispam` array slice.
	 *
	 * @return array Mutated array slice.
	 */
	public function sanitize_post_data( array $antispam ): array {

		unset( $antispam['recaptcha']['method'] );

		$options = Plugin::get( Options::class );

		$v2_stored = (string) $options->get( RecaptchaV2::SECRET_OPTION_KEY );
		if ( self::is_secret_overridden( RecaptchaV2::filter_secret_key( $v2_stored ), $v2_stored ) ) {
			unset( $antispam['recaptcha_v2']['secret_key'] );
		}

		$v3_stored = (string) $options->get( RecaptchaV3::SECRET_OPTION_KEY );
		if ( self::is_secret_overridden( RecaptchaV3::filter_secret_key( $v3_stored ), $v3_stored ) ) {
			unset( $antispam['recaptcha_v3']['secret_key'] );
		}

		return $antispam;
	}

	/**
	 * Localized JS data block contributed under
	 * `sugar_calendar_bookings_admin.antispam.recaptcha`.
	 *
	 * @since 1.5.0
	 *
	 * @return array
	 */
	public function get_admin_script_data(): array {

		$options       = Plugin::get( Options::class );
		$stored_method = (string) $options->get( 'antispam.method' );
		$sub_method    = in_array( $stored_method, $this->get_method_keys(), true )
			? $stored_method
			: self::DEFAULT_SUB_METHOD;

		$site_key_option = $sub_method === 'recaptcha_v3'
			? RecaptchaV3::SITE_KEY_OPTION_KEY
			: RecaptchaV2::SITE_KEY_OPTION_KEY;

		return [
			'site_key' => $options->get( $site_key_option ),
			'method'   => $sub_method,
			'theme'    => $options->get( 'antispam.recaptcha.theme' ) ?: 'auto',
		];
	}

	/**
	 * User-facing description shown under the preview widget when reCAPTCHA
	 * is active and keys are complete.
	 *
	 * @since 1.5.0
	 *
	 * @return string
	 */
	public function get_preview_description(): string {

		return esc_html__( 'This reCAPTCHA is generated using your site and secret keys. If an error is displayed, please double-check your keys.', 'sugar-calendar-bookings-scheduling-appointments-lite' );
	}
}
