<?php
/**
 * Conditional-logic rule catalog for Code Snippet.
 *
 * Secure design (rafter-secure-design / ingestion):
 * - Rule types and operators are allowlisted here. Unknown types are dropped on save.
 * - Value widgets never accept raw HTML; every field is escaped on render.
 * - Geo/IP use request headers only — no outbound lookup.
 *
 * @package CodeSnippet
 */

namespace CodeSnippet;

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

/**
 * Labels, operators, and editor widgets for snippet conditions.
 */
final class ConditionalCatalog {

	public const QUERY_TYPES = [
		'type_of_page',
		'post_type',
		'taxonomy_archive',
		'taxonomy',
		'term',
		'post_meta',
		'post_status',
		'post_id',
		'page_template',
		'author',
		'wc_page',
		'edd_page',
		'mepr_page',
	];

	public const OPERATORS = [
		'contains',
		'not_contains',
		'equals',
		'not_equals',
		'exists',
		'not_exists',
		'greater_than',
		'less_than',
		'before',
		'after',
		'is_empty',
		'is_not_empty',
	];

	/**
	 * @return array<string, array{label: string, types: list<string>}>
	 */
	public static function groups(): array {
		return [
			'user'      => [
				'label' => __( 'User', 'wppowersuite-lite' ),
				'types' => [ 'logged_in', 'user_role', 'user_meta', 'device', 'browser', 'os', 'cookie', 'country', 'continent', 'session' ],
			],
			'content'   => [
				'label' => __( 'Content & location', 'wppowersuite-lite' ),
				'types' => [ 'type_of_page', 'post_type', 'taxonomy_archive', 'taxonomy', 'term', 'url', 'full_url', 'url_path', 'query_var', 'post_meta', 'post_status', 'post_id', 'page_template', 'author', 'referer', 'user_agent' ],
			],
			'ecommerce' => [
				'label' => __( 'eCommerce', 'wppowersuite-lite' ),
				'types' => [ 'wc_page', 'wc_order_count', 'wc_lifetime_spend', 'wc_cart_total', 'wc_product_in_cart', 'edd_page', 'mepr_page', 'mepr_user' ],
			],
			'advanced'  => [
				'label' => __( 'Advanced', 'wppowersuite-lite' ),
				'types' => [ 'date', 'datetime', 'day_of_week', 'time_of_day', 'snippet_loaded', 'ip' ],
			],
		];
	}

	/**
	 * @return array<string, array<string, mixed>>
	 */
	public static function types(): array {
		static $cached = null;
		if ( is_array( $cached ) ) {
			return $cached;
		}

		$page_types   = self::pageTypeOptions();
		$post_types   = [];
		foreach ( get_post_types( [ 'public' => true ], 'objects' ) as $pt ) {
			$post_types[ $pt->name ] = $pt->label;
		}
		$user_roles = function_exists( 'wp_roles' ) ? wp_roles()->get_names() : [];
		$taxonomies = [];
		foreach ( get_taxonomies( [ 'public' => true ], 'objects' ) as $tax ) {
			$taxonomies[ $tax->name ] = $tax->label;
		}
		$templates = [ '' => __( 'Default template', 'wppowersuite-lite' ) ];
		if ( function_exists( 'wp_get_theme' ) ) {
			foreach ( wp_get_theme()->get_page_templates() as $file => $label ) {
				$templates[ $file ] = $label;
			}
		}

		$string_ops   = [ 'contains', 'not_contains', 'equals', 'not_equals' ];
		$equal_ops    = [ 'equals', 'not_equals' ];
		$exist_ops    = [ 'exists', 'not_exists' ];
		$exist_or_val = [ 'exists', 'not_exists', 'contains', 'not_contains', 'equals', 'not_equals' ];
		$num_ops      = [ 'equals', 'not_equals', 'greater_than', 'less_than' ];
		$date_ops     = [ 'equals', 'not_equals', 'before', 'after' ];

		$types = [
			'logged_in'          => [
				'label'     => __( 'User login status', 'wppowersuite-lite' ),
				'operators' => $equal_ops,
				'value'     => 'select',
				'options'   => [ '1' => __( 'Logged in', 'wppowersuite-lite' ), '0' => __( 'Logged out', 'wppowersuite-lite' ) ],
			],
			'user_role'          => [
				'label'     => __( 'User role', 'wppowersuite-lite' ),
				'operators' => $equal_ops,
				'value'     => 'select',
				'options'   => $user_roles,
			],
			'user_meta'          => [
				'label'            => __( 'User meta field', 'wppowersuite-lite' ),
				'operators'        => $exist_or_val,
				'value'            => 'key_value',
				'key_placeholder'  => __( 'Meta key', 'wppowersuite-lite' ),
				'value_placeholder'=> __( 'Meta value', 'wppowersuite-lite' ),
			],
			'device'             => [
				'label'     => __( 'Device type', 'wppowersuite-lite' ),
				'operators' => $equal_ops,
				'value'     => 'select',
				'options'   => [
					'desktop' => __( 'Desktop', 'wppowersuite-lite' ),
					'tablet'  => __( 'Tablet', 'wppowersuite-lite' ),
					'mobile'  => __( 'Mobile', 'wppowersuite-lite' ),
				],
			],
			'browser'            => [
				'label'     => __( 'Browser', 'wppowersuite-lite' ),
				'operators' => $equal_ops,
				'value'     => 'select',
				'options'   => [
					'chrome'  => 'Chrome',
					'firefox' => 'Firefox',
					'safari'  => 'Safari',
					'edge'    => 'Edge',
					'opera'   => 'Opera',
					'ie'      => 'Internet Explorer',
				],
			],
			'os'                 => [
				'label'     => __( 'Operating system', 'wppowersuite-lite' ),
				'operators' => $equal_ops,
				'value'     => 'select',
				'options'   => [
					'windows' => 'Windows',
					'macos'   => 'macOS',
					'linux'   => 'Linux',
					'ios'     => 'iOS',
					'android' => 'Android',
				],
			],
			'cookie'             => [
				'label'             => __( 'Cookie', 'wppowersuite-lite' ),
				'operators'         => $exist_or_val,
				'value'             => 'key_value',
				'key_placeholder'   => __( 'Cookie name', 'wppowersuite-lite' ),
				'value_placeholder' => __( 'Cookie value', 'wppowersuite-lite' ),
			],
			'country'            => [
				'label'             => __( 'Visitor country', 'wppowersuite-lite' ),
				'operators'         => $equal_ops,
				'value'             => 'text',
				'value_placeholder' => __( 'ISO code, e.g. US', 'wppowersuite-lite' ),
			],
			'continent'          => [
				'label'     => __( 'Visitor continent', 'wppowersuite-lite' ),
				'operators' => $equal_ops,
				'value'     => 'select',
				'options'   => [
					'AF' => __( 'Africa', 'wppowersuite-lite' ),
					'AN' => __( 'Antarctica', 'wppowersuite-lite' ),
					'AS' => __( 'Asia', 'wppowersuite-lite' ),
					'EU' => __( 'Europe', 'wppowersuite-lite' ),
					'NA' => __( 'North America', 'wppowersuite-lite' ),
					'OC' => __( 'Oceania', 'wppowersuite-lite' ),
					'SA' => __( 'South America', 'wppowersuite-lite' ),
				],
			],
			'session'            => [
				'label'             => __( 'Session variable', 'wppowersuite-lite' ),
				'operators'         => $exist_or_val,
				'value'             => 'key_value',
				'key_placeholder'   => __( 'Session key', 'wppowersuite-lite' ),
				'value_placeholder' => __( 'Session value', 'wppowersuite-lite' ),
			],
			'type_of_page'       => [
				'label'     => __( 'Page type', 'wppowersuite-lite' ),
				'operators' => $equal_ops,
				'value'     => 'select',
				'options'   => $page_types,
			],
			'post_type'          => [
				'label'     => __( 'Post type', 'wppowersuite-lite' ),
				'operators' => $equal_ops,
				'value'     => 'select',
				'options'   => $post_types,
			],
			'taxonomy_archive'   => [
				'label'     => __( 'Taxonomy archive', 'wppowersuite-lite' ),
				'operators' => $equal_ops,
				'value'     => 'select',
				'options'   => $taxonomies,
			],
			'taxonomy'           => [
				'label'     => __( 'Taxonomy type', 'wppowersuite-lite' ),
				'operators' => $equal_ops,
				'value'     => 'select',
				'options'   => $taxonomies,
			],
			'term'               => [
				'label'             => __( 'Taxonomy term', 'wppowersuite-lite' ),
				'operators'         => $string_ops,
				'value'             => 'text',
				'value_placeholder' => __( 'Term slug or name', 'wppowersuite-lite' ),
			],
			'url'                => [
				'label'             => __( 'URL (path or query)', 'wppowersuite-lite' ),
				'operators'         => $string_ops,
				'value'             => 'text',
				'value_placeholder' => __( '/shop or ?promo=', 'wppowersuite-lite' ),
			],
			'full_url'           => [
				'label'             => __( 'Full page URL', 'wppowersuite-lite' ),
				'operators'         => $string_ops,
				'value'             => 'text',
				'value_placeholder' => __( 'https://example.com/path', 'wppowersuite-lite' ),
			],
			'url_path'           => [
				'label'             => __( 'URL path', 'wppowersuite-lite' ),
				'operators'         => $string_ops,
				'value'             => 'text',
				'value_placeholder' => __( '/shop or /shop/*', 'wppowersuite-lite' ),
			],
			'query_var'          => [
				'label'             => __( 'URL query parameter', 'wppowersuite-lite' ),
				'operators'         => $exist_or_val,
				'value'             => 'key_value',
				'key_placeholder'   => __( 'Parameter name', 'wppowersuite-lite' ),
				'value_placeholder' => __( 'Parameter value', 'wppowersuite-lite' ),
			],
			'post_meta'          => [
				'label'             => __( 'Post meta field', 'wppowersuite-lite' ),
				'operators'         => $exist_or_val,
				'value'             => 'key_value',
				'key_placeholder'   => __( 'Meta key', 'wppowersuite-lite' ),
				'value_placeholder' => __( 'Meta value', 'wppowersuite-lite' ),
			],
			'post_status'        => [
				'label'     => __( 'Post status', 'wppowersuite-lite' ),
				'operators' => $equal_ops,
				'value'     => 'select',
				'options'   => [
					'publish' => __( 'Published', 'wppowersuite-lite' ),
					'draft'   => __( 'Draft', 'wppowersuite-lite' ),
					'pending' => __( 'Pending', 'wppowersuite-lite' ),
					'future'  => __( 'Scheduled', 'wppowersuite-lite' ),
					'private' => __( 'Private', 'wppowersuite-lite' ),
				],
			],
			'post_id'            => [
				'label'             => __( 'Specific posts or pages', 'wppowersuite-lite' ),
				'operators'         => $equal_ops,
				'value'             => 'text',
				'value_placeholder' => __( 'IDs, comma-separated', 'wppowersuite-lite' ),
			],
			'page_template'      => [
				'label'     => __( 'Page template', 'wppowersuite-lite' ),
				'operators' => $equal_ops,
				'value'     => 'select',
				'options'   => $templates,
			],
			'author'             => [
				'label'             => __( 'Author', 'wppowersuite-lite' ),
				'operators'         => $equal_ops,
				'value'             => 'text',
				'value_placeholder' => __( 'Author ID or login', 'wppowersuite-lite' ),
			],
			'referer'            => [
				'label'             => __( 'HTTP referrer', 'wppowersuite-lite' ),
				'operators'         => $string_ops,
				'value'             => 'text',
				'value_placeholder' => __( 'Referring URL', 'wppowersuite-lite' ),
			],
			'user_agent'         => [
				'label'             => __( 'User agent string', 'wppowersuite-lite' ),
				'operators'         => $string_ops,
				'value'             => 'text',
				'value_placeholder' => __( 'Substring or wildcard', 'wppowersuite-lite' ),
			],
			'wc_page'            => [
				'label'     => __( 'WooCommerce page', 'wppowersuite-lite' ),
				'operators' => $equal_ops,
				'value'     => 'select',
				'requires'  => 'woocommerce',
				'options'   => [
					'shop'            => __( 'Shop', 'wppowersuite-lite' ),
					'cart'            => __( 'Cart', 'wppowersuite-lite' ),
					'checkout'        => __( 'Checkout', 'wppowersuite-lite' ),
					'account'         => __( 'My Account', 'wppowersuite-lite' ),
					'product'         => __( 'Single product', 'wppowersuite-lite' ),
					'order_received'  => __( 'Order received', 'wppowersuite-lite' ),
				],
			],
			'wc_order_count'     => [
				'label'             => __( 'WooCommerce order count', 'wppowersuite-lite' ),
				'operators'         => $num_ops,
				'value'             => 'number',
				'requires'          => 'woocommerce',
				'value_placeholder' => '0',
			],
			'wc_lifetime_spend'  => [
				'label'             => __( 'WooCommerce lifetime spend', 'wppowersuite-lite' ),
				'operators'         => $num_ops,
				'value'             => 'number',
				'requires'          => 'woocommerce',
				'value_placeholder' => '0',
			],
			'wc_cart_total'      => [
				'label'             => __( 'WooCommerce cart total', 'wppowersuite-lite' ),
				'operators'         => $num_ops,
				'value'             => 'number',
				'requires'          => 'woocommerce',
				'value_placeholder' => '0',
			],
			'wc_product_in_cart' => [
				'label'             => __( 'WooCommerce product in cart', 'wppowersuite-lite' ),
				'operators'         => $equal_ops,
				'value'             => 'text',
				'requires'          => 'woocommerce',
				'value_placeholder' => __( 'Product ID', 'wppowersuite-lite' ),
			],
			'edd_page'           => [
				'label'     => __( 'Easy Digital Downloads page', 'wppowersuite-lite' ),
				'operators' => $equal_ops,
				'value'     => 'select',
				'requires'  => 'edd',
				'options'   => [
					'checkout'         => __( 'Checkout', 'wppowersuite-lite' ),
					'success'          => __( 'Purchase confirmation', 'wppowersuite-lite' ),
					'purchase_history' => __( 'Purchase history', 'wppowersuite-lite' ),
					'download'         => __( 'Single download', 'wppowersuite-lite' ),
				],
			],
			'mepr_page'          => [
				'label'     => __( 'MemberPress page', 'wppowersuite-lite' ),
				'operators' => $equal_ops,
				'value'     => 'select',
				'requires'  => 'memberpress',
				'options'   => [
					'login'    => __( 'Login', 'wppowersuite-lite' ),
					'account'  => __( 'Account', 'wppowersuite-lite' ),
					'register' => __( 'Registration', 'wppowersuite-lite' ),
					'thankyou' => __( 'Thank you', 'wppowersuite-lite' ),
				],
			],
			'mepr_user'          => [
				'label'     => __( 'MemberPress member status', 'wppowersuite-lite' ),
				'operators' => $equal_ops,
				'value'     => 'select',
				'requires'  => 'memberpress',
				'options'   => [
					'active'  => __( 'Active', 'wppowersuite-lite' ),
					'expired' => __( 'Expired', 'wppowersuite-lite' ),
					'pending' => __( 'Pending', 'wppowersuite-lite' ),
					'none'    => __( 'Not a member', 'wppowersuite-lite' ),
				],
			],
			'date'               => [
				'label'     => __( 'Specific date', 'wppowersuite-lite' ),
				'operators' => $date_ops,
				'value'     => 'date',
			],
			'datetime'           => [
				'label'     => __( 'Specific date & time', 'wppowersuite-lite' ),
				'operators' => $date_ops,
				'value'     => 'datetime',
			],
			'day_of_week'        => [
				'label'     => __( 'Day of the week', 'wppowersuite-lite' ),
				'operators' => $equal_ops,
				'value'     => 'select',
				'options'   => [
					'0' => __( 'Sunday', 'wppowersuite-lite' ),
					'1' => __( 'Monday', 'wppowersuite-lite' ),
					'2' => __( 'Tuesday', 'wppowersuite-lite' ),
					'3' => __( 'Wednesday', 'wppowersuite-lite' ),
					'4' => __( 'Thursday', 'wppowersuite-lite' ),
					'5' => __( 'Friday', 'wppowersuite-lite' ),
					'6' => __( 'Saturday', 'wppowersuite-lite' ),
				],
			],
			'time_of_day'        => [
				'label'     => __( 'Time of day', 'wppowersuite-lite' ),
				'operators' => $date_ops,
				'value'     => 'time',
			],
			'snippet_loaded'     => [
				'label'             => __( 'Another snippet already ran', 'wppowersuite-lite' ),
				'operators'         => $equal_ops,
				'value'             => 'text',
				'value_placeholder' => __( 'Snippet ID', 'wppowersuite-lite' ),
			],
			'ip'                 => [
				'label'             => __( 'Visitor IP address', 'wppowersuite-lite' ),
				'operators'         => $equal_ops,
				'value'             => 'text',
				'value_placeholder' => __( 'IP, list, or CIDR', 'wppowersuite-lite' ),
			],
		];

		$cached = $types;
		return $cached;
	}

	/**
	 * @return array<string, string>
	 */
	public static function pageTypeOptions(): array {
		return [
			'is_front_page' => __( 'Homepage', 'wppowersuite-lite' ),
			'is_home'       => __( 'Blog home', 'wppowersuite-lite' ),
			'is_page'       => __( 'Static page', 'wppowersuite-lite' ),
			'is_single'     => __( 'Single post', 'wppowersuite-lite' ),
			'is_singular'   => __( 'Any singular', 'wppowersuite-lite' ),
			'is_archive'    => __( 'Archive', 'wppowersuite-lite' ),
			'is_category'   => __( 'Category archive', 'wppowersuite-lite' ),
			'is_tag'        => __( 'Tag archive', 'wppowersuite-lite' ),
			'is_tax'        => __( 'Custom taxonomy archive', 'wppowersuite-lite' ),
			'is_search'     => __( 'Search page', 'wppowersuite-lite' ),
			'is_404'        => __( '404 page', 'wppowersuite-lite' ),
			'is_author'     => __( 'Author page', 'wppowersuite-lite' ),
		];
	}

	/**
	 * @return string[]
	 */
	public static function typeIds(): array {
		return array_keys( self::types() );
	}

	public static function isKnownType( string $type ): bool {
		return in_array( $type, self::typeIds(), true );
	}

	public static function isQueryType( string $type ): bool {
		return in_array( $type, self::QUERY_TYPES, true );
	}

	/**
	 * Integration plugins that unlock matching condition types.
	 *
	 * @return array<string, array{label: string, active: bool}>
	 */
	public static function pluginIntegrations(): array {
		return [
			'woocommerce' => [
				'label'  => __( 'WooCommerce', 'wppowersuite-lite' ),
				'active' => class_exists( 'WooCommerce', false ),
			],
			'edd'         => [
				'label'  => __( 'Easy Digital Downloads', 'wppowersuite-lite' ),
				'active' => class_exists( 'Easy_Digital_Downloads', false ) || function_exists( 'EDD' ),
			],
			'memberpress' => [
				'label'  => __( 'MemberPress', 'wppowersuite-lite' ),
				'active' => defined( 'MEPR_VERSION' ) || class_exists( 'MeprAppCtrl', false ),
			],
		];
	}

	public static function isIntegrationActive( string $slug ): bool {
		if ( $slug === '' ) {
			return true;
		}
		$all = self::pluginIntegrations();
		return ! isset( $all[ $slug ] ) || ! empty( $all[ $slug ]['active'] );
	}

	public static function typeRequirement( string $type ): string {
		$types = self::types();
		return isset( $types[ $type ]['requires'] ) ? (string) $types[ $type ]['requires'] : '';
	}

	public static function isTypeAvailable( string $type ): bool {
		return self::isIntegrationActive( self::typeRequirement( $type ) );
	}

	/**
	 * @return array{available: bool, label: string, requires: string}
	 */
	public static function typeAvailability( string $type, string $base_label ): array {
		$requires = self::typeRequirement( $type );
		$available = self::isTypeAvailable( $type );
		$label     = $base_label;
		if ( ! $available ) {
			$plugin = self::pluginIntegrations()[ $requires ]['label'] ?? $requires;
			$label  = sprintf(
				/* translators: 1: condition name, 2: required plugin name. */
				__( '%1$s (requires %2$s)', 'wppowersuite-lite' ),
				$base_label,
				$plugin
			);
		}
		return [
			'available' => $available,
			'label'     => $label,
			'requires'  => $requires,
		];
	}

	/**
	 * @return array<string, mixed>
	 */
	public static function jsConfig(): array {
		$types = [];
		foreach ( self::types() as $id => $def ) {
			$avail = self::typeAvailability( $id, (string) $def['label'] );
			$types[ $id ] = [
				'operators'         => $def['operators'],
				'value'             => $def['value'],
				'options'           => $def['options'] ?? new \stdClass(),
				'key_placeholder'   => $def['key_placeholder'] ?? '',
				'value_placeholder' => $def['value_placeholder'] ?? __( 'Value', 'wppowersuite-lite' ),
				'requires'          => $avail['requires'],
				'available'         => $avail['available'],
				'locked_label'      => $avail['label'],
			];
		}

		$groups = [];
		foreach ( self::groups() as $group ) {
			$items = [];
			foreach ( $group['types'] as $id ) {
				if ( isset( self::types()[ $id ] ) ) {
					$items[ $id ] = self::types()[ $id ]['label'];
				}
			}
			$groups[] = [
				'label' => $group['label'],
				'types' => $items,
			];
		}

		return [
			'groups'    => $groups,
			'types'     => $types,
			'operators' => [
				'contains'      => __( 'contains', 'wppowersuite-lite' ),
				'not_contains'  => __( 'does not contain', 'wppowersuite-lite' ),
				'equals'        => __( 'equals', 'wppowersuite-lite' ),
				'not_equals'    => __( 'does not equal', 'wppowersuite-lite' ),
				'exists'        => __( 'exists', 'wppowersuite-lite' ),
				'not_exists'    => __( 'does not exist', 'wppowersuite-lite' ),
				'greater_than'  => __( 'greater than', 'wppowersuite-lite' ),
				'less_than'     => __( 'less than', 'wppowersuite-lite' ),
				'before'        => __( 'before', 'wppowersuite-lite' ),
				'after'         => __( 'after', 'wppowersuite-lite' ),
				'is_empty'      => __( 'is empty', 'wppowersuite-lite' ),
				'is_not_empty'  => __( 'is not empty', 'wppowersuite-lite' ),
			],
		];
	}

	public static function typeSelectHtml( string $selected ): string {
		$html = '<select class="wpps-cs-rule-type">';
		foreach ( self::groups() as $group ) {
			$html .= '<optgroup label="' . esc_attr( $group['label'] ) . '">';
			foreach ( $group['types'] as $id ) {
				$types = self::types();
				if ( ! isset( $types[ $id ] ) ) {
					continue;
				}
				$avail    = self::typeAvailability( $id, (string) $types[ $id ]['label'] );
				$disabled = ! $avail['available'] && $selected !== $id;
				$html    .= '<option value="' . esc_attr( $id ) . '"' . selected( $selected, $id, false ) . disabled( $disabled, true, false ) . '>' . esc_html( $avail['label'] ) . '</option>';
			}
			$html .= '</optgroup>';
		}
		$html .= '</select>';
		return $html;
	}

	public static function operatorSelectHtml( string $type, string $selected ): string {
		$types = self::types();
		$ops   = $types[ $type ]['operators'] ?? [ 'contains', 'not_contains', 'equals', 'not_equals' ];
		if ( ! in_array( $selected, $ops, true ) ) {
			$selected = $ops[0];
		}
		$labels = self::jsConfig()['operators'];
		$html   = '<select class="wpps-cs-rule-operator">';
		foreach ( $ops as $op ) {
			$html .= '<option value="' . esc_attr( $op ) . '"' . selected( $selected, $op, false ) . '>' . esc_html( $labels[ $op ] ?? $op ) . '</option>';
		}
		$html .= '</select>';
		return $html;
	}

	/**
	 * @param array{type?: string, operator?: string, value?: string, key?: string} $rule
	 */
	public static function valueFieldsHtml( array $rule ): string {
		$type     = (string) ( $rule['type'] ?? 'url' );
		$value    = (string) ( $rule['value'] ?? '' );
		$key      = (string) ( $rule['key'] ?? '' );
		$operator = (string) ( $rule['operator'] ?? '' );
		$def      = self::types()[ $type ] ?? self::types()['url'];
		$kind     = $def['value'];
		$ph       = $def['value_placeholder'] ?? __( 'Value', 'wppowersuite-lite' );
		$key_ph   = $def['key_placeholder'] ?? __( 'Key', 'wppowersuite-lite' );
		$hide_val = in_array( $operator, [ 'exists', 'not_exists' ], true );

		if ( $kind === 'select' ) {
			if ( $hide_val ) {
				return '';
			}
			$html = '<select class="wpps-cs-rule-value wpps-cs-rule-value-select">';
			foreach ( (array) ( $def['options'] ?? [] ) as $opt => $label ) {
				$html .= '<option value="' . esc_attr( (string) $opt ) . '"' . selected( $value, (string) $opt, false ) . '>' . esc_html( (string) $label ) . '</option>';
			}
			$html .= '</select>';
			return $html;
		}

		if ( $kind === 'key_value' ) {
			$html = '<input type="text" class="wpps-cs-rule-key wpps-cs-input" value="' . esc_attr( $key ) . '" placeholder="' . esc_attr( $key_ph ) . '">';
			if ( ! $hide_val ) {
				$html .= '<input type="text" class="wpps-cs-rule-value wpps-cs-input wpps-cs-rule-value-text" value="' . esc_attr( $value ) . '" placeholder="' . esc_attr( $ph ) . '">';
			}
			return $html;
		}

		$input_type = 'text';
		if ( $kind === 'number' ) {
			$input_type = 'number';
		} elseif ( $kind === 'date' ) {
			$input_type = 'date';
		} elseif ( $kind === 'datetime' ) {
			$input_type = 'datetime-local';
		} elseif ( $kind === 'time' ) {
			$input_type = 'time';
		}

		if ( $hide_val ) {
			return '';
		}

		return '<input type="' . esc_attr( $input_type ) . '" class="wpps-cs-rule-value wpps-cs-input wpps-cs-rule-value-text" value="' . esc_attr( $value ) . '" placeholder="' . esc_attr( $ph ) . '">';
	}
}
