<?php

namespace Limb_Chatbot\Includes\Integrations\JetEngine;

use Limb_Chatbot\Includes\Data_Objects\Dataset;
use Limb_Chatbot\Includes\Interfaces\Knowledge_Content_Interface;
use Limb_Chatbot\Includes\Services\Collection;
use WP_Post;
use Exception;

/**
 * JetEngine integration class.
 *
 * Handles JetEngine custom fields integration for knowledge base content.
 *
 * Works safely inside custom API routes.
 */
class JetEngine implements Knowledge_Content_Interface {

	/**
	 * Dataset/collection key for JetEngine post-type meta fields.
	 *
	 * This represents JetEngine "meta fields" attached to a specific post type.
	 */
	const CUSTOM_FIELDS_KEY = 'jet_engine_custom_fields';

	/**
	 * Dataset/collection key for JetEngine meta box fields.
	 *
	 * This represents fields that come from JetEngine meta boxes configuration.
	 */
	const META_BOX_FIELDS_KEY = 'jet_engine_meta_box_fields';

	public static $id = 'jetengine';

	private static $hooks_registered = false;

	/**
	 * Cache for field schemas.
	 */
	private static $fields_cache = [];

	/**
	 * Handle include parameter for post types collection.
	 *
	 * Supports two independent include keys:
	 * - jet_engine_custom_fields      => post type meta fields
	 * - jet_engine_meta_box_fields    => meta box fields (current implementation)
	 */
	public static function handle_post_types_collection_include(
		Collection $collection,
		string $post_type,
		array $include,
		array $params
	): Collection {
		$include = is_array( $include ) ? $include : array( $include );

		$instance = new self();

		// 1) Post type meta fields (jet_engine_custom_fields).
		if ( in_array( self::CUSTOM_FIELDS_KEY, $include, true ) ) {
			$meta_field_keys = $instance->get_available_custom_fields( $post_type );

			if ( empty( $meta_field_keys ) ) {
				$collection->push_property(
					self::CUSTOM_FIELDS_KEY,
					new Collection( [] )
				);
			} else {
				$formatted_meta_fields = [];

				foreach ( $meta_field_keys as $field_key ) {
					$formatted_meta_fields[] = [
						'key'   => $field_key,
						'label' => $instance->get_field_label( $field_key, $post_type ),
					];
				}

				$collection->push_property(
					self::CUSTOM_FIELDS_KEY,
					new Collection( $formatted_meta_fields )
				);
			}
		}

		// 2) Meta box fields (jet_engine_meta_box_fields) – current implementation.
		if ( in_array( self::META_BOX_FIELDS_KEY, $include, true ) ) {
			$meta_box_field_keys = $instance->get_available_meta_box_fields( $post_type );

			if ( empty( $meta_box_field_keys ) ) {
				$collection->push_property(
					self::META_BOX_FIELDS_KEY,
					new Collection( [] )
				);
			} else {
				$formatted_meta_box_fields = [];

				foreach ( $meta_box_field_keys as $field_key ) {
					$formatted_meta_box_fields[] = [
						'key'   => $field_key,
						'label' => $instance->get_field_label( $field_key, $post_type ),
					];
				}

				$collection->push_property(
					self::META_BOX_FIELDS_KEY,
					new Collection( $formatted_meta_box_fields )
				);
			}
		}

		return $collection;
	}

	/**
	 * Get all JetEngine post-type meta field keys for a post type.
	 *
	 * This represents JetEngine "Meta Fields" that belong to the post type itself,
	 * not individual meta boxes. These are used for jet_engine_custom_fields.
	 */
	public function get_available_custom_fields( string $post_type ): array {
		if ( isset( self::$fields_cache['meta_fields'][ $post_type ] ) ) {
			return self::$fields_cache['meta_fields'][ $post_type ];
		}

		$this->ensure_jetengine_loaded();

		// Get meta fields for this post type from JetEngine meta boxes component.
		$meta_fields = $this->get_post_type_meta_fields_schemas( $post_type );

		$field_keys = [];

		foreach ( $meta_fields as $field ) {
			if ( ! empty( $field['name'] ) ) {
				$field_keys[] = $field['name'];
			}
		}

		$field_keys = array_values( array_unique( $field_keys ) );

		self::$fields_cache['meta_fields'][ $post_type ] = $field_keys;

		return $field_keys;
	}

	/**
	 * Get all JetEngine meta box field keys for a post type.
	 *
	 * This represents fields coming from JetEngine meta boxes attached to the post type.
	 * Used for jet_engine_meta_box_fields.
	 */
	public function get_available_meta_box_fields( string $post_type ): array {
		if ( isset( self::$fields_cache['meta_box_fields'][ $post_type ] ) ) {
			return self::$fields_cache['meta_box_fields'][ $post_type ];
		}

		$this->ensure_jetengine_loaded();

		$field_keys = [];
		$meta_boxes = $this->get_jetengine_meta_boxes( $post_type );

		foreach ( $meta_boxes as $meta_box ) {
			if ( empty( $meta_box['meta_fields'] ) ) {
				continue;
			}

			foreach ( $meta_box['meta_fields'] as $field ) {
				if ( ! empty( $field['name'] ) ) {
					$field_keys[] = $field['name'];
				}
			}
		}

		$field_keys = array_values( array_unique( $field_keys ) );

		self::$fields_cache['meta_box_fields'][ $post_type ] = $field_keys;

		return $field_keys;
	}

	/**
	 * Ensure JetEngine is ready (important for API routes).
	 */
	private function ensure_jetengine_loaded(): void {
		if ( ! function_exists( 'jet_engine' ) ) {
			return;
		}

		// Don't call init() as it may cause conflicts - JetEngine should already be initialized
		// Just verify it's available
		$jet = jet_engine();
		if ( ! $jet || ! isset( $jet->meta_boxes ) ) {
			return;
		}
	}

	/**
	 * Init integration.
	 */
	public function init() {
		self::register_hooks();
	}

	/**
	 * Register hooks.
	 */
	public static function register_hooks(): void {
		if ( self::$hooks_registered ) {
			return;
		}

		add_filter(
			'lbaic_post_types_collection_include',
			[ __CLASS__, 'handle_post_types_collection_include' ],
			10,
			4
		);

		// Hook into dataset entry custom fields content generation
		add_filter(
			'lbaic_dataset_entry_custom_fields_content',
			[ __CLASS__, 'handle_dataset_entry_custom_fields_content' ],
			10,
			3
		);

		self::$hooks_registered = true;
	}

	/**
	 * Get JetEngine post-type meta field schemas for a post type.
	 *
	 * Uses JetEngine Meta Fields API (not meta boxes) to retrieve fields
	 * registered for the given post type. Additionally filters out any keys
	 * that are also present in meta boxes, so meta fields and meta box fields
	 * never overlap.
	 */
	private function get_post_type_meta_fields_schemas( string $post_type ): array {
		if ( ! function_exists( 'jet_engine' ) ) {
			return [];
		}

		$meta_fields = [];

		try {
			$jet = jet_engine();

			if ( ! $jet ) {
				return [];
			}

			// Prefer dedicated Meta Fields component if available.
			if ( isset( $jet->meta ) ) {
				// Newer JetEngine versions.
				if ( method_exists( $jet->meta, 'get_fields_for_context' ) ) {
					$meta_fields = $jet->meta->get_fields_for_context( 'post_type', $post_type );
				} elseif ( method_exists( $jet->meta, 'get_meta_fields_for_object' ) ) {
					$meta_fields = $jet->meta->get_meta_fields_for_object( $post_type );
				}
			}

			// Legacy / safety fallback: some setups might still expose meta fields via meta_boxes.
			if ( empty( $meta_fields ) && isset( $jet->meta_boxes ) ) {
				if ( method_exists( $jet->meta_boxes, 'get_fields_for_context' ) ) {
					$meta_fields = $jet->meta_boxes->get_fields_for_context( 'post_type', $post_type );
				} elseif ( method_exists( $jet->meta_boxes, 'get_meta_fields_for_object' ) ) {
					$meta_fields = $jet->meta_boxes->get_meta_fields_for_object( $post_type );
				}
			}
		} catch ( Exception $e ) {
			$meta_fields = [];
		}

		if ( ! is_array( $meta_fields ) ) {
			$meta_fields = [];
		}

		// At this point $meta_fields may still include fields coming from meta boxes.
		// To guarantee a clean separation, we subtract any keys that are also present
		// in get_available_meta_box_fields().
		$meta_box_field_keys = $this->get_available_meta_box_fields( $post_type );

		if ( ! empty( $meta_box_field_keys ) ) {
			$meta_fields = array_values(
				array_filter(
					$meta_fields,
					static function ( $field ) use ( $meta_box_field_keys ) {
						$name = isset( $field['name'] ) ? (string) $field['name'] : '';

						return $name && ! in_array( $name, $meta_box_field_keys, true );
					}
				)
			);
		}

		return $meta_fields;
	}

	/**
	 * Get JetEngine meta box configs for a post type.
	 *
	 * Filters $jet->meta_boxes directly using PHP to get all meta boxes
	 * that apply to the given post type. Returns field definitions only,
	 * not actual field values for specific posts.
	 */
	private function get_jetengine_meta_boxes( string $post_type ): array {
		$meta_boxes = [];

		if ( ! function_exists( 'jet_engine' ) ) {
			return $meta_boxes;
		}

		try {
			$jet = jet_engine();

			if ( ! $jet || ! isset( $jet->meta_boxes ) || ! isset( $jet->meta_boxes->data ) ) {
				return $meta_boxes;
			}

			// Check if get_raw method exists
			if ( ! method_exists( $jet->meta_boxes->data, 'get_raw' ) ) {
				return $meta_boxes;
			}

			// Get all meta boxes using the data->get_raw() method
			$all_meta_boxes = $jet->meta_boxes->data->get_raw();

			if ( empty( $all_meta_boxes ) || ! is_array( $all_meta_boxes ) ) {
				return $meta_boxes;
			}

			// Filter meta boxes that apply to this post type
			foreach ( $all_meta_boxes as $meta_box ) {
				if ( ! is_array( $meta_box ) || empty( $meta_box['args'] ) ) {
					continue;
				}

				$args = $meta_box['args'];

				// Check if this meta box is for posts
				$object_type = $args['object_type'] ?? 'post';
				if ( $object_type !== 'post' ) {
					continue;
				}

				// Check if this meta box applies to the given post type
				$allowed_post_types = $args['allowed_post_type'] ?? array();
				if ( ! is_array( $allowed_post_types ) ) {
					$allowed_post_types = array( $allowed_post_types );
				}

				if ( ! in_array( $post_type, $allowed_post_types, true ) ) {
					continue;
				}

				// Unserialize meta_fields if needed
				$meta_fields = $meta_box['meta_fields'] ?? array();
				if ( is_string( $meta_fields ) ) {
					$meta_fields = maybe_unserialize( $meta_fields );
				}

				// Add this meta box with its fields
				$meta_boxes[] = array(
					'id'          => $meta_box['id'] ?? '',
					'args'        => $args,
					'meta_fields' => is_array( $meta_fields ) ? $meta_fields : array(),
				);
			}
		} catch ( Exception $e ) {
			// JetEngine not available or error occurred - return empty array
			return $meta_boxes;
		}

		return $meta_boxes;
	}

	/**
	 * Get field label for a given key and post type.
	 *
	 * Tries post-type meta fields first, then meta box fields, then falls back
	 * to the raw field key.
	 */
	public function get_field_label( string $field_key, string $post_type ): string {
		// 1) Look in post-type meta fields.
		$meta_fields = $this->get_post_type_meta_fields_schemas( $post_type );

		foreach ( $meta_fields as $field ) {
			if ( isset( $field['name'] ) && $field['name'] === $field_key ) {
				return $field['title'] ?? $field_key;
			}
		}

		// 2) Look in meta box fields.
		$meta_boxes = $this->get_jetengine_meta_boxes( $post_type );

		foreach ( $meta_boxes as $meta_box ) {
			if ( empty( $meta_box['meta_fields'] ) ) {
				continue;
			}

			foreach ( $meta_box['meta_fields'] as $field ) {
				if ( isset( $field['name'] ) && $field['name'] === $field_key ) {
					return $field['title'] ?? $field_key;
				}
			}
		}

		return $field_key;
	}

	/**
	 * Handle dataset entry custom fields content filter.
	 *
	 * Checks for jet_engine_custom_fields in dataset meta and adds formatted content.
	 *
	 * @param  string  $content  Existing content.
	 * @param  WP_Post  $post  WordPress post object.
	 * @param  Dataset|null  $dataset  Dataset instance.
	 *
	 * @return string Additional custom fields content.
	 */
	public static function handle_dataset_entry_custom_fields_content(
		string $content,
		WP_Post $post,
		$dataset
	): string {
		if ( ! $dataset instanceof Dataset ) {
			return $content;
		}

		$instance = new self();

		$content_sections = [];

		// 1) Post-type meta fields (jet_engine_custom_fields).
		$meta_fields_keys = $dataset->get_meta_value( self::CUSTOM_FIELDS_KEY );
		if ( ! empty( $meta_fields_keys ) ) {
			if ( is_string( $meta_fields_keys ) ) {
				$meta_fields_keys = json_decode( $meta_fields_keys, true );
			}

			if ( is_array( $meta_fields_keys ) ) {
				$meta_fields_keys = array_filter(
					$meta_fields_keys,
					static function ( $field_key ) {
						return is_string( $field_key ) && ! empty( trim( $field_key ) );
					}
				);

				if ( ! empty( $meta_fields_keys ) ) {
					$meta_fields_content = $instance->get_post_custom_fields_content(
						$post,
						array_values( $meta_fields_keys )
					);

					if ( ! empty( $meta_fields_content ) ) {
						$content_sections[] = $meta_fields_content;
					}
				}
			}
		}

		// 2) Meta box fields (jet_engine_meta_box_fields).
		$meta_box_fields_keys = $dataset->get_meta_value( self::META_BOX_FIELDS_KEY );
		if ( ! empty( $meta_box_fields_keys ) ) {
			if ( is_string( $meta_box_fields_keys ) ) {
				$meta_box_fields_keys = json_decode( $meta_box_fields_keys, true );
			}

			if ( is_array( $meta_box_fields_keys ) ) {
				$meta_box_fields_keys = array_filter(
					$meta_box_fields_keys,
					static function ( $field_key ) {
						return is_string( $field_key ) && ! empty( trim( $field_key ) );
					}
				);

				if ( ! empty( $meta_box_fields_keys ) ) {
					$meta_box_fields_content = $instance->get_post_custom_fields_content(
						$post,
						array_values( $meta_box_fields_keys )
					);

					if ( ! empty( $meta_box_fields_content ) ) {
						$content_sections[] = $meta_box_fields_content;
					}
				}
			}
		}

		$custom_fields_content = implode( "\n\n", array_filter( $content_sections ) );

		// Append to existing content with clear separation (plain text)
		if ( ! empty( $custom_fields_content ) ) {
			if ( ! empty( $content ) ) {
				$content .= "\n\n---\n\n";
			}
			$content .= $custom_fields_content;
		}

		return $content;
	}

	/**
	 * Extract JetEngine content from post.
	 */
	public function get_post_custom_fields_content(
		WP_Post $post,
		array $field_keys = []
	): string {
		if ( empty( $field_keys ) ) {
			$field_keys = $this->get_available_custom_fields( $post->post_type );
		}

		if ( empty( $field_keys ) ) {
			return '';
		}

		$content_parts = [];

		foreach ( $field_keys as $field_key ) {
			$value = $this->get_jetengine_field_value(
				$post->ID,
				$field_key
			);

			if ( $value === '' || $value === null || ( is_array( $value ) && empty( $value ) ) ) {
				continue;
			}

			$field_label = $this->get_field_label(
				$field_key,
				$post->post_type
			);

			// Ensure label is never empty - use field_key as fallback
			if ( empty( $field_label ) || $field_label === $field_key ) {
				// Try to create a readable label from field_key
				$field_label = $this->format_field_key_as_label( $field_key );
			}

			$formatted_value = $this->format_field_value( $value );

			// Only add if we have a value after formatting
			if ( ! empty( trim( $formatted_value ) ) ) {
				// Return plain text for indexing (will be converted to HTML for source_content separately)
				$field_content = sprintf(
					'%s: %s',
					$field_label,
					$formatted_value
				);
				$content_parts[] = $field_content;
			}
		}

		// Join fields with double newlines for clear separation (plain text)
		return implode( "\n\n", $content_parts );
	}

	/**
	 * Get field value safely.
	 */
	private function get_jetengine_field_value( int $post_id, string $field_key ) {
		$this->ensure_jetengine_loaded();

		/**
		 * Try JetEngine API first.
		 */
		if ( function_exists( 'jet_engine' ) ) {
			$jet = jet_engine();

			if ( isset( $jet->meta_boxes )
			     && method_exists( $jet->meta_boxes, 'get_field_value' )
			) {
				return $jet->meta_boxes->get_field_value(
					$field_key,
					$post_id
				);
			}
		}

		/**
		 * Fallback to WP meta.
		 */
		return get_post_meta( $post_id, $field_key, true );
	}

	/**
	 * Format field key as readable label.
	 *
	 * Converts field_key like "review-product-title" to "Review Product Title".
	 * Removes redundant prefixes for better RAG performance.
	 *
	 * @param  string  $field_key  Field key.
	 *
	 * @return string Formatted label.
	 */
	private function format_field_key_as_label( string $field_key ): string {
		// Replace hyphens and underscores with spaces
		$label = str_replace( [ '-', '_' ], ' ', $field_key );

		// Remove redundant "review product" prefix for cleaner RAG output
		$label = preg_replace( '/^review\s+product\s+/i', '', $label );

		// Capitalize first letter of each word
		$label = ucwords( $label );

		return $label;
	}

	/**
	 * Format value.
	 *
	 * Strips HTML and formats arrays/objects for clean text output.
	 */
	private function format_field_value( $value ): string {
		if ( is_array( $value ) ) {
			return $this->format_array_value( $value );
		}

		if ( is_object( $value ) ) {
			// Convert object to array first
			$value = (array) $value;
			return $this->format_array_value( $value );
		}

		$value = (string) $value;

		// Check if value contains HTML - if so, try to extract list items first
		if ( strpos( $value, '<li>' ) !== false || strpos( $value, '<!-- wp:list-item -->' ) !== false ) {
			$value = $this->extract_list_items_from_html( $value );
		}

		// Strip HTML tags and decode HTML entities
		$value = wp_strip_all_tags( $value, true );
		// Remove HTML comments
		$value = preg_replace( '/<!--.*?-->/s', '', $value );
		// Remove trailing backslashes (common escaping issue)
		$value = rtrim( $value, '\\' );
		// Clean up extra whitespace
		$value = preg_replace( '/\s+/', ' ', $value );
		$value = trim( $value );

		return $value;
	}

	/**
	 * Extract list items from HTML and format as clean text.
	 *
	 * Handles both HTML list items and WordPress block comments.
	 */
	private function extract_list_items_from_html( string $html ): string {
		$items = [];

		// Extract WordPress list items (<!-- wp:list-item -->)
		if ( preg_match_all( '/<!-- wp:list-item -->\s*<li>(.*?)<\/li>/s', $html, $wp_matches ) ) {
			foreach ( $wp_matches[1] as $item_content ) {
				$clean_item = wp_strip_all_tags( $item_content, true );
				$clean_item = preg_replace( '/<!--.*?-->/s', '', $clean_item );
				$clean_item = preg_replace( '/\s+/', ' ', $clean_item );
				$clean_item = trim( $clean_item );
				if ( ! empty( $clean_item ) ) {
					$items[] = '- ' . $clean_item;
				}
			}
		}

		// Extract regular HTML list items
		if ( empty( $items ) && preg_match_all( '/<li[^>]*>(.*?)<\/li>/s', $html, $html_matches ) ) {
			foreach ( $html_matches[1] as $item_content ) {
				$clean_item = wp_strip_all_tags( $item_content, true );
				$clean_item = preg_replace( '/<!--.*?-->/s', '', $clean_item );
				$clean_item = preg_replace( '/\s+/', ' ', $clean_item );
				$clean_item = trim( $clean_item );
				if ( ! empty( $clean_item ) ) {
					$items[] = '- ' . $clean_item;
				}
			}
		}

		// If we extracted items, return formatted list
		if ( ! empty( $items ) ) {
			return implode( "\n", $items );
		}

		// Otherwise return original HTML for further processing
		return $html;
	}

	/**
	 * Format array value for clean text output.
	 *
	 * Handles nested arrays, repeater fields, and complex structures.
	 * Removes item-0, item-1 keys and formats with beautiful separation.
	 */
	private function format_array_value( array $value ): string {
		// Check if this is a simple indexed array (like a list)
		$keys = array_keys( $value );
		$is_indexed = $keys === range( 0, count( $value ) - 1 );

		// Check if keys are like "item-0", "item-1" (repeater format)
		$is_repeater_format = false;
		if ( ! $is_indexed && count( $value ) > 0 ) {
			$is_repeater_format = preg_match( '/^item-\d+$/', (string) $keys[0] ) === 1;
		}

		if ( $is_indexed || $is_repeater_format ) {
			// Simple list or repeater format - format as structured items (plain text)
			$formatted = [];
			$index = 1;

			foreach ( $value as $item ) {
				if ( is_array( $item ) ) {
					// Nested array (repeater item) - format as structured item with index
					$nested = $this->format_nested_array_item( $item, $index );
					if ( ! empty( trim( $nested ) ) ) {
						$formatted[] = $nested;
						$index++;
					}
				} else {
					$formatted_value = wp_strip_all_tags( (string) $item, true );
					$formatted_value = preg_replace( '/<!--.*?-->/s', '', $formatted_value );
					$formatted_value = preg_replace( '/\s+/', ' ', $formatted_value );
					$formatted_value = trim( $formatted_value );
					if ( ! empty( $formatted_value ) ) {
						$formatted[] = sprintf( '%d. %s', $index, $formatted_value );
						$index++;
					}
				}
			}

			// Join with double newlines for clear separation (plain text)
			return implode( "\n\n", $formatted );
		}

		// Associative array - format as key-value pairs (plain text)
		$formatted = [];
		foreach ( $value as $key => $item ) {
			// Skip numeric keys that are just indices
			if ( is_numeric( $key ) && ! $is_indexed ) {
				continue;
			}

			if ( is_array( $item ) ) {
				$nested = $this->format_array_value( $item );
				if ( ! empty( trim( $nested ) ) ) {
					// For nested arrays, strip HTML tags and format as key: value
					$nested_text = wp_strip_all_tags( $nested, true );
					$nested_text = preg_replace( '/\s+/', ' ', $nested_text );
					$nested_text = trim( $nested_text );
					if ( ! empty( $nested_text ) ) {
						$formatted[] = sprintf(
							'%s: %s',
							$this->format_field_key_as_label( (string) $key ),
							$nested_text
						);
					}
				}
			} else {
				$formatted_value = wp_strip_all_tags( (string) $item, true );
				$formatted_value = preg_replace( '/<!--.*?-->/s', '', $formatted_value );
				$formatted_value = preg_replace( '/\s+/', ' ', $formatted_value );
				$formatted_value = trim( $formatted_value );
				if ( ! empty( $formatted_value ) ) {
					$formatted[] = sprintf(
						'%s: %s',
						$this->format_field_key_as_label( (string) $key ),
						$formatted_value
					);
				}
			}
		}

		// Join with double newlines for clear separation (plain text)
		return implode( "\n\n", $formatted );
	}

	/**
	 * Format nested array item (for repeater fields).
	 *
	 * Formats items like repeater field entries in a clean, readable way.
	 * Generic formatting that works with any JetEngine field structure.
	 * Adds index for proper knowledge injection.
	 *
	 * @param  array  $item  Nested array item.
	 * @param  int  $index  Optional index number for the item.
	 *
	 * @return string Formatted item (plain text, will be wrapped in <p> by caller).
	 */
	private function format_nested_array_item( array $item, int $index = 0 ): string {
		$parts = [];

		foreach ( $item as $key => $value ) {
			// Skip empty values
			if ( $value === '' || $value === null ) {
				continue;
			}

			if ( is_array( $value ) ) {
				$nested = $this->format_array_value( $value );
				if ( ! empty( trim( $nested ) ) ) {
					// For nested arrays, strip HTML tags and format as key: value
					$nested_text = wp_strip_all_tags( $nested, true );
					$nested_text = preg_replace( '/\s+/', ' ', $nested_text );
					$nested_text = trim( $nested_text );
					if ( ! empty( $nested_text ) ) {
						$parts[] = sprintf(
							'%s: %s',
							$this->format_field_key_as_label( (string) $key ),
							$nested_text
						);
					}
				}
			} else {
				$formatted_value = wp_strip_all_tags( (string) $value, true );
				$formatted_value = preg_replace( '/<!--.*?-->/s', '', $formatted_value );
				$formatted_value = preg_replace( '/\s+/', ' ', $formatted_value );
				$formatted_value = trim( $formatted_value );
				if ( ! empty( $formatted_value ) ) {
					$parts[] = sprintf(
						'%s: %s',
						$this->format_field_key_as_label( (string) $key ),
						$formatted_value
					);
				}
			}
		}

		$formatted_item = implode( ' | ', $parts );

		// Add index prefix if provided for proper knowledge injection
		if ( $index > 0 && ! empty( $formatted_item ) ) {
			return sprintf( '%d. %s', $index, $formatted_item );
		}

		return $formatted_item;
	}

	/**
	 * Indent text for nested structures.
	 *
	 * Adds proper indentation to nested content for better readability.
	 *
	 * @param  string  $text  Text to indent.
	 * @param  int  $spaces  Number of spaces to indent (default 2).
	 *
	 * @return string Indented text.
	 */
	private function indent_text( string $text, int $spaces = 2 ): string {
		$indent = str_repeat( ' ', $spaces );
		$lines = explode( "\n", $text );
		$indented_lines = array_map( function( $line ) use ( $indent ) {
			return $indent . $line;
		}, $lines );
		return implode( "\n", $indented_lines );
	}
}
