<?php

namespace SugarCalendarBookings\Antispam\Captcha\Settings;

use SugarCalendarBookings\Antispam\Captcha\CaptchaVerifierRegistry;
use SugarCalendarBookings\Support\Helpers\UI;

/**
 * Shared scaffolding for captcha settings classes.
 *
 * Owns the field-rendering helpers and the secret-override detection that
 * used to live inline on AntispamSettingsTab. Concrete classes implement
 * the CaptchaSettingsInterface methods using these helpers.
 *
 * @since 1.5.0
 */
abstract class AbstractCaptchaSettings implements CaptchaSettingsInterface {

	/**
	 * Derive owned method-keys by iterating the verifier registry and matching
	 * `::CATEGORY` against this category's key.
	 *
	 * @since 1.5.0
	 *
	 * @return array<int, string>
	 */
	public function get_method_keys(): array {

		$keys = [];

		foreach ( CaptchaVerifierRegistry::all() as $method_key => $verifier_class ) {
			if ( $this->get_key() === $verifier_class::CATEGORY ) {
				$keys[] = $method_key;
			}
		}

		return $keys;
	}

	/**
	 * Whether the given stored method-key belongs to this category.
	 *
	 * @since 1.5.0
	 *
	 * @param string $method Stored flat method-key.
	 *
	 * @return bool
	 */
	public function owns_method( string $method ): bool {

		return in_array( $method, $this->get_method_keys(), true );
	}

	/**
	 * Render a radio group inside SCB's standard setting row.
	 *
	 * Relocated from AntispamSettingsTab::render_radio_group(). Markup is
	 * byte-identical.
	 *
	 * @since 1.5.0
	 *
	 * @param string $name        Dot-path segment under `sugar-calendar-bookings[antispam][...]`.
	 * @param string $label       Group label.
	 * @param array  $options     Map of value => label.
	 * @param string $description Description text (allows <a>).
	 * @param string $value       Current value.
	 * @param string $row_class   Extra CSS class for the row wrapper.
	 *
	 * @return void
	 */
	protected static function render_radio_group(
		string $name,
		string $label,
		array $options,
		string $description,
		string $value = '',
		string $row_class = ''
	): void {

		$dot_path  = explode( '.', $name );
		$input_id  = 'antispam-' . str_replace( '.', '-', $name );
		$name_attr = 'sugar-calendar-bookings[antispam]';

		foreach ( $dot_path as $segment ) {
			$name_attr .= '[' . $segment . ']';
		}

		ob_start();

		foreach ( $options as $option_value => $option_label ) {
			echo '<span class="sugar-calendar-bookings-settings-field-radio-wrapper">';
				printf(
					'<input type="radio" id="%1$s" name="%2$s" value="%3$s" %4$s/>',
					esc_attr( $input_id . '-' . $option_value ),
					esc_attr( $name_attr ),
					esc_attr( $option_value ),
					checked( $option_value, $value, false )
				);
				printf(
					'<label for="%1$s">%2$s</label>',
					esc_attr( $input_id . '-' . $option_value ),
					esc_html( $option_label )
				);
			echo '</span>';
		}

		if ( ! empty( $description ) ) {
			echo '<p class="desc">';
				echo wp_kses(
					$description,
					[
						'a'  => [
							'href'   => true,
							'target' => true,
							'rel'    => true,
						],
						'br' => [],
					]
				);
			echo '</p>';
		}

		UI::field_wrapper(
			[
				'id'    => $input_id,
				'type'  => 'radio',
				'label' => $label,
				'class' => $row_class,
			],
			ob_get_clean()
		);
	}

	/**
	 * `wp_kses()` whitelist for documentation links inside card descriptions.
	 *
	 * @since 1.5.0
	 *
	 * @return array
	 */
	public static function allowed_link_html(): array {

		return [
			'a' => [
				'href'   => true,
				'target' => true,
				'rel'    => true,
			],
		];
	}

	/**
	 * Whether a resolved secret indicates a code-level filter override of the
	 * stored option.
	 *
	 * Relocated from AntispamSettingsTab::is_secret_overridden(). Semantics
	 * preserved exactly.
	 *
	 * @since 1.5.0
	 *
	 * @param string $resolved Resolved secret (post-filter).
	 * @param string $stored   Raw stored option value.
	 *
	 * @return bool
	 */
	protected static function is_secret_overridden( string $resolved, string $stored ): bool {

		return $resolved !== '' && $resolved !== $stored;
	}
}
