<?php
/**
 * Extensions for the Rule Form, in lieu of refactoring the form.
 *
 * @link       https://personalizewp.com/
 * @since      3.2.0 Merged into PWP
 * @since      3.0.0
 *
 * @package    PersonalizeWP
 * @subpackage PersonalizeWP/Admin
 */

namespace PersonalizeWP\Admin;

use PersonalizeWP\Admin\Utils;

defined( 'ABSPATH' ) || exit; // Exit if accessed directly.

/**
 * Extends the core plugin's rule form to support autocomplete fields
 */
class RuleFormExtension {

	/**
	 * Configuration for autocomplete conditions
	 *
	 * @var array
	 */
	private static array $autocomplete_configs = [
		'woocommerce_product_stock_level'       => [
			'mode'          => 'product',
			'content_types' => 'products',
		],
		'woocommerce_product_quantity_in_cart'  => [
			'mode'          => 'product',
			'content_types' => 'products',
		],
		'woocommerce_category_quantity_in_cart' => [
			'mode'          => 'product',
			'content_types' => 'categories',
		],
	];

	/**
	 * Initialize the form extension
	 *
	 * @return void
	 */
	public static function init(): void {
		// Hook into the base plugin's condition rendering
		add_action( 'personalizewp_rule_condition_custom_fields', [ __CLASS__, 'render_autocomplete_field' ], 10, 5 );
		add_action( 'personalizewp_rule_condition_template_custom_fields', [ __CLASS__, 'render_autocomplete_template' ] );
		add_action( 'admin_enqueue_scripts', [ __CLASS__, 'enqueue_scripts' ] );
	}

	/**
	 * Check if a condition identifier is an autocomplete condition
	 *
	 * @param string $condition_identifier The condition identifier
	 * @return bool
	 */
	private static function is_autocomplete_condition( string $condition_identifier ): bool {
		return array_key_exists( $condition_identifier, self::$autocomplete_configs );
	}

	/**
	 * Render autocomplete field for existing conditions
	 *
	 * @param object      $condition            The current condition object
	 * @param object|null $condition_class      The condition class instance
	 * @param string      $condition_identifier The condition identifier
	 * @param string      $condition_type       The comparison type
	 * @return void
	 */
	public static function render_autocomplete_field( $condition, $condition_class, $condition_identifier, $condition_type ): void { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed
		if ( ! self::is_autocomplete_condition( $condition_identifier ) ) {
			return;
		}

		$config         = self::$autocomplete_configs[ $condition_identifier ];
		$measure_key    = $condition_class ? $condition_class->measure_key : null;
		$meta_value     = $measure_key && ! empty( $condition->meta->$measure_key ) ? $condition->meta->$measure_key : '';
		$selected_items = self::prepare_selected_items( $meta_value, $condition_identifier );

		self::output_autocomplete_field( $config, $selected_items );
	}

	/**
	 * Render autocomplete template for new conditions
	 *
	 * @param array $all_grouped_conditions_options Available condition options
	 * @return void
	 */
	public static function render_autocomplete_template( $all_grouped_conditions_options ): void { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.Found
		// Output templates for each autocomplete condition type
		foreach ( self::$autocomplete_configs as $condition_id => $config ) {
			self::output_autocomplete_template( $condition_id, $config );
		}
	}

	/**
	 * Prepare selected items from meta value
	 *
	 * @param string $meta_value          The meta value (comma-separated IDs)
	 * @param string $condition_identifier The condition identifier
	 * @return array
	 */
	private static function prepare_selected_items( string $meta_value, string $condition_identifier ): array {
		if ( empty( $meta_value ) ) {
			return [];
		}

		$selected_items = [];
		$ids            = array_filter( array_map( 'trim', explode( ',', $meta_value ) ) );

		foreach ( $ids as $id ) {
			$item_data = self::get_item_data( $id, $condition_identifier );
			if ( $item_data ) {
				$selected_items[] = $item_data;
			}
		}

		return $selected_items;
	}

	/**
	 * Get item data for display
	 *
	 * @param string $id                  The item ID
	 * @param string $condition_identifier The condition identifier
	 * @return array|null
	 */
	private static function get_item_data( string $id, string $condition_identifier ): ?array {
		$numeric_id = self::extract_numeric_id( $id );
		if ( ! $numeric_id ) {
			return null;
		}

		switch ( $condition_identifier ) {
			case 'woocommerce_product_stock_level':
			case 'woocommerce_product_quantity_in_cart':
				$prod_name = sprintf(
					/* translators: 1: %s Product ID. */
					__( 'Product #%1$s', 'personalizewp' ),
					$numeric_id
				);
				$product = function_exists( 'wc_get_product' ) ? wc_get_product( $numeric_id ) : null;
				if ( $product instanceof \WC_Product ) {
					$prod_name = $product->get_name();
				}
				return [
					'value' => "woocommerce:product:{$numeric_id}",
					'text'  => $prod_name,
				];
				break;

			case 'woocommerce_category_quantity_in_cart':
				$term_name = sprintf(
					/* translators: 1: %s Category ID. */
					__( 'Category #%1$s', 'personalizewp' ),
					$numeric_id
				);
				$term = get_term( $numeric_id, 'product_cat' );
				if ( $term && ! is_wp_error( $term ) ) {
					$term_name = $term->name;
				}
				return [
					'value' => "woocommerce:product_cat:{$numeric_id}",
					'text'  => $term_name,
				];
				break;
		}

		return null;
	}

	/**
	 * Extract numeric ID from value
	 *
	 * @param string $value The value to extract from
	 * @return string|null
	 */
	private static function extract_numeric_id( string $value ): ?string {
		// If it's already numeric, return as is
		if ( is_numeric( $value ) ) {
			return $value;
		}

		// Extract from formats like "woocommerce:product:123"
		if ( preg_match( '/:(\d+)$/', $value, $matches ) ) {
			return $matches[1];
		}

		return null;
	}

	/**
	 * Output the autocomplete field HTML
	 *
	 * @param array $config         The autocomplete configuration
	 * @param array $selected_items Selected items for content attribute
	 * @return void
	 */
	private static function output_autocomplete_field( array $config, array $selected_items = [] ): void {
		$comma_separated_values = '';
		if ( ! empty( $selected_items ) ) {
			$values                 = array_map(
				function ( $item ) {
					$val = self::extract_numeric_id( $item['value'] );
					return ( $val ) ? $val : $item['value'];
				},
				$selected_items
			);
			$comma_separated_values = implode( ',', $values );
		}

		self::render_autocomplete_html( $config, $selected_items, $comma_separated_values );
	}

	/**
	 * Output autocomplete template for new conditions
	 *
	 * @param string $condition_id The condition identifier
	 * @param array  $config       The autocomplete configuration
	 * @return void
	 */
	private static function output_autocomplete_template( string $condition_id, array $config ): void {
		?>
		<template id="pwp-autocomplete-template-<?php echo esc_attr( $condition_id ); ?>" hidden>
			<?php self::render_autocomplete_html( $config ); ?>
		</template>
		<?php
	}

	/**
	 * Render autocomplete HTML
	 *
	 * @param array  $config         The autocomplete configuration
	 * @param array  $selected_items Selected items for content attribute
	 * @param string $comma_separated_values Comma-separated values for the main input
	 * @return void
	 */
	private static function render_autocomplete_html( array $config, array $selected_items = [], string $comma_separated_values = '' ): void {
		$content_attr = ! empty( $selected_items ) ? wp_json_encode( $selected_items ) : '';
		?>
		<div class="autocomplete-field-wrapper field-wrapper-styles" style="display: none;" data-condition-type="autocomplete">
			<input type="hidden" name="personalizewp_form[conditions][meta_value][]" value="<?php echo esc_attr( $comma_separated_values ); ?>" class="rule-condition-values" />

			<auto-complete
				mode="product"
				<?php
				switch ( $config['content_types'] ) :
					case 'products':
						printf(
							'placeholder="%s"',
							esc_attr__( 'Search for a product', 'personalizewp' )
						);
						break;

					case 'categories':
						printf(
							'placeholder="%s"',
							esc_attr__( 'Search for a category', 'personalizewp' )
						);
						break;
				endswitch;
				?>
				class="rule-condition-autocomplete"
				content="<?php echo esc_attr( $content_attr ); ?>"
				content-types="<?php echo esc_attr( $config['content_types'] ); ?>"
			>
				<template hidden>
					<span></span>
					<input type="hidden" name="pwp_autocomplete_item[]" value="" class="autocomplete-item-input" />
					<button type="button" data-type="selected" aria-label="<?php esc_attr_e( 'Remove', 'personalizewp' ); ?>">
						<?php Utils::svg_icon( 'cross' ); ?>
					</button>
				</template>
			</auto-complete>
		</div>
		<?php
	}

	/**
	 * Enqueue scripts and styles for autocomplete functionality
	 *
	 * @param string $hook_suffix The current admin page hook suffix
	 * @return void
	 */
	public static function enqueue_scripts( string $hook_suffix ): void { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.Found

		if ( ! personalizewp()->admin->is_admin_page() ) {
			return;
		}

		wp_add_inline_script(
			'personalizewp',
			'pwpRuleFormEx = ' . wp_json_encode(
				[
					'autocomplete_conditions' => array_keys( self::$autocomplete_configs ),
				]
			) . ';',
			'before'
		);
	}
}
