<?php
/**
 * Settings Field Renderers
 *
 * @package AmbassadorHub\Admin\Settings
 */

namespace AmbassadorHub\Admin\Settings;

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

use function get_option;
use function get_pages;
use function esc_attr;
use function esc_html;
use function esc_html__;
use function esc_textarea;
use function checked;
use function selected;
use function absint;

/**
 * Static helper class for rendering WordPress settings form fields.
 *
 * Each method outputs a complete <tr> row suitable for use inside a
 * <table class="form-table"> element.
 *
 * Fields read their current value from wp_options via get_option() and use
 * the option key as the HTML name attribute — compatible with the WordPress
 * Settings API (options.php) and custom submission handlers alike.
 *
 * ## Usage
 *
 * From a tab's render() method or an ambh_settings_*_fields action callback:
 *
 *   echo '<table class="form-table"><tbody>';
 *   Fields::text( 'ambassador_hub_general_platform_name', __( 'Platform name', 'ambassadorhub' ) );
 *   Fields::checkbox( 'ambassador_hub_tools_debug_mode', __( 'Enable debug mode', 'ambassadorhub' ) );
 *   echo '</tbody></table>';
 *
 * From inside AbstractTab subclasses, use the inherited convenience wrappers:
 *
 *   $this->render_text_field( 'platform_name', __( 'Platform name', 'ambassadorhub' ) );
 *   // → delegates to Fields::text( 'ambh_{tab_id}_platform_name', ... )
 */
final class Fields {

	/**
	 * Render a help-tooltip icon next to a field label.
	 *
	 * Used instead of an always-visible <p class="description"> block so
	 * settings screens stay scannable — the explanation only shows on hover
	 * or focus of the icon. The bubble is hidden via opacity (not
	 * visibility), so it stays in the accessibility tree: pair this with
	 * aria-describedby="$tip_id" on the actual form control so screen reader
	 * users hear the explanation when they reach the field itself, without
	 * needing to interact with the icon.
	 *
	 * @param string $tip_id Unique id for the tooltip bubble (e.g. "{$option_key}-desc").
	 * @param string $text   Tooltip text. No-op when empty.
	 *
	 * @return void
	 */
	private static function help_tip( string $tip_id, string $text ): void {
		if ( ! $text ) {
			return;
		}
		echo '<span class="ambh-help-tip" tabindex="0">';
		echo '<span class="dashicons dashicons-editor-help" aria-hidden="true"></span>';
		echo '<span class="ambh-help-tip__bubble" role="tooltip" id="' . esc_attr( $tip_id ) . '">' . esc_html( $text ) . '</span>';
		echo '</span>';
	}

	/**
	 * Render a text input field.
	 *
	 * @param string $option_key  Full wp_options key — used as id, name, and to read the current value.
	 * @param string $title       Field title.
	 * @param string $description Optional help text, shown in a tooltip next to the label.
	 * @param string $type        Input type: text, email, url, or password. Default 'text'.
	 * @param array  $attributes   Additional HTML attributes for the <input> element, as an associative array of attribute => value pairs.
	 *
	 * @return void
	 */
	public static function text( string $option_key, string $title, string $description = '', string $type = 'text', array $attributes = array() ): void {
		$value  = (string) get_option( $option_key );
		$tip_id = $option_key . '-desc';

		echo '<tr>';
		echo '<th scope="row">';
		echo '<label for="' . esc_attr( $option_key ) . '">' . esc_html( $title ) . '</label>';
		self::help_tip( $tip_id, $description );
		echo '</th>';
		echo '<td>';
		$extra_class = isset( $attributes['class'] ) ? ' ' . $attributes['class'] : '';
		unset( $attributes['class'] );
		echo '<input type="' . esc_attr( $type ) . '" id="' . esc_attr( $option_key ) . '" name="' . esc_attr( $option_key ) . '" value="' . esc_attr( $value ) . '" class="regular-text' . esc_attr( $extra_class ) . '"';
		if ( $description ) {
			echo ' aria-describedby="' . esc_attr( $tip_id ) . '"';
		}
		foreach ( $attributes as $attr => $attr_value ) {
			echo ' ' . esc_attr( $attr ) . '="' . esc_attr( $attr_value ) . '"';
		}
		echo ' />';
		echo '</td>';
		echo '</tr>';
	}

	/**
	 * Render a password input field.
	 *
	 * Sets autocomplete="new-password" to prevent browser autofill on API key
	 * and secret fields.
	 *
	 * @param string $option_key  Full wp_options key.
	 * @param string $title       Field title.
	 * @param string $description Optional help text, shown in a tooltip next to the label.
	 *
	 * @return void
	 */
	public static function password( string $option_key, string $title, string $description = '' ): void {
		$value  = (string) get_option( $option_key );
		$tip_id = $option_key . '-desc';

		echo '<tr>';
		echo '<th scope="row">';
		echo '<label for="' . esc_attr( $option_key ) . '">' . esc_html( $title ) . '</label>';
		self::help_tip( $tip_id, $description );
		echo '</th>';
		echo '<td>';
		echo '<input type="password" id="' . esc_attr( $option_key ) . '" name="' . esc_attr( $option_key ) . '" value="' . esc_attr( $value ) . '" class="regular-text" autocomplete="new-password"' . ( $description ? ' aria-describedby="' . esc_attr( $tip_id ) . '"' : '' ) . ' />';
		echo '</td>';
		echo '</tr>';
	}

	/**
	 * Render a checkbox field.
	 *
	 * Stores '1' when checked, '' when unchecked.
	 *
	 * @param string $option_key  Full wp_options key.
	 * @param string $title       Label shown next to the checkbox.
	 * @param string $description Optional help text, shown in a tooltip next to the title.
	 *
	 * @return void
	 */
	public static function checkbox( string $option_key, string $title, string $label, string $description = '' ): void {
		$value  = get_option( $option_key );
		$tip_id = $option_key . '-desc';

		echo '<tr>';
		echo '<th scope="row">' . esc_html( $title );
		self::help_tip( $tip_id, $description );
		echo '</th>';
		echo '<td>';
		echo '<label>';
		echo '<input type="checkbox" id="' . esc_attr( $option_key ) . '" name="' . esc_attr( $option_key ) . '" value="1"' . checked( $value, '1', false ) . ( $description ? ' aria-describedby="' . esc_attr( $tip_id ) . '"' : '' ) . ' />'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- checked() is a WP core function that returns a safe HTML attribute string.
		echo ' ' . esc_html( $label );
		echo '</label>';
		echo '</td>';
		echo '</tr>';
	}

	/**
	 * Render a textarea field.
	 *
	 * @param string $option_key  Full wp_options key.
	 * @param string $title       Field title.
	 * @param string $description Optional help text, shown in a tooltip next to the label.
	 * @param int    $rows        Number of visible rows. Default 5.
	 *
	 * @return void
	 */
	public static function textarea( string $option_key, string $title, string $description = '', int $rows = 5, string $placeholder = '' ): void {
		$value  = (string) get_option( $option_key );
		$tip_id = $option_key . '-desc';

		echo '<tr>';
		echo '<th scope="row">';
		echo '<label for="' . esc_attr( $option_key ) . '">' . esc_html( $title ) . '</label>';
		self::help_tip( $tip_id, $description );
		echo '</th>';
		echo '<td>';

		echo '<textarea id="' . esc_attr( $option_key ) . '" name="' . esc_attr( $option_key ) . '" rows="' . absint( $rows ) . '" class="large-text"' . ( $placeholder ? ' placeholder="' . esc_attr( $placeholder ) . '"' : '' ) . ( $description ? ' aria-describedby="' . esc_attr( $tip_id ) . '"' : '' ) . '>' . esc_textarea( $value ) . '</textarea>';
		echo '</td>';
		echo '</tr>';
	}

	/**
	 * Render a select dropdown field.
	 *
	 * @param string               $option_key  Full wp_options key.
	 * @param string               $title       Field title.
	 * @param array<string,string> $options     Associative array of value => label pairs.
	 * @param string               $description Optional help text, shown in a tooltip next to the label.
	 *
	 * @return void
	 */
	public static function select( string $option_key, string $title, array $options, string $description = '' ): void {
		$value  = (string) get_option( $option_key );
		$tip_id = $option_key . '-desc';

		echo '<tr>';
		echo '<th scope="row">';
		echo '<label for="' . esc_attr( $option_key ) . '">' . esc_html( $title ) . '</label>';
		self::help_tip( $tip_id, $description );
		echo '</th>';
		echo '<td>';
		echo '<select id="' . esc_attr( $option_key ) . '" name="' . esc_attr( $option_key ) . '"' . ( $description ? ' aria-describedby="' . esc_attr( $tip_id ) . '"' : '' ) . '>';
		foreach ( $options as $opt_value => $opt_label ) {
			echo '<option value="' . esc_attr( (string) $opt_value ) . '"' . selected( $value, (string) $opt_value, false ) . '>' . esc_html( $opt_label ) . '</option>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- selected() is a WP core function that returns a safe HTML attribute string.
		}
		echo '</select>';
		echo '</td>';
		echo '</tr>';
	}

	/**
	 * Render a description-only row (no input element).
	 *
	 * Use this to insert explanatory text into the table flow between or
	 * before other fields, without breaking the <table class="form-table">
	 * structure.
	 *
	 * $text may contain a limited subset of inline HTML:
	 * <code>, <strong>, <em>, <a href>, <br>.
	 * All other tags and attributes are stripped by wp_kses().
	 *
	 * @param string $text  Description text to display. May contain safe inline HTML.
	 *
	 * @return void
	 */
	public static function description( string $text ): void {

		if ( ! $text ) {
			return;
		}

		$allowed_html = array(
			'code'   => array(),
			'strong' => array(),
			'em'     => array(),
			'br'     => array(),
			'a'      => array(
				'href'   => array(),
				'target' => array(),
				'rel'    => array(),
			),
		);

		echo '</tbody></table>';
		echo '<p>' . wp_kses( $text, $allowed_html ) . '</p>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- wp_kses() sanitizes to the explicit $allowed_html allowlist above.
		echo '<table class="form-table"><tbody>';
	}

	/**
	 * Render a page selector dropdown.
	 *
	 * Lists all published WordPress pages. Stores the selected page ID
	 * as an integer in wp_options.
	 *
	 * @param string $option_key  Full wp_options key (stores the selected page ID).
	 * @param string $title       Field title.
	 * @param string $description Optional help text, shown in a tooltip next to the label.
	 *
	 * @return void
	 */
	public static function page_selector( string $option_key, string $title, string $description = '' ): void {
		$page_id = absint( get_option( $option_key, 0 ) );
		$tip_id  = $option_key . '-desc';

		$pages = get_pages(
			array(
				'post_status' => 'publish',
				'sort_column' => 'post_title',
			)
		);

		echo '<tr>';
		echo '<th scope="row">';
		echo '<label for="' . esc_attr( $option_key ) . '">' . esc_html( $title ) . '</label>';
		self::help_tip( $tip_id, $description );
		echo '</th>';
		echo '<td>';
		echo '<select id="' . esc_attr( $option_key ) . '" name="' . esc_attr( $option_key ) . '"' . ( $description ? ' aria-describedby="' . esc_attr( $tip_id ) . '"' : '' ) . '>';
		echo '<option value="">' . esc_html__( '-- Select Page --', 'ambassadorhub' ) . '</option>';
		foreach ( $pages as $page ) {
			$is_selected = $page->ID === $page_id ? ' selected="selected"' : '';
			echo '<option value="' . absint( $page->ID ) . '"' . $is_selected . '>' . esc_html( $page->post_title ) . '</option>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- $is_selected is a static safe string from a ternary with no user input.
		}
		echo '</select>';
		echo '</td>';
		echo '</tr>';
	}
}
