<?php
/**
 * Content Indexer class for managing content indexing
 *
 * This class handles content indexing for various sources including posts,
 * pages, and PDFs, with support for different content types and formats.
 *
 * @package Askany
 * @since 1.0.0
 */

namespace Askany;

use ask\askany\wpnts_nts_fs;

/**
 * Content Indexer class for managing content indexing
 *
 * @package Askany
 * @since 1.0.0
 */
class ContentIndexer {
	/**
	 * Database instance for content management.
	 *
	 * @var Database
	 */
	private $database;
	/**
	 * Batch size for processing content.
	 *
	 * @var int
	 */
	private $batch_size = 50;

	/**
	 * Constructor for ContentIndexer.
	 *
	 * Initializes the database instance and sets up hooks.
	 *
	 * @param Database $database Database instance for content management.
	 */
	public function __construct( $database ) {
		$this->database = $database;
	}

	/**
	 * Initialize hooks for content indexing.
	 *
	 * Sets up actions for reindexing content, saving posts, and deleting posts.
	 *
	 * @return void
	 */
	public function init() {
		add_action('askany_reindex_content', array( $this, 'reindex_all_content' ));
		add_action('save_post', array( $this, 'index_post' ), 10, 3);
		add_action('delete_post', array( $this, 'delete_post_index' ));
		add_action('wp_insert_comment', array( $this, 'index_comment' ), 10, 2);
		add_action('delete_comment', array( $this, 'delete_comment_index' ));
		add_action('woocommerce_new_product', array( $this, 'index_product' ));
		add_action('woocommerce_update_product', array( $this, 'index_product' ));
		add_action('woocommerce_delete_product', array( $this, 'delete_product_index' ));
	}

	/**
	 * Reindex all content.
	 *
	 * This method is called to reindex all content types including posts, comments,
	 * and products. It clears the existing index and rebuilds it.
	 *
	 * @return bool True on success, false on failure.
	 */
	public function index_content() {
		return $this->reindex_all_content();
	}

	/**
	 * Reindex all content types.
	 *
	 * This method clears the existing index and rebuilds it for all content types.
	 *
	 * @return bool True on success, false on failure.
	 */
	public function reindex_all_content() {
		global $wpdb;
		$tables = $this->database->get_tables();
		$content_index_table = $tables['content_index'];

		// Clear existing index.
		$wpdb->query("TRUNCATE TABLE $content_index_table");

		// Index posts and pages.
		$this->index_posts();
		$this->index_pages();
		$this->index_template_pages();
		$this->index_docs_pages();

		// Index comments.
		$this->index_comments();

		// Index products and related content if WooCommerce is active.
		if ( class_exists('WooCommerce') ) {
			$this->index_products();
			$this->index_product_categories();
			$this->index_product_tags();
			$this->index_store_configuration();
		}

		// Index FAQ data for better AI understanding
		$this->index_faqs();
		
		// Index PDF content
		$this->index_pdfs();
		
		// Index external sources
		$this->index_external_sources();

		// Index additional website content.
		$this->index_custom_fields();
		$this->index_menus();
		$this->index_widgets();

		return true;
	}

	/**
	 * Get comprehensive content statistics.
	 *
	 * This method retrieves detailed statistics about the indexed content including
	 * counts for all content types, total content size, and indexing status.
	 *
	 * @return array Array containing detailed content statistics.
	 */
	public function get_content_stats() {
		global $wpdb;
		$tables = $this->database->get_tables();
		$content_index_table = $tables['content_index'];

		// Get individual content type counts
		$stats = array(
			'posts' => (int) $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM $content_index_table WHERE object_type = %s", 'post')),
			'pages' => (int) $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM $content_index_table WHERE object_type = %s", 'page')),
			'template_pages' => (int) $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM $content_index_table WHERE object_type = %s", 'template_page')),
			'docs' => (int) $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM $content_index_table WHERE object_type = %s", 'docs')),
			'comments' => (int) $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM $content_index_table WHERE object_type = %s", 'comment')),
			'products' => (int) $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM $content_index_table WHERE object_type = %s", 'product')),
			'product_categories' => (int) $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM $content_index_table WHERE object_type = %s", 'product_category')),
			'product_tags' => (int) $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM $content_index_table WHERE object_type = %s", 'product_tag')),
			'custom_fields' => (int) $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM $content_index_table WHERE object_type = %s", 'custom_field')),
			'menus' => (int) $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM $content_index_table WHERE object_type = %s", 'menu')),
			'widgets' => (int) $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM $content_index_table WHERE object_type = %s", 'widget')),
			'store_config' => (int) $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM $content_index_table WHERE object_type = %s", 'store_config')),
			// FAQ, Q&A, PDF, and External Sources
			'faqs' => (int) $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM $content_index_table WHERE object_type = %s", 'faq')),
			'faq_collections' => (int) $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM $content_index_table WHERE object_type = %s", 'faq_collection')),
			'qa_pairs' => (int) $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM $content_index_table WHERE object_type = %s", 'qa')),
			'qa_collections' => (int) $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM $content_index_table WHERE object_type = %s", 'qa_collection')),
			'pdfs' => (int) $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM $content_index_table WHERE object_type = %s", 'pdf')),
			'pdf_collections' => (int) $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM $content_index_table WHERE object_type = %s", 'pdf_collection')),
			'external_sources' => (int) $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM $content_index_table WHERE object_type = %s", 'external_source')),
			'external_collections' => (int) $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM $content_index_table WHERE object_type = %s", 'external_collection')),
		);

		// Calculate totals and additional metrics
		$stats['total_indexed'] = array_sum($stats);
		
		// Get content size statistics
		$stats['total_content_size'] = (int) $wpdb->get_var("SELECT SUM(LENGTH(content)) FROM $content_index_table");
		$stats['average_content_length'] = $stats['total_indexed'] > 0 ? 
			round($stats['total_content_size'] / $stats['total_indexed']) : 0;

		// Get last update information
		$stats['last_updated'] = $wpdb->get_var("SELECT MAX(updated_at) FROM $content_index_table");
		
		// Get content type breakdown with percentages
		$stats['content_breakdown'] = array();
		$content_types = array('posts', 'pages', 'template_pages', 'docs', 'comments', 'products', 'product_categories', 'product_tags', 'custom_fields', 'menus', 'widgets', 'store_config', 'faqs', 'faq_collections', 'qa_pairs', 'qa_collections', 'pdfs', 'pdf_collections', 'external_sources', 'external_collections');
		
		foreach ( $content_types as $type ) {
			$stats['content_breakdown'][$type] = array(
				'count' => $stats[$type],
				'percentage' => $stats['total_indexed'] > 0 ? 
					round(($stats[$type] / $stats['total_indexed']) * 100, 2) : 0,
			);
		}

		// Get WordPress content availability for comparison
		$stats['wordpress_totals'] = $this->get_wordpress_content_totals();
		
		// Get FAQ, PDF, and External Sources totals from their respective tables
		$stats['source_totals'] = $this->get_source_content_totals();
		
		// Calculate indexing coverage
		$stats['indexing_coverage'] = array();
		if ( $stats['wordpress_totals']['posts'] > 0 ) {
			$stats['indexing_coverage']['posts'] = round(($stats['posts'] / $stats['wordpress_totals']['posts']) * 100, 2);
		}
		if ( $stats['wordpress_totals']['pages'] > 0 ) {
			$stats['indexing_coverage']['pages'] = round(($stats['pages'] / $stats['wordpress_totals']['pages']) * 100, 2);
		}
		if ( $stats['wordpress_totals']['comments'] > 0 ) {
			$stats['indexing_coverage']['comments'] = round(($stats['comments'] / $stats['wordpress_totals']['comments']) * 100, 2);
		}
		if ( class_exists('WooCommerce') && $stats['wordpress_totals']['products'] > 0 ) {
			$stats['indexing_coverage']['products'] = round(($stats['products'] / $stats['wordpress_totals']['products']) * 100, 2);
		}
		
		// Calculate coverage for new content types
		if ( $stats['source_totals']['faqs'] > 0 ) {
			$stats['indexing_coverage']['faqs'] = round(($stats['faqs'] / $stats['source_totals']['faqs']) * 100, 2);
		}
		if ( $stats['source_totals']['qa_pairs'] > 0 ) {
			$stats['indexing_coverage']['qa_pairs'] = round(($stats['qa_pairs'] / $stats['source_totals']['qa_pairs']) * 100, 2);
		}
		if ( $stats['source_totals']['pdfs'] > 0 ) {
			$stats['indexing_coverage']['pdfs'] = round(($stats['pdfs'] / $stats['source_totals']['pdfs']) * 100, 2);
		}
		if ( $stats['source_totals']['external_sources'] > 0 ) {
			$stats['indexing_coverage']['external_sources'] = round(($stats['external_sources'] / $stats['source_totals']['external_sources']) * 100, 2);
		}

		// Add indexing health status
		$stats['indexing_health'] = $this->calculate_indexing_health($stats);

		return $stats;
	}

	/**
	 * Get WordPress content totals for comparison.
	 *
	 * @return array Array containing WordPress content totals.
	 */
	private function get_wordpress_content_totals() {
		$totals = array(
			'posts' => (int) wp_count_posts('post')->publish,
			'pages' => (int) wp_count_posts('page')->publish,
			'comments' => (int) wp_count_comments()->approved,
		);

		// Add WooCommerce product count if available
		if ( class_exists('WooCommerce') ) {
			$totals['products'] = (int) wp_count_posts('product')->publish;
			
			// Get product categories and tags count
			$totals['product_categories'] = (int) wp_count_terms(array(
				'taxonomy' => 'product_cat',
				'hide_empty' => false,
			));
			
			$totals['product_tags'] = (int) wp_count_terms(array(
				'taxonomy' => 'product_tag',
				'hide_empty' => false,
			));
		}

		// Get menu count
		$totals['menus'] = count(wp_get_nav_menus());

		// Get template count
		$totals['template_pages'] = count(wp_get_theme()->get_page_templates());

		// Get documentation post types count
		$doc_post_types = array('docs', 'documentation', 'knowledge_base', 'faq');
		$totals['docs'] = 0;
		foreach ( $doc_post_types as $post_type ) {
			if ( post_type_exists($post_type) ) {
				$count = wp_count_posts($post_type);
				$totals['docs'] += isset($count->publish) ? (int) $count->publish : 0;
			}
		}

		// Estimate custom fields count (this is approximate)
		global $wpdb;
		$totals['custom_fields'] = (int) $wpdb->get_var("
			SELECT COUNT(DISTINCT CONCAT(post_id, '_', meta_key)) 
			FROM {$wpdb->postmeta} 
			WHERE meta_key NOT LIKE '\_%' 
			AND meta_value != '' 
			AND LENGTH(meta_value) > 10
		");

		// Estimate widgets count
		$sidebars = wp_get_sidebars_widgets();
		$widget_count = 0;
		foreach ( $sidebars as $sidebar_id => $widgets ) {
			if ( is_array($widgets) ) {
				$widget_count += count($widgets);
			}
		}
		$totals['widgets'] = $widget_count;

		return $totals;
	}
	
	/**
	 * Get source content totals (FAQs, PDFs, External Sources) for comparison.
	 *
	 * This method retrieves the total counts of FAQs, PDFs, and External Sources
	 * from their respective database tables for coverage calculation.
	 *
	 * @return array Array containing source content totals.
	 */
	private function get_source_content_totals() {
		global $wpdb;
		$tables = $this->database->get_tables();
		
		$totals = array(
			'faqs' => 0,
			'qa_pairs' => 0,
			'pdfs' => 0,
			'external_sources' => 0,
		);
		
		// Get FAQ totals (home FAQs)
		$faqs_table = $tables['home_faqs'];
		if ( $wpdb->get_var("SHOW TABLES LIKE '$faqs_table'") === $faqs_table ) {
			$totals['faqs'] = (int) $wpdb->get_var("SELECT COUNT(*) FROM $faqs_table");
		}
		
		// Get Q&A pairs totals
		$qa_table = $tables['qa_pairs'];
		if ( $wpdb->get_var("SHOW TABLES LIKE '$qa_table'") === $qa_table ) {
			$totals['qa_pairs'] = (int) $wpdb->get_var("SELECT COUNT(*) FROM $qa_table WHERE status = 'active'");
		}
		
		// Get PDF totals
		$pdf_table = $tables['pdf_index'];
		if ( $wpdb->get_var("SHOW TABLES LIKE '$pdf_table'") === $pdf_table ) {
			$totals['pdfs'] = (int) $wpdb->get_var("SELECT COUNT(*) FROM $pdf_table");
		}
		
		// Get External Sources totals
		$external_table = $tables['external_sources'];
		if ( $wpdb->get_var("SHOW TABLES LIKE '$external_table'") === $external_table ) {
			$totals['external_sources'] = (int) $wpdb->get_var("SELECT COUNT(*) FROM $external_table");
		}
		
		return $totals;
	}

	/**
	 * Calculate indexing health status.
	 *
	 * @param array $stats Current statistics.
	 * @return array Health status information.
	 */
	private function calculate_indexing_health( $stats ) {
		$health = array(
			'status' => 'good',
			'score' => 100,
			'issues' => array(),
			'recommendations' => array(),
		);

		// Check if there's any content indexed
		if ( $stats['total_indexed'] === 0 ) {
			$health['status'] = 'critical';
			$health['score'] = 0;
			$health['issues'][] = 'No content has been indexed yet';
			$health['recommendations'][] = 'Run a full content reindex to populate the search index';
			return $health;
		}

		// Check coverage for main content types
		$coverage_issues = 0;
		if ( isset($stats['indexing_coverage']['posts']) && $stats['indexing_coverage']['posts'] < 90 ) {
			$coverage_issues++;
			$health['issues'][] = 'Post indexing coverage is below 90%';
		}
		
		if ( isset($stats['indexing_coverage']['pages']) && $stats['indexing_coverage']['pages'] < 90 ) {
			$coverage_issues++;
			$health['issues'][] = 'Page indexing coverage is below 90%';
		}

		if ( isset($stats['indexing_coverage']['products']) && $stats['indexing_coverage']['products'] < 90 ) {
			$coverage_issues++;
			$health['issues'][] = 'Product indexing coverage is below 90%';
		}

		// Check if index is stale (older than 7 days)
		if ( $stats['last_updated'] ) {
			$last_update = strtotime($stats['last_updated']);
			$days_old = (time() - $last_update) / (24 * 60 * 60);
			
			if ( $days_old > 7 ) {
				$coverage_issues++;
				$health['issues'][] = 'Content index is more than 7 days old';
				$health['recommendations'][] = 'Consider running a content reindex to ensure freshness';
			}
		}

		// Calculate health score based on issues
		if ( $coverage_issues > 0 ) {
			$health['score'] = max(0, 100 - ($coverage_issues * 20));
			
			if ( $health['score'] < 60 ) {
				$health['status'] = 'critical';
			} elseif ( $health['score'] < 80 ) {
				$health['status'] = 'warning';
			}
		}

		// Add general recommendations
		if ( $stats['total_indexed'] < 100 ) {
			$health['recommendations'][] = 'Consider adding more content to improve AI response quality';
		}

		if ( empty($health['recommendations']) ) {
			$health['recommendations'][] = 'Content indexing is working well. Monitor regularly for optimal performance.';
		}

		return $health;
	}

	/**
	 * Index posts in batches.
	 *
	 * This method retrieves all posts and indexes them in batches to improve performance.
	 *
	 * @return void
	 */
	private function index_posts() {
		$post_types = get_post_types(array( 'public' => true ));
		unset($post_types['attachment']);

		$args = array(
			'post_type' => $post_types,
			'post_status' => 'publish',
			'posts_per_page' => -1,
			'fields' => 'ids',
		);

		$post_ids = get_posts($args);
		$total_posts = count($post_ids);

		for ( $i = 0; $i < $total_posts; $i += $this->batch_size ) {
			$batch = array_slice($post_ids, $i, $this->batch_size);
			foreach ( $batch as $post_id ) {
				$this->index_post($post_id);
			}
		}
	}

	/**
	 * Index comments in batches.
	 *
	 * This method retrieves all approved comments and indexes them in batches to improve performance.
	 *
	 * @return void
	 */
	private function index_comments() {
		$args = array(
			'status' => 'approve',
			'number' => -1,
			'fields' => 'ids',
		);

		$comment_ids = get_comments($args);
		$total_comments = count($comment_ids);

		for ( $i = 0; $i < $total_comments; $i += $this->batch_size ) {
			$batch = array_slice($comment_ids, $i, $this->batch_size);
			foreach ( $batch as $comment_id ) {
				$this->index_comment($comment_id);
			}
		}
	}

	/**
	 * Index products in batches.
	 *
	 * This method retrieves all published products and indexes them in batches to improve performance.
	 *
	 * @return void
	 */
	private function index_products() {
		$args = array(
			'post_type' => 'product',
			'post_status' => 'publish',
			'posts_per_page' => -1,
			'fields' => 'ids',
		);

		$product_ids = get_posts($args);
		$total_products = count($product_ids);

		for ( $i = 0; $i < $total_products; $i += $this->batch_size ) {
			$batch = array_slice($product_ids, $i, $this->batch_size);
			foreach ( $batch as $product_id ) {
				$this->index_product($product_id);
			}
		}
	}

	/**
	 * Index a single post.
	 *
	 * This method indexes a single post by its ID. It prepares the content and stores it in the database.
	 *
	 * @param int          $post_id Post ID to index.
	 * @param WP_Post|null $post Optional. Post object. Default null.
	 * @param bool|null    $update Optional. Whether this is an update. Default null.
	 * @return void
	 */
	public function index_post( $post_id, $post = null, $update = null ) {
		if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) {
			return;
		}

		if ( ! $post ) {
			$post = get_post($post_id);
		}

		if ( ! $post || $post->post_status !== 'publish' ) {
			return;
		}

		// Store the post object before modifying global
		$current_post = $post;
		
		// Set global post for Elementor extraction
		global $post;
		$old_global_post = $post;
		$post = get_post($post_id);
		
		// Verify post was retrieved successfully
		if ( ! $post ) {
			$post = $old_global_post;
			return;
		}
		
		// Combine title, content, and excerpt
		$content_parts = array(
			'Title: ' . $post->post_title,
			'Content: ' . $post->post_content,
		);
		
		if ( ! empty( $post->post_excerpt ) ) {
			$content_parts[] = 'Excerpt: ' . $post->post_excerpt;
		}
		
		// Add post metadata for better AI context
		$author = get_the_author_meta('display_name', $post->post_author);
		if ( $author ) {
			$content_parts[] = 'Author: ' . $author;
		}
		
		$content_parts[] = 'Published: ' . get_the_date('F j, Y', $post_id);
		$content_parts[] = 'Modified: ' . get_the_modified_date('F j, Y', $post_id);
		$content_parts[] = 'Post Type: ' . $post->post_type;
		
		// Add categories with descriptions
		$categories = get_the_category($post_id);
		if ( ! empty($categories) ) {
			$cat_info = array();
			foreach ( $categories as $category ) {
				$cat_text = 'Category: ' . $category->name;
				if ( ! empty($category->description) ) {
					$cat_text .= ' - ' . $category->description;
				}
				$cat_info[] = $cat_text;
			}
			$content_parts = array_merge($content_parts, $cat_info);
		}
		
		// Add tags
		$tags = get_the_tags($post_id);
		if ( ! empty($tags) ) {
			$tag_names = array_map(function($tag) { return $tag->name; }, $tags);
			$content_parts[] = 'Tags: ' . implode(', ', $tag_names);
		}
		
		// Add custom taxonomies
		$taxonomies = get_object_taxonomies($post->post_type, 'objects');
		foreach ( $taxonomies as $taxonomy ) {
			// Skip built-in taxonomies already handled
			if ( in_array($taxonomy->name, array('category', 'post_tag', 'post_format')) ) {
				continue;
			}
			
			$terms = get_the_terms($post_id, $taxonomy->name);
			if ( ! empty($terms) && ! is_wp_error($terms) ) {
				foreach ( $terms as $term ) {
					$term_text = $taxonomy->label . ': ' . $term->name;
					if ( ! empty($term->description) ) {
						$term_text .= ' - ' . $term->description;
					}
					$content_parts[] = $term_text;
				}
			}
		}
		
		// Add featured image alt text
		if ( has_post_thumbnail($post_id) ) {
			$thumbnail_id = get_post_thumbnail_id($post_id);
			$alt_text = get_post_meta($thumbnail_id, '_wp_attachment_image_alt', true);
			if ( $alt_text ) {
				$content_parts[] = 'Featured Image: ' . $alt_text;
			}
			$caption = wp_get_attachment_caption($thumbnail_id);
			if ( $caption ) {
				$content_parts[] = 'Image Caption: ' . $caption;
			}
		}
		
		// Add ACF fields if ACF is active
		if ( function_exists('get_fields') ) {
			$acf_fields = get_fields($post_id);
			if ( ! empty($acf_fields) && is_array($acf_fields) ) {
				foreach ( $acf_fields as $field_name => $field_value ) {
					// Skip empty values and arrays/objects
					if ( empty($field_value) || is_array($field_value) || is_object($field_value) ) {
						continue;
					}
					// Convert field name to readable format
					$readable_name = ucwords(str_replace(array('_', '-'), ' ', $field_name));
					$content_parts[] = $readable_name . ': ' . $field_value;
				}
			}
		}
		
		// Add common custom fields (non-private meta)
		$all_meta = get_post_meta($post_id);
		$allowed_meta_keys = array(
			'subtitle' => 'Subtitle',
			'subheading' => 'Subheading',
			'custom_description' => 'Description',
			'location' => 'Location',
			'event_date' => 'Event Date',
			'price' => 'Price',
			'duration' => 'Duration',
		);
		
		foreach ( $allowed_meta_keys as $meta_key => $label ) {
			if ( isset($all_meta[$meta_key]) && ! empty($all_meta[$meta_key][0]) ) {
				$meta_value = $all_meta[$meta_key][0];
				// Skip serialized data
				if ( ! is_serialized($meta_value) ) {
					$content_parts[] = $label . ': ' . $meta_value;
				}
			}
		}
		
		// Add Elementor meta description if available
		$elementor_settings = get_post_meta( $post_id, '_elementor_page_settings', true );
		if ( ! empty( $elementor_settings['post_excerpt'] ) ) {
			$content_parts[] = 'Meta Description: ' . $elementor_settings['post_excerpt'];
		}
		
		// Add SEO meta if available
		$seo_desc = get_post_meta( $post_id, '_yoast_wpseo_metadesc', true );
		if ( $seo_desc ) {
			$content_parts[] = 'SEO Description: ' . $seo_desc;
		}
		
		$seo_title = get_post_meta( $post_id, '_yoast_wpseo_title', true );
		if ( $seo_title ) {
			$content_parts[] = 'SEO Title: ' . $seo_title;
		}

		$content = $this->prepare_content(implode("\n", $content_parts));
		
		// Store title before restoring global post
		$post_title = $post->post_title;
		
		// Restore global post
		$post = $old_global_post;
		
		if ( empty($content) ) {
			return;
		}

		$this->store_content('post', $post_id, $content, get_permalink($post_id), $post_title);
	}

	/**
	 * Index a single comment.
	 *
	 * This method indexes a single comment by its ID. It prepares the content and stores it in the database.
	 *
	 * @param int             $comment_id Comment ID to index.
	 * @param WP_Comment|null $comment Optional. Comment object. Default null.
	 * @return void
	 */
	public function index_comment( $comment_id, $comment = null ) {
		if ( ! $comment ) {
			$comment = get_comment($comment_id);
		}

		if ( ! $comment || $comment->comment_approved !== '1' ) {
			return;
		}

		$content = $this->prepare_content($comment->comment_content);
		if ( empty($content) ) {
			return;
		}

		$title = 'Comment by ' . $comment->comment_author;
		$this->store_content('comment', $comment_id, $content, get_comment_link($comment_id), $title);
	}

	/**
	 * Index a single product with comprehensive WooCommerce data.
	 *
	 * This method indexes a single product by its ID with full product data including
	 * categories, tags, attributes, variations, stock info, and metadata.
	 * Optimized for AI understanding with clear labels and structure.
	 *
	 * @param int $product_id Product ID to index.
	 * @return void
	 */
	public function index_product( $product_id ) {
		$product = wc_get_product($product_id);
		if ( ! $product ) {
			return;
		}

		$content = array();
		
		// === BASIC PRODUCT INFORMATION ===
		$content[] = '=== PRODUCT INFORMATION ===';
		$content[] = 'Product Name: ' . $product->get_name();
		$content[] = 'Product Type: ' . ucfirst($product->get_type());
		$content[] = 'SKU: ' . $product->get_sku();
		$content[] = 'Status: ' . ucfirst($product->get_status());
		
		// === PRICING ===
		$content[] = "\n=== PRICING ===";
		$content[] = 'Regular Price: ' . wc_price($product->get_regular_price());
		if ( $product->is_on_sale() ) {
			$content[] = 'Sale Price: ' . wc_price($product->get_sale_price());
			$content[] = 'On Sale: Yes';
		}
		$content[] = 'Display Price: ' . $product->get_price_html();
		
		// === DESCRIPTIONS ===
		$content[] = "\n=== DESCRIPTIONS ===";
		if ( $product->get_short_description() ) {
			$content[] = 'Short Description: ' . $product->get_short_description();
		}
		if ( $product->get_description() ) {
			$content[] = 'Full Description: ' . $product->get_description();
		}

		// === STOCK INFORMATION ===
		$content[] = "\n=== STOCK & AVAILABILITY ===";
		if ( $product->managing_stock() ) {
			$content[] = 'Stock Quantity: ' . $product->get_stock_quantity();
			$content[] = 'Stock Status: ' . ucfirst($product->get_stock_status());
			$content[] = 'Backorders: ' . ucfirst($product->get_backorders());
		} else {
			$content[] = 'Stock Status: ' . ucfirst($product->get_stock_status());
		}
		$content[] = 'In Stock: ' . ($product->is_in_stock() ? 'Yes' : 'No');

		// === CATEGORIES ===
		$categories = wp_get_post_terms($product_id, 'product_cat');
		if ( ! empty($categories) ) {
			$content[] = "\n=== CATEGORIES ===";
			foreach ( $categories as $category ) {
				$cat_text = 'Category: ' . $category->name;
				if ( ! empty($category->description) ) {
					$cat_text .= ' - ' . $category->description;
				}
				$content[] = $cat_text;
			}
		}

		// === TAGS ===
		$tags = wp_get_post_terms($product_id, 'product_tag');
		if ( ! empty($tags) ) {
			$content[] = "\n=== TAGS ===";
			$tag_names = array_map(function($tag) { return $tag->name; }, $tags);
			$content[] = 'Tags: ' . implode(', ', $tag_names);
		}

		// === ATTRIBUTES ===
		$attributes = $product->get_attributes();
		if ( ! empty($attributes) ) {
			$content[] = "\n=== PRODUCT ATTRIBUTES ===";
			foreach ( $attributes as $attribute ) {
				$attribute_name = $attribute->get_name();
				$attribute_label = wc_attribute_label($attribute_name);
				
				if ( $attribute->is_taxonomy() ) {
					$terms = wp_get_post_terms($product_id, $attribute_name);
					$term_names = array_map(function($term) { return $term->name; }, $terms);
					if ( ! empty($term_names) ) {
						$content[] = $attribute_label . ': ' . implode(', ', $term_names);
					}
				} else {
					$options = $attribute->get_options();
					if ( is_array($options) && ! empty($options) ) {
						$content[] = $attribute_label . ': ' . implode(', ', $options);
					}
				}
			}
		}

		// === VARIATIONS (for variable products) ===
		if ( $product->is_type('variable') ) {
			$variations = $product->get_children();
			if ( ! empty($variations) ) {
				$content[] = "\n=== PRODUCT VARIATIONS ===";
				$content[] = 'Total Variations: ' . count($variations);
				
				foreach ( $variations as $variation_id ) {
					$variation = wc_get_product($variation_id);
					if ( $variation ) {
						$content[] = "\n--- Variation ---";
						$content[] = 'Variation Name: ' . $variation->get_name();
						
						if ( $variation->get_sku() ) {
							$content[] = 'Variation SKU: ' . $variation->get_sku();
						}
						
						$content[] = 'Variation Price: ' . $variation->get_price_html();
						
						if ( $variation->managing_stock() ) {
							$content[] = 'Variation Stock: ' . $variation->get_stock_quantity();
						}
						$content[] = 'Variation In Stock: ' . ($variation->is_in_stock() ? 'Yes' : 'No');
						
						// Add variation attributes
						$variation_attributes = $variation->get_variation_attributes();
						if ( ! empty($variation_attributes) ) {
							foreach ( $variation_attributes as $attr_name => $attr_value ) {
								$clean_name = str_replace('attribute_', '', $attr_name);
								$clean_name = wc_attribute_label($clean_name);
								$content[] = $clean_name . ': ' . $attr_value;
							}
						}
					}
				}
			}
		}

		// === DIMENSIONS & SHIPPING ===
		$has_dimensions = false;
		$dimensions_content = array();
		
		if ( $product->get_weight() ) {
			$dimensions_content[] = 'Weight: ' . $product->get_weight() . ' ' . get_option('woocommerce_weight_unit');
			$has_dimensions = true;
		}
		if ( $product->get_length() ) {
			$dimensions_content[] = 'Length: ' . $product->get_length() . ' ' . get_option('woocommerce_dimension_unit');
			$has_dimensions = true;
		}
		if ( $product->get_width() ) {
			$dimensions_content[] = 'Width: ' . $product->get_width() . ' ' . get_option('woocommerce_dimension_unit');
			$has_dimensions = true;
		}
		if ( $product->get_height() ) {
			$dimensions_content[] = 'Height: ' . $product->get_height() . ' ' . get_option('woocommerce_dimension_unit');
			$has_dimensions = true;
		}
		
		if ( $has_dimensions ) {
			$content[] = "\n=== DIMENSIONS & SHIPPING ===";
			$content = array_merge($content, $dimensions_content);
		}
		
		$shipping_class = $product->get_shipping_class();
		if ( $shipping_class ) {
			if ( ! $has_dimensions ) {
				$content[] = "\n=== SHIPPING ===";
			}
			$content[] = 'Shipping Class: ' . $shipping_class;
		}

		// === REVIEWS & RATINGS ===
		$average_rating = $product->get_average_rating();
		$review_count = $product->get_review_count();
		if ( $average_rating > 0 || $review_count > 0 ) {
			$content[] = "\n=== REVIEWS & RATINGS ===";
			$content[] = 'Average Rating: ' . $average_rating . ' out of 5';
			$content[] = 'Total Reviews: ' . $review_count;
		}

		// === TAX INFORMATION ===
		$content[] = "\n=== TAX INFORMATION ===";
		$content[] = 'Tax Status: ' . ucfirst($product->get_tax_status());
		$tax_class = $product->get_tax_class();
		if ( $tax_class ) {
			$content[] = 'Tax Class: ' . $tax_class;
		}

		// === ADDITIONAL INFORMATION ===
		$additional_info = array();
		
		$purchase_note = get_post_meta($product_id, '_purchase_note', true);
		if ( $purchase_note ) {
			$additional_info[] = 'Purchase Note: ' . $purchase_note;
		}
		
		if ( $product->is_type('external') ) {
			$external_url = $product->get_product_url();
			$button_text = $product->get_button_text();
			if ( $external_url ) {
				$additional_info[] = 'External URL: ' . $external_url;
			}
			if ( $button_text ) {
				$additional_info[] = 'Button Text: ' . $button_text;
			}
		}
		
		if ( ! empty($additional_info) ) {
			$content[] = "\n=== ADDITIONAL INFORMATION ===";
			$content = array_merge($content, $additional_info);
		}

		// === IMAGES ===
		$gallery_ids = $product->get_gallery_image_ids();
		if ( ! empty($gallery_ids) ) {
			$content[] = "\n=== PRODUCT IMAGES ===";
			foreach ( $gallery_ids as $image_id ) {
				$alt_text = get_post_meta($image_id, '_wp_attachment_image_alt', true);
				if ( $alt_text ) {
					$content[] = 'Image Description: ' . $alt_text;
				}
			}
		}
		
		// Add featured image alt text
		if ( has_post_thumbnail($product_id) ) {
			$thumbnail_id = get_post_thumbnail_id($product_id);
			$alt_text = get_post_meta($thumbnail_id, '_wp_attachment_image_alt', true);
			if ( $alt_text ) {
				if ( empty($gallery_ids) ) {
					$content[] = "\n=== PRODUCT IMAGES ===";
				}
				$content[] = 'Featured Image: ' . $alt_text;
			}
		}

		// === ACF FIELDS (if available) ===
		if ( function_exists('get_fields') ) {
			$acf_fields = get_fields($product_id);
			if ( ! empty($acf_fields) && is_array($acf_fields) ) {
				$content[] = "\n=== CUSTOM FIELDS ===";
				foreach ( $acf_fields as $field_name => $field_value ) {
					if ( empty($field_value) || is_array($field_value) || is_object($field_value) ) {
						continue;
					}
					$readable_name = ucwords(str_replace(array('_', '-'), ' ', $field_name));
					$content[] = $readable_name . ': ' . $field_value;
				}
			}
		}

		$prepared_content = $this->prepare_content(implode("\n", $content));
		if ( empty($prepared_content) ) {
			return;
		}

		$this->store_content('product', $product_id, $prepared_content, get_permalink($product_id), $product->get_name());
	}

	/**
	 * Delete the index for a post.
	 *
	 * This method deletes the index entry for a specific post by its ID.
	 *
	 * @param int $post_id Post ID to delete from the index.
	 * @return void
	 */
	public function delete_post_index( $post_id ) {
		global $wpdb;
		$tables = $this->database->get_tables();
		$content_index_table = $tables['content_index'];

		$wpdb->delete(
			$content_index_table,
			array(
				'object_type' => 'post',
				'object_id' => $post_id,
			),
			array( '%s', '%d' )
		);
	}

	/**
	 * Delete the index for a comment.
	 *
	 * This method deletes the index entry for a specific comment by its ID.
	 *
	 * @param int $comment_id Comment ID to delete from the index.
	 * @return void
	 */
	public function delete_comment_index( $comment_id ) {
		global $wpdb;
		$tables = $this->database->get_tables();
		$content_index_table = $tables['content_index'];

		$wpdb->delete(
			$content_index_table,
			array(
				'object_type' => 'comment',
				'object_id' => $comment_id,
			),
			array( '%s', '%d' )
		);
	}

	/**
	 * Delete the index for a product.
	 *
	 * This method deletes the index entry for a specific product by its ID.
	 *
	 * @param int $product_id Product ID to delete from the index.
	 * @return void
	 */
	public function delete_product_index( $product_id ) {
		global $wpdb;
		$tables = $this->database->get_tables();
		$content_index_table = $tables['content_index'];

		$wpdb->delete(
			$content_index_table,
			array(
				'object_type' => 'product',
				'object_id' => $product_id,
			),
			array( '%s', '%d' )
		);
	}

	/**
	 * Index pages in batches.
	 *
	 * This method retrieves all published pages and indexes them in batches.
	 *
	 * @return void
	 */
	private function index_pages() {
		$args = array(
			'post_type' => 'page',
			'post_status' => 'publish',
			'posts_per_page' => -1,
			'fields' => 'ids',
		);

		$page_ids = get_posts($args);
		$total_pages = count($page_ids);

		for ( $i = 0; $i < $total_pages; $i += $this->batch_size ) {
			$batch = array_slice($page_ids, $i, $this->batch_size);
			foreach ( $batch as $page_id ) {
				$this->index_page($page_id);
			}
		}
	}

	/**
	 * Index template pages.
	 *
	 * This method indexes page templates and their content.
	 *
	 * @return void
	 */
	private function index_template_pages() {
		// Get all page templates from theme
		$templates = wp_get_theme()->get_page_templates();
		
		foreach ( $templates as $template_file => $template_name ) {
			$this->index_template_page($template_file, $template_name);
		}
		
		// Also index pages that USE these templates
		$args = array(
			'post_type' => 'page',
			'post_status' => 'publish',
			'posts_per_page' => -1,
			'meta_query' => array(
				array(
					'key' => '_wp_page_template',
					'value' => 'default',
					'compare' => '!='
				)
			)
		);
		
		$pages_with_templates = get_posts($args);
		foreach ( $pages_with_templates as $page ) {
			// Index the page with its template content
			$this->index_page_with_template( $page->ID );
		}
	}

	/**
	 * Index documentation pages.
	 *
	 * This method indexes documentation-related content and custom post types.
	 *
	 * @return void
	 */
	private function index_docs_pages() {
		// Index common documentation post types including BetterDocs
		$doc_post_types = array('docs', 'documentation', 'knowledge_base', 'faq', 'betterdocs');
		
		foreach ( $doc_post_types as $post_type ) {
			if ( post_type_exists($post_type) ) {
				$args = array(
					'post_type' => $post_type,
					'post_status' => 'publish',
					'posts_per_page' => -1,
					'fields' => 'ids',
				);

				$doc_ids = get_posts($args);
				foreach ( $doc_ids as $doc_id ) {
					$this->index_docs_page($doc_id);
				}
			}
		}
		
		// Index BetterDocs categories and tags if plugin is active
		if ( class_exists('BetterDocs') || taxonomy_exists('doc_category') ) {
			$this->index_betterdocs_taxonomies();
		}
	}

	/**
	 * Index BetterDocs taxonomies (categories, tags, knowledge bases).
	 *
	 * @return void
	 */
	private function index_betterdocs_taxonomies() {
		// Index doc categories
		if ( taxonomy_exists('doc_category') ) {
			$doc_categories = get_terms(array(
				'taxonomy' => 'doc_category',
				'hide_empty' => false,
			));

			foreach ( $doc_categories as $category ) {
				$content = array(
					$category->name,
					$category->description,
					$category->slug,
				);

				// Get category icon if available
				$icon = get_term_meta($category->term_id, 'doc_category_image-id', true);
				if ( $icon ) {
					$content[] = "Has icon";
				}

				// Get category order
				$order = get_term_meta($category->term_id, 'doc_category_order', true);
				if ( $order ) {
					$content[] = "Order: " . $order;
				}

				$prepared_content = $this->prepare_content(implode("\n", $content));
				if ( ! empty($prepared_content) ) {
					$this->store_content('doc_category', $category->term_id, $prepared_content, get_term_link($category), $category->name);
				}
			}
		}

		// Index doc tags
		if ( taxonomy_exists('doc_tag') ) {
			$doc_tags = get_terms(array(
				'taxonomy' => 'doc_tag',
				'hide_empty' => false,
			));

			foreach ( $doc_tags as $tag ) {
				$content = array(
					$tag->name,
					$tag->description,
					$tag->slug,
				);

				$prepared_content = $this->prepare_content(implode("\n", $content));
				if ( ! empty($prepared_content) ) {
					$this->store_content('doc_tag', $tag->term_id, $prepared_content, get_term_link($tag), $tag->name);
				}
			}
		}

		// Index knowledge bases
		if ( taxonomy_exists('knowledge_base') ) {
			$knowledge_bases = get_terms(array(
				'taxonomy' => 'knowledge_base',
				'hide_empty' => false,
			));

			foreach ( $knowledge_bases as $kb ) {
				$content = array(
					$kb->name,
					$kb->description,
					$kb->slug,
				);

				$prepared_content = $this->prepare_content(implode("\n", $content));
				if ( ! empty($prepared_content) ) {
					$this->store_content('knowledge_base', $kb->term_id, $prepared_content, get_term_link($kb), $kb->name);
				}
			}
		}
	}

	/**
	 * Index product categories.
	 *
	 * This method indexes WooCommerce product categories and their descriptions.
	 *
	 * @return void
	 */
	private function index_product_categories() {
		$categories = get_terms(array(
			'taxonomy' => 'product_cat',
			'hide_empty' => false,
		));

		foreach ( $categories as $category ) {
			$this->index_product_category($category);
		}
	}

	/**
	 * Index product tags.
	 *
	 * This method indexes WooCommerce product tags and their descriptions.
	 *
	 * @return void
	 */
	private function index_product_tags() {
		$tags = get_terms(array(
			'taxonomy' => 'product_tag',
			'hide_empty' => false,
		));

		foreach ( $tags as $tag ) {
			$this->index_product_tag($tag);
		}
	}

	/**
	 * Index custom fields across the website.
	 *
	 * This method indexes custom fields and meta data from posts, pages, and products.
	 *
	 * @return void
	 */
	private function index_custom_fields() {
		global $wpdb;

		// Get all custom fields with meaningful content
		$custom_fields = $wpdb->get_results("
			SELECT DISTINCT meta_key, meta_value, post_id 
			FROM {$wpdb->postmeta} 
			WHERE meta_key NOT LIKE '\_%' 
			AND meta_value != '' 
			AND LENGTH(meta_value) > 10
			LIMIT 1000
		");

		foreach ( $custom_fields as $field ) {
			$this->index_custom_field($field);
		}
	}

	/**
	 * Index navigation menus.
	 *
	 * This method indexes WordPress navigation menus and their items.
	 *
	 * @return void
	 */
	private function index_menus() {
		$menus = wp_get_nav_menus();

		foreach ( $menus as $menu ) {
			$this->index_menu($menu);
		}
	}

	/**
	 * Index widgets.
	 *
	 * This method indexes active widgets and their content.
	 *
	 * @return void
	 */
	private function index_widgets() {
		$sidebars = wp_get_sidebars_widgets();

		foreach ( $sidebars as $sidebar_id => $widgets ) {
			if ( is_array($widgets) ) {
				foreach ( $widgets as $widget_id ) {
					$this->index_widget($widget_id, $sidebar_id);
				}
			}
		}
	}

	/**
	 * Index a single page.
	 *
	 * @param int $page_id Page ID to index.
	 * @return void
	 */
	private function index_page( $page_id ) {
		global $post;
		
		$page = get_post($page_id);
		if ( ! $page || $page->post_status !== 'publish' ) {
			return;
		}

		// Set global post for Elementor extraction
		$old_post = $post;
		$post = $page;

		$content = array(
			$page->post_title,
			$page->post_content,
			$page->post_excerpt,
		);

		// Add page template info
		$template = get_page_template_slug($page_id);
		if ( $template ) {
			$content[] = "Template: " . $template;
		}
		
		// Add Elementor meta description if available
		$elementor_settings = get_post_meta( $page_id, '_elementor_page_settings', true );
		if ( ! empty( $elementor_settings['post_excerpt'] ) ) {
			$content[] = $elementor_settings['post_excerpt'];
		}
		
		// Add custom fields that might contain important info
		$custom_fields = array(
			'_yoast_wpseo_metadesc' => 'SEO Description',
			'_yoast_wpseo_title' => 'SEO Title',
			'page_subtitle' => 'Subtitle',
			'page_description' => 'Description',
		);
		
		foreach ( $custom_fields as $field => $label ) {
			$meta_value = get_post_meta( $page_id, $field, true );
			if ( $meta_value ) {
				$content[] = $label . ": " . $meta_value;
			}
		}

		$prepared_content = $this->prepare_content(implode("\n", $content));
		
		// Restore global post
		$post = $old_post;
		
		if ( empty($prepared_content) ) {
			return;
		}

		$this->store_content('page', $page_id, $prepared_content, get_permalink($page_id), $page->post_title);
	}

	/**
	 * Index a template page.
	 *
	 * @param string $template_file Template file name.
	 * @param string $template_name Template display name.
	 * @return void
	 */
	private function index_template_page( $template_file, $template_name ) {
		$content = array(
			$template_name,
			"Template file: " . $template_file,
		);

		// Try to read template file content from theme directories
		$template_paths = array(
			get_template_directory() . '/' . $template_file,
			get_stylesheet_directory() . '/' . $template_file,
			// Check in templates subdirectory (common location)
			get_template_directory() . '/templates/' . $template_file,
			get_stylesheet_directory() . '/templates/' . $template_file,
		);
		
		$template_path = '';
		foreach ( $template_paths as $path ) {
			if ( file_exists( $path ) ) {
				$template_path = $path;
				break;
			}
		}

		if ( ! empty( $template_path ) && file_exists( $template_path ) ) {
			$file_content = file_get_contents( $template_path );
			
			// Extract PHP doc comments and Template Name
			preg_match_all('/\/\*\*(.*?)\*\//s', $file_content, $doc_matches);
			if ( ! empty( $doc_matches[1] ) ) {
				foreach ( $doc_matches[1] as $doc_comment ) {
					// Clean up doc comment
					$doc_comment = preg_replace('/^\s*\*\s*/m', '', $doc_comment);
					$content[] = trim( $doc_comment );
				}
			}
			
			// Extract all translatable strings
			preg_match_all('/esc_html_e\([\'"]([^\'"]+)[\'"]/i', $file_content, $i18n_matches);
			if ( ! empty( $i18n_matches[1] ) ) {
				$content = array_merge( $content, $i18n_matches[1] );
			}
			
			preg_match_all('/esc_html__\([\'"]([^\'"]+)[\'"]/i', $file_content, $i18n_matches2);
			if ( ! empty( $i18n_matches2[1] ) ) {
				$content = array_merge( $content, $i18n_matches2[1] );
			}
			
			preg_match_all('/esc_attr_e\([\'"]([^\'"]+)[\'"]/i', $file_content, $i18n_matches3);
			if ( ! empty( $i18n_matches3[1] ) ) {
				$content = array_merge( $content, $i18n_matches3[1] );
			}
			
			preg_match_all('/esc_attr__\([\'"]([^\'"]+)[\'"]/i', $file_content, $i18n_matches4);
			if ( ! empty( $i18n_matches4[1] ) ) {
				$content = array_merge( $content, $i18n_matches4[1] );
			}
			
			// Extract content from esc_html() wrapping strings
			preg_match_all('/esc_html\([\'"]([^\'"]+)[\'"]\)/i', $file_content, $esc_html_matches);
			if ( ! empty( $esc_html_matches[1] ) ) {
				$content = array_merge( $content, $esc_html_matches[1] );
			}
			
			// Extract HTML content (text between tags)
			// Create a version with PHP short tags processed
			$html_content = $file_content;
			
			// Remove PHP blocks but keep their echo output patterns
			$html_content = preg_replace('/<\?php\s+echo\s+esc_html\([\'"]([^\'"]+)[\'"]\)\s*;\s*\?>/i', '$1', $html_content);
			$html_content = preg_replace('/<\?php.*?\?>/s', ' ', $html_content);
			
			// Extract text from HTML using DOMDocument
			$dom = new \DOMDocument();
			libxml_use_internal_errors(true); // Suppress HTML5 warnings
			@$dom->loadHTML( '<?xml encoding="UTF-8">' . $html_content, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD );
			libxml_clear_errors();
			
			// Extract text from all relevant elements
			$text_elements = array( 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'li', 'span', 'div', 'a', 'button', 'label', 'td', 'th' );
			foreach ( $text_elements as $tag ) {
				$elements = $dom->getElementsByTagName( $tag );
				foreach ( $elements as $element ) {
					$text = trim( $element->textContent );
					// Filter out empty strings, very short strings, and common noise
					if ( ! empty( $text ) && strlen( $text ) > 2 && ! preg_match('/^[\d\s\$\%\.\,\-]+$/', $text) ) {
						$content[] = $text;
					}
				}
			}
			
			// Extract class names that might be descriptive (like "hero-title", "feature-description")
			preg_match_all('/class=["\']([^"\']*(?:title|heading|description|content|text|feature|benefit|section)[^"\']*)["\']/', $file_content, $class_matches);
			if ( ! empty( $class_matches[1] ) ) {
				foreach ( $class_matches[1] as $class_name ) {
					// Convert class names to readable text (e.g., "hero-title" -> "hero title")
					$readable = str_replace( array('-', '_'), ' ', $class_name );
					if ( strlen( $readable ) > 5 ) {
						$content[] = "Section: " . $readable;
					}
				}
			}
			
			// Extract alt text from images
			preg_match_all('/alt=["\']([^"\']+)["\']/', $file_content, $alt_matches);
			if ( ! empty( $alt_matches[1] ) ) {
				foreach ( $alt_matches[1] as $alt_text ) {
					if ( strlen( $alt_text ) > 3 ) {
						$content[] = "Image: " . $alt_text;
					}
				}
			}
			
			// Extract aria-label attributes for accessibility content
			preg_match_all('/aria-label=["\']([^"\']+)["\']/', $file_content, $aria_matches);
			if ( ! empty( $aria_matches[1] ) ) {
				$content = array_merge( $content, $aria_matches[1] );
			}
		}

		// Remove duplicates and empty values
		$content = array_unique( array_filter( $content ) );
		
		$prepared_content = $this->prepare_content(implode("\n", $content));
		if ( empty($prepared_content) ) {
			return;
		}

		$this->store_content('template_page', crc32($template_file), $prepared_content, '', $template_name);
	}
	
	/**
	 * Index a page that uses a custom template
	 *
	 * @param int $page_id Page ID
	 * @return void
	 */
	private function index_page_with_template( $page_id ) {
		global $post;
		
		$page = get_post( $page_id );
		if ( ! $page || $page->post_status !== 'publish' ) {
			return;
		}
		
		// Set global post for Elementor extraction
		$old_post = $post;
		$post = $page;
		
		$template_file = get_page_template_slug( $page_id );
		
		$content = array(
			$page->post_title,
			$page->post_content,
			$page->post_excerpt,
			"Template: " . $template_file,
		);
		
		// Get template content from theme directories
		$template_paths = array(
			get_template_directory() . '/' . $template_file,
			get_stylesheet_directory() . '/' . $template_file,
			get_template_directory() . '/templates/' . $template_file,
			get_stylesheet_directory() . '/templates/' . $template_file,
		);
		
		foreach ( $template_paths as $template_path ) {
			if ( file_exists( $template_path ) ) {
				$file_content = file_get_contents( $template_path );
				
				// Extract all translatable strings from the template
				preg_match_all('/esc_html_e\([\'"]([^\'"]+)[\'"]/i', $file_content, $i18n_matches);
				if ( ! empty( $i18n_matches[1] ) ) {
					$content = array_merge( $content, $i18n_matches[1] );
				}
				
				preg_match_all('/esc_html__\([\'"]([^\'"]+)[\'"]/i', $file_content, $i18n_matches2);
				if ( ! empty( $i18n_matches2[1] ) ) {
					$content = array_merge( $content, $i18n_matches2[1] );
				}
				
				preg_match_all('/esc_attr_e\([\'"]([^\'"]+)[\'"]/i', $file_content, $i18n_matches3);
				if ( ! empty( $i18n_matches3[1] ) ) {
					$content = array_merge( $content, $i18n_matches3[1] );
				}
				
				preg_match_all('/esc_html\([\'"]([^\'"]+)[\'"]\)/i', $file_content, $esc_html_matches);
				if ( ! empty( $esc_html_matches[1] ) ) {
					$content = array_merge( $content, $esc_html_matches[1] );
				}
				
				// Extract visible text content from HTML
				$html_content = preg_replace('/<\?php\s+echo\s+esc_html\([\'"]([^\'"]+)[\'"]\)\s*;\s*\?>/i', '$1', $file_content);
				$html_content = preg_replace('/<\?php.*?\?>/s', ' ', $html_content);
				
				$dom = new \DOMDocument();
				libxml_use_internal_errors(true);
				@$dom->loadHTML( '<?xml encoding="UTF-8">' . $html_content, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD );
				libxml_clear_errors();
				
				$text_elements = array( 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'li', 'span', 'a', 'button', 'label', 'td', 'th' );
				foreach ( $text_elements as $tag ) {
					$elements = $dom->getElementsByTagName( $tag );
					foreach ( $elements as $element ) {
						$text = trim( $element->textContent );
						if ( ! empty( $text ) && strlen( $text ) > 2 && ! preg_match('/^[\d\s\$\%\.\,\-]+$/', $text) ) {
							$content[] = $text;
						}
					}
				}
				
				// Extract alt text and aria-labels
				preg_match_all('/alt=["\']([^"\']+)["\']/', $file_content, $alt_matches);
				if ( ! empty( $alt_matches[1] ) ) {
					foreach ( $alt_matches[1] as $alt_text ) {
						if ( strlen( $alt_text ) > 3 ) {
							$content[] = $alt_text;
						}
					}
				}
				
				preg_match_all('/aria-label=["\']([^"\']+)["\']/', $file_content, $aria_matches);
				if ( ! empty( $aria_matches[1] ) ) {
					$content = array_merge( $content, $aria_matches[1] );
				}
				
				// Extract section/feature descriptions from class names
				preg_match_all('/class=["\']([^"\']*(?:title|heading|description|content|text|feature|benefit)[^"\']*)["\']/', $file_content, $class_matches);
				if ( ! empty( $class_matches[1] ) ) {
					foreach ( $class_matches[1] as $class_name ) {
						$readable = str_replace( array('-', '_'), ' ', $class_name );
						if ( strlen( $readable ) > 5 ) {
							$content[] = "Section: " . $readable;
						}
					}
				}
				
				break;
			}
		}
		
		// Add custom fields
		$custom_fields = array(
			'_yoast_wpseo_metadesc' => 'SEO Description',
			'_yoast_wpseo_title' => 'SEO Title',
		);
		
		foreach ( $custom_fields as $field => $label ) {
			$meta_value = get_post_meta( $page_id, $field, true );
			if ( $meta_value ) {
				$content[] = $label . ": " . $meta_value;
			}
		}
		
		// Remove duplicates
		$content = array_unique( array_filter( $content ) );
		
		$prepared_content = $this->prepare_content( implode( "\n", $content ) );
		
		// Restore global post
		$post = $old_post;
		
		if ( empty( $prepared_content ) ) {
			return;
		}
		
		$this->store_content( 'page', $page_id, $prepared_content, get_permalink( $page_id ), $page->post_title );
	}

	/**
	 * Index a documentation page.
	 *
	 * @param int $doc_id Documentation page ID.
	 * @return void
	 */
	private function index_docs_page( $doc_id ) {
		$doc = get_post($doc_id);
		if ( ! $doc || $doc->post_status !== 'publish' ) {
			return;
		}

		$content = array(
			$doc->post_title,
			$doc->post_content,
			$doc->post_excerpt,
		);

		// Add BetterDocs categories
		$doc_categories = wp_get_post_terms($doc_id, 'doc_category');
		if ( ! empty($doc_categories) && ! is_wp_error($doc_categories) ) {
			foreach ( $doc_categories as $category ) {
				$content[] = "Category: " . $category->name;
				if ( ! empty($category->description) ) {
					$content[] = $category->description;
				}
			}
		}

		// Add BetterDocs tags
		$doc_tags = wp_get_post_terms($doc_id, 'doc_tag');
		if ( ! empty($doc_tags) && ! is_wp_error($doc_tags) ) {
			foreach ( $doc_tags as $tag ) {
				$content[] = "Tag: " . $tag->name;
			}
		}

		// Add knowledge base taxonomy
		$knowledge_bases = wp_get_post_terms($doc_id, 'knowledge_base');
		if ( ! empty($knowledge_bases) && ! is_wp_error($knowledge_bases) ) {
			foreach ( $knowledge_bases as $kb ) {
				$content[] = "Knowledge Base: " . $kb->name;
			}
		}

		// Add custom fields that might contain documentation metadata
		$meta_fields = array(
			'doc_category' => 'Category',
			'doc_tags' => 'Tags',
			'doc_difficulty' => 'Difficulty',
			'doc_version' => 'Version',
			'_betterdocs_meta_views' => 'Views',
			'_betterdocs_meta_reactions' => 'Reactions',
		);
		
		foreach ( $meta_fields as $field => $label ) {
			$meta_value = get_post_meta($doc_id, $field, true);
			if ( $meta_value ) {
				$content[] = $label . ": " . $meta_value;
			}
		}

		// Add related docs if available
		$related_docs = get_post_meta($doc_id, '_betterdocs_related_docs', true);
		if ( ! empty($related_docs) && is_array($related_docs) ) {
			foreach ( $related_docs as $related_id ) {
				$related_post = get_post($related_id);
				if ( $related_post ) {
					$content[] = "Related: " . $related_post->post_title;
				}
			}
		}

		$prepared_content = $this->prepare_content(implode("\n", $content));
		if ( empty($prepared_content) ) {
			return;
		}

		$this->store_content('docs', $doc_id, $prepared_content, get_permalink($doc_id), $doc->post_title);
	}

	/**
	 * Index a product category.
	 *
	 * @param WP_Term $category Product category term.
	 * @return void
	 */
	private function index_product_category( $category ) {
		$content = array(
			$category->name,
			$category->description,
			$category->slug,
		);

		$prepared_content = $this->prepare_content(implode("\n", $content));
		if ( empty($prepared_content) ) {
			return;
		}

		$this->store_content('product_category', $category->term_id, $prepared_content, get_term_link($category), $category->name);
	}

	/**
	 * Index a product tag.
	 *
	 * @param WP_Term $tag Product tag term.
	 * @return void
	 */
	private function index_product_tag( $tag ) {
		$content = array(
			$tag->name,
			$tag->description,
			$tag->slug,
		);

		$prepared_content = $this->prepare_content(implode("\n", $content));
		if ( empty($prepared_content) ) {
			return;
		}

		$this->store_content('product_tag', $tag->term_id, $prepared_content, get_term_link($tag), $tag->name);
	}

	/**
	 * Index a custom field.
	 *
	 * @param object $field Custom field data.
	 * @return void
	 */
	private function index_custom_field( $field ) {
		$content = array(
			$field->meta_key,
			$field->meta_value,
		);

		$prepared_content = $this->prepare_content(implode(": ", $content));
		if ( empty($prepared_content) ) {
			return;
		}

		$post_url = get_permalink($field->post_id);
		$this->store_content('custom_field', $field->post_id . '_' . crc32($field->meta_key), $prepared_content, $post_url, $field->meta_key);
	}

	/**
	 * Index a navigation menu.
	 *
	 * @param WP_Term $menu Menu term object.
	 * @return void
	 */
	private function index_menu( $menu ) {
		$menu_items = wp_get_nav_menu_items($menu->term_id);
		$content = array($menu->name);

		foreach ( $menu_items as $item ) {
			$content[] = $item->title;
			if ( $item->description ) {
				$content[] = $item->description;
			}
		}

		$prepared_content = $this->prepare_content(implode("\n", $content));
		if ( empty($prepared_content) ) {
			return;
		}

		$this->store_content('menu', $menu->term_id, $prepared_content, '', $menu->name);
	}

	/**
	 * Index a widget.
	 *
	 * @param string $widget_id Widget ID.
	 * @param string $sidebar_id Sidebar ID.
	 * @return void
	 */
	private function index_widget( $widget_id, $sidebar_id ) {
		global $wp_registered_widgets;

		if ( ! isset($wp_registered_widgets[$widget_id]) ) {
			return;
		}

		$widget = $wp_registered_widgets[$widget_id];
		$content = array(
			$widget['name'],
			"Sidebar: " . $sidebar_id,
		);

		// Try to get widget settings
		$widget_base = $widget['callback'][0]->id_base ?? '';
		if ( $widget_base ) {
			$widget_options = get_option('widget_' . $widget_base);
			if ( is_array($widget_options) ) {
				foreach ( $widget_options as $option ) {
					if ( is_array($option) ) {
						foreach ( $option as $key => $value ) {
							if ( is_string($value) && strlen($value) > 5 ) {
								$content[] = $key . ": " . $value;
							}
						}
					}
				}
			}
		}

		$prepared_content = $this->prepare_content(implode("\n", $content));
		if ( empty($prepared_content) ) {
			return;
		}

		$this->store_content('widget', crc32($widget_id), $prepared_content, '');
	}

	/**
	 * Store content in the database.
	 *
	 * @param string $object_type Type of object being indexed.
	 * @param mixed  $object_id   ID of the object.
	 * @param string $content     Prepared content.
	 * @param string $url         URL of the content.
	 * @return void
	 */
	private function store_content( $object_type, $object_id, $content, $url, $title = '' ) {
		global $wpdb;
		$tables = $this->database->get_tables();
		$content_index_table = $tables['content_index'];

		// Extract title from content if not provided
		if ( empty( $title ) ) {
			$lines = explode( "\n", $content );
			$title = ! empty( $lines[0] ) ? substr( $lines[0], 0, 255 ) : $object_type . ' #' . $object_id;
		}

		$result = $wpdb->replace(
			$content_index_table,
			array(
				'object_type' => $object_type,
				'object_id' => $object_id,
				'content' => $content,
				'title' => $title,
				'url' => $url,
				'updated_at' => current_time('mysql'),
			),
			array( '%s', '%s', '%s', '%s', '%s', '%s' )
		);
		
		// Log if replace failed
		if ( $result === false ) {
			// error_log("AskAny: Failed to store content - Type: $object_type, ID: $object_id, Error: " . $wpdb->last_error);
			return;
		}

		// Generate embeddings if RAG is enabled
		$this->generate_embeddings_for_content( $object_type, $object_id, $content, $url, $title );
	}

	/**
	 * Generate embeddings for content when RAG is enabled
	 */
	private function generate_embeddings_for_content( $object_type, $object_id, $content, $url, $title ) {
		// Check if RAG is enabled
		$rag_enabled = get_option( 'askany_rag_enabled', false );
		
		if ( ! $rag_enabled ) {
			return;
		}

		// Get content_id from database
		global $wpdb;
		$tables = $this->database->get_tables();
		$content_index_table = $tables['content_index'];
		
		$content_id = $wpdb->get_var( $wpdb->prepare(
			"SELECT id FROM {$content_index_table} WHERE object_type = %s AND object_id = %s",
			$object_type,
			$object_id
		) );

		if ( ! $content_id ) {
			return;
		}

		// Get API manager instance
		$api_manager = new ApiManager();
		
		// Initialize embedding manager
		$embedding_manager = new Embedding_Manager( $this->database, $api_manager );
		
		// Generate embeddings (handles chunking automatically)
		$result = $embedding_manager->generate_content_embeddings(
			$content_id,
			$object_type,
			$content,
			array(
				'source_url' => $url,
				'title' => $title,
				'excerpt' => substr( wp_strip_all_tags( $content ), 0, 500 ),
			)
		);
		
		if ( is_wp_error( $result ) ) {
			$error_message = $result->get_error_message();
			
			// Don't log quota errors since we show them in the UI
			$is_quota_error = stripos($error_message, 'quota') !== false || 
			                  stripos($error_message, 'rate limit') !== false;
			
			if (!$is_quota_error) {
				// error_log( 'AskAny: Failed to generate embeddings for ' . $object_type . ' ' . $object_id . ': ' . $error_message );
			}
		}
	}

	/**
	 * Prepare content for indexing.
	 *
	 * This method prepares the content by removing HTML tags, shortcodes,
	 * and extra whitespace.
	 *
	 * @param string $content Content to prepare.
	 * @return string Prepared content.
	 */
	private function prepare_content( $content ) {
		// Extract Elementor content if present
		$content = $this->extract_elementor_content( $content );
		
		// Extract Gutenberg blocks content if present
		$content = $this->extract_gutenberg_content( $content );
		
		// Remove HTML tags.
		$content = wp_strip_all_tags($content);

		// Remove shortcodes.
		$content = strip_shortcodes($content);

		// Remove extra whitespace.
		$content = preg_replace('/\s+/', ' ', $content);

		// Trim content.
		$content = trim($content);

		return $content;
	}
	
	/**
	 * Extract content from Elementor data
	 *
	 * @param string $content Post content
	 * @return string Enhanced content with Elementor data
	 */
	private function extract_elementor_content( $content ) {
		global $post;
		
		// Check if Elementor is active and this post uses Elementor
		if ( ! class_exists( '\Elementor\Plugin' ) ) {
			return $content;
		}
		
		// Get current post ID from global or try to extract from context
		$post_id = $post ? $post->ID : 0;
		
		if ( ! $post_id ) {
			return $content;
		}
		
		// Check if this page is built with Elementor
		$elementor_data = get_post_meta( $post_id, '_elementor_data', true );
		
		if ( empty( $elementor_data ) ) {
			return $content;
		}
		
		// Decode Elementor JSON data
		$elementor_content = json_decode( $elementor_data, true );
		
		if ( ! is_array( $elementor_content ) ) {
			return $content;
		}
		
		// Extract text content from Elementor elements
		$extracted_text = $this->parse_elementor_elements( $elementor_content );
		
		// Combine original content with Elementor content
		if ( ! empty( $extracted_text ) ) {
			$content .= "\n\n" . $extracted_text;
		}
		
		return $content;
	}
	
	/**
	 * Recursively parse Elementor elements to extract text
	 *
	 * @param array $elements Elementor elements array
	 * @return string Extracted text content
	 */
	private function parse_elementor_elements( $elements ) {
		$text_content = array();
		
		foreach ( $elements as $element ) {
			// Extract widget content
			if ( isset( $element['widgetType'] ) ) {
				$widget_type = $element['widgetType'];
				$settings = isset( $element['settings'] ) ? $element['settings'] : array();
				
				// Extract text from common widgets
				switch ( $widget_type ) {
					case 'heading':
						if ( ! empty( $settings['title'] ) ) {
							$text_content[] = $settings['title'];
						}
						break;
						
					case 'text-editor':
						if ( ! empty( $settings['editor'] ) ) {
							$text_content[] = wp_strip_all_tags( $settings['editor'] );
						}
						break;
						
					case 'button':
						if ( ! empty( $settings['text'] ) ) {
							$text_content[] = $settings['text'];
						}
						break;
						
					case 'image':
						if ( ! empty( $settings['caption'] ) ) {
							$text_content[] = $settings['caption'];
						}
						if ( ! empty( $settings['alt_text'] ) ) {
							$text_content[] = $settings['alt_text'];
						}
						break;
						
					case 'icon-box':
						if ( ! empty( $settings['title_text'] ) ) {
							$text_content[] = $settings['title_text'];
						}
						if ( ! empty( $settings['description_text'] ) ) {
							$text_content[] = wp_strip_all_tags( $settings['description_text'] );
						}
						break;
						
					case 'testimonial':
						if ( ! empty( $settings['testimonial_content'] ) ) {
							$text_content[] = wp_strip_all_tags( $settings['testimonial_content'] );
						}
						if ( ! empty( $settings['testimonial_name'] ) ) {
							$text_content[] = $settings['testimonial_name'];
						}
						break;
						
					case 'accordion':
					case 'toggle':
						if ( ! empty( $settings['tabs'] ) && is_array( $settings['tabs'] ) ) {
							foreach ( $settings['tabs'] as $tab ) {
								if ( ! empty( $tab['tab_title'] ) ) {
									$text_content[] = $tab['tab_title'];
								}
								if ( ! empty( $tab['tab_content'] ) ) {
									$text_content[] = wp_strip_all_tags( $tab['tab_content'] );
								}
							}
						}
						break;
						
					case 'pricing-table':
						if ( ! empty( $settings['heading'] ) ) {
							$text_content[] = $settings['heading'];
						}
						if ( ! empty( $settings['sub_heading'] ) ) {
							$text_content[] = $settings['sub_heading'];
						}
						if ( ! empty( $settings['price'] ) ) {
							$text_content[] = 'Price: ' . $settings['price'];
						}
						if ( ! empty( $settings['features_list'] ) && is_array( $settings['features_list'] ) ) {
							foreach ( $settings['features_list'] as $feature ) {
								if ( ! empty( $feature['item_text'] ) ) {
									$text_content[] = wp_strip_all_tags( $feature['item_text'] );
								}
							}
						}
						break;
				}
			}
			
			// Recursively parse child elements
			if ( ! empty( $element['elements'] ) && is_array( $element['elements'] ) ) {
				$child_content = $this->parse_elementor_elements( $element['elements'] );
				if ( ! empty( $child_content ) ) {
					$text_content[] = $child_content;
				}
			}
		}
		
		return implode( "\n", $text_content );
	}
	
	/**
	 * Extract content from Gutenberg blocks
	 *
	 * @param string $content Post content with Gutenberg blocks
	 * @return string Enhanced content with block data extracted
	 */
	private function extract_gutenberg_content( $content ) {
		// Check if content has Gutenberg blocks
		if ( ! has_blocks( $content ) ) {
			return $content;
		}
		
		// Parse blocks
		$blocks = parse_blocks( $content );
		
		if ( empty( $blocks ) ) {
			return $content;
		}
		
		// Extract text from blocks
		$extracted_text = $this->parse_gutenberg_blocks( $blocks );
		
		// Combine original content with extracted block content
		if ( ! empty( $extracted_text ) ) {
			$content .= "\n\n" . $extracted_text;
		}
		
		return $content;
	}
	
	/**
	 * Recursively parse Gutenberg blocks to extract text
	 *
	 * @param array $blocks Gutenberg blocks array
	 * @return string Extracted text content
	 */
	private function parse_gutenberg_blocks( $blocks ) {
		$text_content = array();
		
		foreach ( $blocks as $block ) {
			// Skip empty blocks
			if ( empty( $block['blockName'] ) ) {
				continue;
			}
			
			$block_name = $block['blockName'];
			$attrs = isset( $block['attrs'] ) ? $block['attrs'] : array();
			
			// Extract content based on block type
			switch ( $block_name ) {
				case 'core/paragraph':
				case 'core/heading':
				case 'core/quote':
				case 'core/verse':
				case 'core/preformatted':
					if ( ! empty( $block['innerHTML'] ) ) {
						$text_content[] = wp_strip_all_tags( $block['innerHTML'] );
					}
					break;
					
				case 'core/list':
					if ( ! empty( $block['innerHTML'] ) ) {
						$text_content[] = wp_strip_all_tags( $block['innerHTML'] );
					}
					break;
					
				case 'core/image':
				case 'core/cover':
					if ( ! empty( $attrs['alt'] ) ) {
						$text_content[] = $attrs['alt'];
					}
					if ( ! empty( $attrs['caption'] ) ) {
						$text_content[] = $attrs['caption'];
					}
					break;
					
				case 'core/button':
					if ( ! empty( $block['innerHTML'] ) ) {
						$text_content[] = wp_strip_all_tags( $block['innerHTML'] );
					}
					break;
					
				case 'core/columns':
				case 'core/column':
				case 'core/group':
					// These are container blocks, process inner blocks
					break;
					
				case 'core/table':
					if ( ! empty( $block['innerHTML'] ) ) {
						$text_content[] = wp_strip_all_tags( $block['innerHTML'] );
					}
					break;
			}
			
			// Recursively parse inner blocks
			if ( ! empty( $block['innerBlocks'] ) && is_array( $block['innerBlocks'] ) ) {
				$inner_content = $this->parse_gutenberg_blocks( $block['innerBlocks'] );
				if ( ! empty( $inner_content ) ) {
					$text_content[] = $inner_content;
				}
			}
		}
		
		return implode( "\n", $text_content );
	}
	
	/**
	 * Index WooCommerce store configuration.
	 *
	 * This method indexes store settings like shipping methods, payment gateways,
	 * and store policies to help AI answer customer support questions.
	 *
	 * @return void
	 */
	private function index_store_configuration() {
		if ( ! class_exists('WooCommerce') ) {
			return;
		}
		
		$content = array();
		
		// Index shipping zones and methods
		if ( class_exists('WC_Shipping_Zones') ) {
			$shipping_zones = \WC_Shipping_Zones::get_zones();
			if ( ! empty($shipping_zones) ) {
				$content[] = "=== SHIPPING INFORMATION ===";
				foreach ( $shipping_zones as $zone ) {
					$zone_obj = new \WC_Shipping_Zone($zone['id']);
					$content[] = "Shipping Zone: " . $zone_obj->get_zone_name();
					$content[] = "Zone Locations: " . implode(', ', array_column($zone['zone_locations'], 'code'));
					
					$shipping_methods = $zone_obj->get_shipping_methods(true);
					foreach ( $shipping_methods as $method ) {
						$content[] = "Shipping Method: " . $method->get_title();
						if ( $method->get_method_description() ) {
							$content[] = "Description: " . $method->get_method_description();
						}
					}
				}
				
				// Worldwide shipping (zone 0)
				$zone_0 = new \WC_Shipping_Zone(0);
				$methods_0 = $zone_0->get_shipping_methods(true);
				if ( ! empty($methods_0) ) {
					$content[] = "Worldwide Shipping Methods:";
					foreach ( $methods_0 as $method ) {
						$content[] = "- " . $method->get_title();
					}
				}
			}
		}
		
		// Index payment gateways (names only, no credentials)
		$payment_gateways = WC()->payment_gateways->get_available_payment_gateways();
		if ( ! empty($payment_gateways) ) {
			$content[] = "\n=== PAYMENT METHODS ===";
			foreach ( $payment_gateways as $gateway ) {
				$content[] = "Payment Method: " . $gateway->get_title();
				if ( $gateway->get_description() ) {
					$content[] = "Description: " . $gateway->get_description();
				}
			}
		}
		
		// Index store policies from WooCommerce settings
		$policy_pages = array(
			'woocommerce_terms_page_id' => 'Terms and Conditions',
			'woocommerce_privacy_page_id' => 'Privacy Policy',
			'wp_page_for_privacy_policy' => 'Privacy Policy',
		);
		
		$content[] = "\n=== STORE POLICIES ===";
		foreach ( $policy_pages as $option_key => $label ) {
			$page_id = get_option($option_key);
			if ( $page_id ) {
				$page = get_post($page_id);
				if ( $page && $page->post_status === 'publish' ) {
					$content[] = $label . ": " . $page->post_title;
					$content[] = strip_tags($page->post_content);
				}
			}
		}
		
		// Index common store pages
		$store_pages = array(
			'woocommerce_shop_page_id' => 'Shop Page',
			'woocommerce_cart_page_id' => 'Cart Page',
			'woocommerce_checkout_page_id' => 'Checkout Page',
			'woocommerce_myaccount_page_id' => 'My Account Page',
		);
		
		$content[] = "\n=== STORE PAGES ===";
		foreach ( $store_pages as $option_key => $label ) {
			$page_id = get_option($option_key);
			if ( $page_id ) {
				$page = get_post($page_id);
				if ( $page ) {
					$content[] = $label . ": " . get_permalink($page_id);
				}
			}
		}
		
		// Index currency and store location
		$content[] = "\n=== STORE SETTINGS ===";
		$content[] = "Currency: " . get_woocommerce_currency();
		$content[] = "Currency Symbol: " . get_woocommerce_currency_symbol();
		$content[] = "Store Country: " . WC()->countries->get_base_country();
		$content[] = "Store Address: " . WC()->countries->get_base_address();
		$content[] = "Store City: " . WC()->countries->get_base_city();
		$content[] = "Store Postcode: " . WC()->countries->get_base_postcode();
		
		// Index tax settings
		$content[] = "\n=== TAX SETTINGS ===";
		$content[] = "Prices include tax: " . (wc_prices_include_tax() ? 'Yes' : 'No');
		$content[] = "Calculate tax based on: " . get_option('woocommerce_tax_based_on');
		$content[] = "Display prices in shop: " . get_option('woocommerce_tax_display_shop');
		$content[] = "Display prices in cart: " . get_option('woocommerce_tax_display_cart');
		
		// Index order statuses
		$order_statuses = wc_get_order_statuses();
		$content[] = "\n=== ORDER STATUSES ===";
		foreach ( $order_statuses as $status_key => $status_label ) {
			$content[] = "Order Status: " . $status_label . " (" . $status_key . ")";
		}
		
		$prepared_content = $this->prepare_content(implode("\n", $content));
		if ( ! empty($prepared_content) ) {
			$this->store_content('store_config', 1, $prepared_content, get_home_url(), 'Store Configuration');
		}
	}
	
	/**
	 * Index FAQ data for AI understanding.
	 *
	 * This method indexes all FAQ questions and answers so the AI can understand
	 * and match user queries with appropriate FAQ responses intelligently.
	 *
	 * @return void
	 */
	private function index_faqs() {
		global $wpdb;
		$tables = $this->database->get_tables();
		
		// Index both home FAQs and Q&A pairs
		$this->index_home_faqs();
		$this->index_qa_pairs();
	}
	
	/**
	 * Index home page FAQs.
	 *
	 * @return void
	 */
	private function index_home_faqs() {
		global $wpdb;
		$tables = $this->database->get_tables();
		$faqs_table = $tables['home_faqs'];
		
		// Check if table exists first
		if ( $wpdb->get_var("SHOW TABLES LIKE '$faqs_table'") !== $faqs_table ) {
			// error_log("AskAny: Home FAQ table does not exist: $faqs_table");
			return;
		}
		
		// Get all FAQs from database (including inactive ones for indexing)
		$faqs = $wpdb->get_results("SELECT * FROM $faqs_table ORDER BY id ASC");
		
		if ( empty($faqs) ) {
			// error_log("AskAny: No home FAQs found in table $faqs_table");
			return;
		}
		
		
		$content = array();
		$content[] = "=== HOME PAGE FREQUENTLY ASKED QUESTIONS ===";
		$content[] = "This section contains home page FAQ questions and answers for intelligent matching.";
		$content[] = "";
		
		foreach ( $faqs as $faq ) {
			$content[] = "--- FAQ ITEM ---";
			$content[] = "Question: " . $faq->question;
			$content[] = "Answer: " . $faq->answer;
			$content[] = "Category: Home FAQ";
			$content[] = "Type: Frequently Asked Question";
			$content[] = "";
			
			// Also index each FAQ individually for better matching
			$individual_content = array(
				"=== FAQ ITEM ===",
				"Question: " . $faq->question,
				"Answer: " . $faq->answer,
				"FAQ Category: Home Page",
				"Content Type: FAQ",
			);
			
			$prepared_individual = $this->prepare_content(implode("\n", $individual_content));
			if ( ! empty($prepared_individual) ) {
				$this->store_content('faq', $faq->id, $prepared_individual, '', 'FAQ: ' . $faq->question);
			} 
			
		}
		
		// Store all home FAQs together for context
		$prepared_content = $this->prepare_content(implode("\n", $content));
		if ( ! empty($prepared_content) ) {
			$this->store_content('faq_collection', 1, $prepared_content, '', 'Home FAQs Collection');
		} 
		
	}
	
	/**
	 * Index Q&A pairs from Q&A Management.
	 *
	 * @return void
	 */
	private function index_qa_pairs() {
		global $wpdb;
		$tables = $this->database->get_tables();
		$qa_table = $tables['qa_pairs'];
		
		// Check if table exists first
		if ( $wpdb->get_var("SHOW TABLES LIKE '$qa_table'") !== $qa_table ) {
			// error_log("AskAny: Q&A pairs table does not exist: $qa_table");
			return;
		}
		
		// Get all active Q&A pairs from database
		$qa_pairs = $wpdb->get_results("SELECT * FROM $qa_table WHERE status = 'active' ORDER BY id ASC");
		
	
		if ( empty($qa_pairs) ) {
			// error_log("AskAny: No Q&A pairs found in table $qa_table");
			return;
		}
		
		
		$content = array();
		$content[] = "=== Q&A KNOWLEDGE BASE ===";
		$content[] = "This section contains Q&A pairs from the knowledge base for intelligent matching.";
		$content[] = "";
		
		foreach ( $qa_pairs as $qa ) {
			$content[] = "--- Q&A ITEM ---";
			$content[] = "Question: " . $qa->question;
			$content[] = "Answer: " . $qa->answer;
			$content[] = "Category: Q&A Knowledge Base";
			$content[] = "Type: Question and Answer";
			$content[] = "";
			
			// Also index each Q&A individually for better matching
			$individual_content = array(
				"=== Q&A ITEM ===",
				"Question: " . $qa->question,
				"Answer: " . $qa->answer,
				"Q&A Category: Knowledge Base",
				"Content Type: Q&A",
			);
			
			$prepared_individual = $this->prepare_content(implode("\n", $individual_content));
			if ( ! empty($prepared_individual) ) {
				// Use 'qa' prefix to differentiate from 'faq'
				$this->store_content('qa', $qa->id, $prepared_individual, '', 'Q&A: ' . $qa->question);
			} 
		}
		
		// Store all Q&A pairs together for context
		$prepared_content = $this->prepare_content(implode("\n", $content));
		if ( ! empty($prepared_content) ) {
			$this->store_content('qa_collection', 1, $prepared_content, '', 'All Q&A Pairs Collection');
			
		} 
	}
	
	/**
	 * Index PDF content for AI understanding.
	 *
	 * This method indexes all uploaded PDF content so the AI can reference
	 * document information when answering user queries.
	 *
	 * @return void
	 */
	private function index_pdfs() {
		global $wpdb;
		$tables = $this->database->get_tables();
		$pdf_table = $tables['pdf_index'];
		
		// Check if table exists first
		if ( $wpdb->get_var("SHOW TABLES LIKE '$pdf_table'") !== $pdf_table ) {
			// error_log("AskAny: PDF table does not exist: $pdf_table");
			return;
		}
		
		// Get all PDF content from database
		$pdfs = $wpdb->get_results("SELECT * FROM $pdf_table ORDER BY id ASC");
		
		
		if ( empty($pdfs) ) {
			// error_log("AskAny: No PDFs found in table $pdf_table");
			return;
		}
		
		
		$content = array();
		$content[] = "=== PDF DOCUMENTS ===";
		$content[] = "This section contains content from uploaded PDF documents.";
		$content[] = "";
		
		foreach ( $pdfs as $pdf ) {
			$pdf_title = isset($pdf->title) ? $pdf->title : 'PDF Document';
			$pdf_filename = isset($pdf->file_name) ? $pdf->file_name : 'Unknown';
			
			$content[] = "--- PDF DOCUMENT ---";
			$content[] = "Document Title: " . $pdf_title;
			$content[] = "File Name: " . $pdf_filename;
			$content[] = "Content: " . $pdf->content;
			$content[] = "Document Type: PDF";
			$content[] = "Source: Uploaded Document";
			$content[] = "";
			
			// Also index each PDF individually
			$individual_content = array(
				"=== PDF DOCUMENT ===",
				"Document Title: " . $pdf_title,
				"File Name: " . $pdf_filename,
				"Content: " . $pdf->content,
				"Document Type: PDF Document",
				"Source: Uploaded PDF",
			);
			
			$prepared_individual = $this->prepare_content(implode("\n", $individual_content));
			if ( ! empty($prepared_individual) ) {
				$title = $pdf_title !== 'PDF Document' ? $pdf_title : ('PDF: ' . $pdf_filename);
				$this->store_content('pdf', $pdf->id, $prepared_individual, '', $title);
				
			} 
		}
		
		// Store all PDFs together for context
		$prepared_content = $this->prepare_content(implode("\n", $content));
		if ( ! empty($prepared_content) ) {
			$this->store_content('pdf_collection', 1, $prepared_content, '', 'All PDF Documents');
			
		} 
	}
	
	/**
	 * Index external sources for AI understanding.
	 *
	 * This method indexes all external source content so the AI can reference
	 * external information when answering user queries.
	 *
	 * @return void
	 */
	private function index_external_sources() {
		global $wpdb;
		$tables = $this->database->get_tables();
		$external_table = $tables['external_sources'];
		
		// Check if table exists
		$table_exists = $wpdb->get_var("SHOW TABLES LIKE '$external_table'") === $external_table;
		if ( ! $table_exists ) {
			// error_log("AskAny: External sources table does not exist: $external_table");
			return;
		}
		
		// Get all external sources from database
		$sources = $wpdb->get_results("SELECT * FROM $external_table ORDER BY id ASC");
		
		
		if ( empty($sources) ) {
			// error_log("AskAny: No external sources found in table $external_table");
			return;
		}
		
	
		$content = array();
		$content[] = "=== EXTERNAL SOURCES ===";
		$content[] = "This section contains content from external sources and integrations.";
		$content[] = "";
		
		foreach ( $sources as $source ) {
			$source_title = isset($source->title) ? $source->title : 'External Source';
			$source_url = isset($source->url) ? $source->url : 'No URL';
			$source_type = isset($source->type) ? $source->type : 'External';
			$source_content = isset($source->content) ? $source->content : '';
			
			$content[] = "--- EXTERNAL SOURCE ---";
			$content[] = "Source Title: " . $source_title;
			$content[] = "Source URL: " . $source_url;
			$content[] = "Source Type: " . $source_type;
			$content[] = "Content: " . $source_content;
			$content[] = "Source Category: External Integration";
			$content[] = "";
			
			// Also index each source individually
			$individual_content = array(
				"=== EXTERNAL SOURCE ===",
				"Source Title: " . $source_title,
				"Source URL: " . $source_url,
				"Source Type: " . $source_type,
				"Content: " . $source_content,
				"Category: External Source",
			);
			
			$prepared_individual = $this->prepare_content(implode("\n", $individual_content));
			if ( ! empty($prepared_individual) ) {
				$this->store_content('external_source', $source->id, $prepared_individual, $source_url !== 'No URL' ? $source_url : '', $source_title);
				
			} 
		}
		
		// Store all external sources together for context
		$prepared_content = $this->prepare_content(implode("\n", $content));
		if ( ! empty($prepared_content) ) {
			$this->store_content('external_collection', 1, $prepared_content, '', 'All External Sources');
		} 
	}
	
	/**
	 * Get indexed content by type for viewing.
	 *
	 * This method retrieves indexed content by object type for admin viewing.
	 *
	 * @param string $object_type The content type to retrieve.
	 * @param int $limit Optional limit for results.
	 * @param int $offset Optional offset for pagination.
	 * @return array Array of indexed content items.
	 */
	public function get_indexed_content_by_type( $object_type, $limit = 50, $offset = 0 ) {
		global $wpdb;
		$tables = $this->database->get_tables();
		$content_index_table = $tables['content_index'];
		
		$results = $wpdb->get_results($wpdb->prepare(
			"SELECT id, object_id, object_type, title, url, 
			LEFT(content, 200) as content_preview, 
			LENGTH(content) as content_length,
			created_at, updated_at 
			FROM $content_index_table 
			WHERE object_type = %s 
			ORDER BY updated_at DESC 
			LIMIT %d OFFSET %d",
			$object_type,
			$limit,
			$offset
		));
		
		return $results;
	}
	
	/**
	 * Get full indexed content item by ID.
	 *
	 * This method retrieves a complete indexed content item by its ID.
	 *
	 * @param int $content_id The content index ID.
	 * @return object|null The content item or null if not found.
	 */
	public function get_indexed_content_by_id( $content_id ) {
		global $wpdb;
		$tables = $this->database->get_tables();
		$content_index_table = $tables['content_index'];
		
		$result = $wpdb->get_row($wpdb->prepare(
			"SELECT * FROM $content_index_table WHERE id = %d",
			$content_id
		));
		
		return $result;
	}
	
	/**
	 * Get content type display names for admin interface.
	 *
	 * @return array Array of content type display names.
	 */
	public function get_content_type_labels() {
		return array(
			'post' => 'Blog Posts',
			'page' => 'Pages',
			'template_page' => 'Template Pages',
			'docs' => 'Documentation',
			'comment' => 'Comments',
			'product' => 'Products',
			'product_category' => 'Product Categories',
			'product_tag' => 'Product Tags',
			'custom_field' => 'Custom Fields',
			'menu' => 'Menus',
			'widget' => 'Widgets',
			'store_config' => 'Store Configuration',
			'faq' => 'Home FAQs',
			'faq_collection' => 'FAQ Collections',
			'qa' => 'Q&A Pairs',
			'qa_collection' => 'Q&A Collections',
			'pdf' => 'PDF Documents',
			'pdf_collection' => 'PDF Collections',
			'external_source' => 'External Sources',
			'external_collection' => 'External Collections',
		);
	}
}

