<?php
/**
 * AYSA SEO History AJAX Handlers
 * 
 * Handles all AJAX requests for SEO generation history functionality.
 * 
 * @package AYSA
 * @since 1.0.0
 */

if (!defined('ABSPATH')) {
    exit; // Exit if accessed directly
}

class Aysa_Seo_History_Ajax {
    
    /**
     * The SEO history manager instance
     * 
     * @var Aysa_Seo_History
     */
    private $seo_history;
    
    /**
     * Initialize the AJAX handlers
     */
    public function __construct() {
        aysa_debug_log('AYSA: Aysa_Seo_History_Ajax constructor called');
        $this->seo_history = aysa_get_seo_history();
        $this->init_hooks();
        aysa_debug_log('AYSA: Aysa_Seo_History_Ajax hooks initialized');
    }
    
    /**
     * Initialize WordPress hooks
     */
    private function init_hooks() {
        aysa_debug_log('AYSA: init_hooks() called');
        
        // AJAX handlers for logged-in users
        add_action('wp_ajax_aysa_log_seo_generation', array($this, 'ajax_log_seo_generation'));
        add_action('wp_ajax_aysa_log_seo_generation_batch', array($this, 'ajax_log_seo_generation_batch'));
        add_action('wp_ajax_aysa_update_history_status', array($this, 'ajax_update_history_status'));
        add_action('wp_ajax_aysa_get_entity_history', array($this, 'ajax_get_entity_history'));
        add_action('wp_ajax_aysa_get_recent_history', array($this, 'ajax_get_recent_history'));
        add_action('wp_ajax_aysa_search_history', array($this, 'ajax_search_history'));
        add_action('wp_ajax_aysa_get_history_statistics', array($this, 'ajax_get_history_statistics'));
        add_action('wp_ajax_aysa_seo_history_add_entry', array($this, 'ajax_seo_history_add_entry'));


        add_action('wp_ajax_aysa_seo_update_post_meta', array($this, 'aysa_seo_update_post_meta_handler'));
        add_action('wp_ajax_aysa_seo_update_product_meta', array($this, 'aysa_seo_update_product_meta_handler'));
        add_action('wp_ajax_aysa_seo_update_category_meta', array($this, 'aysa_seo_update_category_meta_handler'));
        add_action('wp_ajax_aysa_seo_update_product_category_meta', array($this, 'aysa_seo_update_product_category_meta_handler'));
        add_action('wp_head', array($this, 'aysa_seo_output_meta_tags'));
        add_action('wp_ajax_aysa_seo_update_generic_meta', array($this, 'aysa_seo_update_generic_meta_handler'));
        
        // Add test handler for meta save verification
        add_action('wp_ajax_aysa_test_meta_save', array($this, 'aysa_test_meta_save_handler'));
        
        // Add nonce to admin pages
        add_action('admin_head', array($this, 'add_history_nonce'));
        
        aysa_debug_log('AYSA: All hooks registered, including wp_head for aysa_seo_output_meta_tags');
    }
    
    /**
     * Add history nonce to admin pages
     */
    public function add_history_nonce() {
        $nonce = wp_create_nonce('aysa_history_action');
        echo '<meta name="aysa-history-nonce" content="' . esc_attr($nonce) . '">' . "\n";
        echo '<script>window.aysaHistoryNonce = "' . esc_js($nonce) . '";</script>' . "\n";
    }

    private function track_wallet_usage($action_key, $reference, $fallback_cost_cents, $meta = array(), $endpoint = '') {
        if (!function_exists('aysa_get_wallet_manager')) {
            return;
        }

        $project_id = max(0, intval(get_option('aysa_project_id', 0)));
        if ($project_id <= 0) {
            return;
        }

        $wallet_manager = aysa_get_wallet_manager();
        if (!$wallet_manager || !method_exists($wallet_manager, 'track_action_usage')) {
            return;
        }

        $wallet_manager->track_action_usage($project_id, $action_key, $reference, array(
            'meta' => is_array($meta) ? $meta : array(),
            'fallback_cost_cents' => max(0, intval($fallback_cost_cents)),
            'endpoint' => $endpoint,
            'billing_authority' => 'plugin_wallet',
        ));
    }
    
    function aysa_seo_update_post_meta_handler() {
        aysa_debug_log('🔧 [DEBUG] aysa_seo_update_post_meta_handler called');
        // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Reviewed callback inventory: this request read is downstream of the handler nonce and capability guard, a shared guarded delegate, or the authenticated WordPress core save/query flow.
        aysa_debug_log('📦 [DEBUG] POST keys: ' . implode(',', array_keys($_POST)));
        aysa_debug_log('🌐 [DEBUG] Request method: ' . (isset($_SERVER['REQUEST_METHOD']) ? sanitize_text_field((string) wp_unslash($_SERVER['REQUEST_METHOD'])) : 'unknown'));
        
        try {
            // Check if nonce exists
            if (!isset($_POST['nonce'])) {
                aysa_debug_log('❌ [ERROR] Nonce missing from request');
                wp_send_json_error(['message' => 'Nonce missing']);
                return;
            }
            
            $provided_nonce = sanitize_text_field((string) wp_unslash($_POST['nonce']));
            
            // Verify nonce - try different nonce names
            $nonce_valid = false;
            $nonce_names = ['aysa_history_action', 'aysa_seo_nonce', 'aysa_seo_history_nonce', 'nonce'];
            
            foreach ($nonce_names as $nonce_name) {
                if (wp_verify_nonce($provided_nonce, $nonce_name)) {
                    $nonce_valid = true;
                    aysa_debug_log('✅ [DEBUG] Nonce verified with action: ' . $nonce_name);
                    break;
                }
            }
            
            if (!$nonce_valid) {
                aysa_debug_log('❌ [ERROR] Nonce verification failed for all attempted actions');
                aysa_debug_log('🔑 [DEBUG] Tried nonce actions: ' . implode(', ', $nonce_names));
                wp_send_json_error(['message' => 'Security check failed']);
                return;
            }
            
            // Check permissions
            $can_edit_posts = current_user_can('edit_posts');
            $can_edit_pages = current_user_can('edit_pages');
            aysa_debug_log('👤 [DEBUG] User permissions - edit_posts: ' . ($can_edit_posts ? 'YES' : 'NO') . ', edit_pages: ' . ($can_edit_pages ? 'YES' : 'NO'));
            aysa_debug_log('👤 [DEBUG] Current user ID: ' . get_current_user_id());
            
            if (!$can_edit_posts && !$can_edit_pages) {
                aysa_debug_log('❌ [ERROR] User lacks required permissions');
                wp_send_json_error(['message' => 'Insufficient permissions']);
                return;
            }
            
            // Validate and sanitize input
            // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reviewed release input boundary: the guarded callback preserves structured input only until its field-specific validation or normalizer, before persistence, output, SQL, or a broker request.
            $raw_entity_id = isset($_POST['entity_id']) ? (string) wp_unslash($_POST['entity_id']) : '';
            if ($raw_entity_id === '' || !is_numeric($raw_entity_id)) {
                aysa_debug_log('❌ [ERROR] Invalid entity ID provided');
                wp_send_json_error(['message' => 'Invalid entity ID']);
                return;
            }
            
            $entity_id = intval($raw_entity_id);
            if (!current_user_can('edit_post', $entity_id)) {
                wp_send_json_error(['message' => 'Post permission denied'], 403);
                return;
            }
            $meta_title = isset($_POST['meta_title']) ? sanitize_text_field((string) wp_unslash($_POST['meta_title'])) : '';
            $meta_description = isset($_POST['meta_description']) ? sanitize_textarea_field((string) wp_unslash($_POST['meta_description'])) : '';
            $meta_keywords = isset($_POST['meta_keywords']) ? sanitize_text_field((string) wp_unslash($_POST['meta_keywords'])) : '';
            $entity_type = isset($_POST['entity_type']) ? sanitize_text_field((string) wp_unslash($_POST['entity_type'])) : 'not set';
            
            aysa_debug_log('📋 [DEBUG] Sanitized input data:');
            aysa_debug_log('  - Entity ID: ' . $entity_id);
            aysa_debug_log('  - Entity Type: ' . $entity_type);
            aysa_debug_log('  - Meta Title: ' . $meta_title);
            aysa_debug_log('  - Meta Description: ' . $meta_description);
            aysa_debug_log('  - Meta Keywords: ' . $meta_keywords);
            
            // Check if post exists
            $post = get_post($entity_id);
            if (!$post) {
                aysa_debug_log('❌ [ERROR] Post not found for ID: ' . $entity_id);
                wp_send_json_error(['message' => 'Post not found for ID: ' . $entity_id]);
                return;
            }
            
            aysa_debug_log('✅ [DEBUG] Post found: ' . $post->post_title . ' (ID: ' . $entity_id . ', Type: ' . $post->post_type . ')');
            
            // Update post meta
            aysa_debug_log('🚀 [DEBUG] Starting meta field updates...');
            $results = [];
            
            if ($meta_title) {
                // Save to our custom field
                $result = update_post_meta($entity_id, '_aysa_seo_title', $meta_title);
                $results['title'] = $result;
                aysa_debug_log('📝 [DEBUG] Updated _aysa_seo_title: ' . ($result ? 'SUCCESS' : 'FAILED') . ' (Result: ' . aysa_debug_export($result, true) . ')');
                
                // Also save to standard WordPress meta fields for immediate display
                update_post_meta($entity_id, '_aysa_meta_title', $meta_title);
                aysa_debug_log('📝 [DEBUG] Updated _aysa_meta_title: SUCCESS');
            }
            
            if ($meta_description) {
                // Save to our custom field
                $result = update_post_meta($entity_id, '_aysa_seo_description', $meta_description);
                $results['description'] = $result;
                aysa_debug_log('📝 [DEBUG] Updated _aysa_seo_description: ' . ($result ? 'SUCCESS' : 'FAILED') . ' (Result: ' . aysa_debug_export($result, true) . ')');
                
                // Also save to standard WordPress meta fields for immediate display
                update_post_meta($entity_id, '_aysa_meta_description', $meta_description);
                aysa_debug_log('📝 [DEBUG] Updated _aysa_meta_description: SUCCESS');
            }
            
            if ($meta_keywords) {
                // Save to our custom field
                $result = update_post_meta($entity_id, '_aysa_seo_keywords', $meta_keywords);
                $results['keywords'] = $result;
                aysa_debug_log('📝 [DEBUG] Updated _aysa_seo_keywords: ' . ($result ? 'SUCCESS' : 'FAILED') . ' (Result: ' . aysa_debug_export($result, true) . ')');
                
                // Also save to standard WordPress meta fields for immediate display
                update_post_meta($entity_id, '_aysa_meta_keywords', $meta_keywords);
                aysa_debug_log('📝 [DEBUG] Updated _aysa_meta_keywords: SUCCESS');
            }
            
            // Update Yoast fields if plugin is active
            $yoast_active = function_exists('is_plugin_active') && is_plugin_active('wordpress-seo/wp-seo.php');
            aysa_debug_log('🔌 [DEBUG] Yoast SEO plugin active: ' . ($yoast_active ? 'YES' : 'NO'));
            
            if ($yoast_active) {
                if ($meta_title) {
                    $result = update_post_meta($entity_id, '_yoast_wpseo_title', $meta_title);
                    aysa_debug_log('📝 [DEBUG] Updated _yoast_wpseo_title: ' . ($result ? 'SUCCESS' : 'FAILED'));
                }
                if ($meta_description) {
                    $result = update_post_meta($entity_id, '_yoast_wpseo_metadesc', $meta_description);
                    aysa_debug_log('📝 [DEBUG] Updated _yoast_wpseo_metadesc: ' . ($result ? 'SUCCESS' : 'FAILED'));
                }
                if ($meta_keywords) {
                    $result = update_post_meta($entity_id, '_yoast_wpseo_focuskw', $meta_keywords);
                    aysa_debug_log('📝 [DEBUG] Updated _yoast_wpseo_focuskw: ' . ($result ? 'SUCCESS' : 'FAILED'));
                }
            }
            
            // Update RankMath fields if plugin is active
            $rankmath_active = function_exists('is_plugin_active') && is_plugin_active('seo-by-rank-math/rank-math.php');
            aysa_debug_log('🔌 [DEBUG] RankMath SEO plugin active: ' . ($rankmath_active ? 'YES' : 'NO'));
            
            if ($rankmath_active) {
                if ($meta_title) {
                    $result = update_post_meta($entity_id, 'rank_math_title', $meta_title);
                    aysa_debug_log('📝 [DEBUG] Updated rank_math_title: ' . ($result ? 'SUCCESS' : 'FAILED'));
                }
                if ($meta_description) {
                    $result = update_post_meta($entity_id, 'rank_math_description', $meta_description);
                    aysa_debug_log('📝 [DEBUG] Updated rank_math_description: ' . ($result ? 'SUCCESS' : 'FAILED'));
                }
                if ($meta_keywords) {
                    $result = update_post_meta($entity_id, 'rank_math_focus_keyword', $meta_keywords);
                    aysa_debug_log('📝 [DEBUG] Updated rank_math_focus_keyword: ' . ($result ? 'SUCCESS' : 'FAILED'));
                }
            }
            
            // Verify the meta was actually saved by reading it back
            aysa_debug_log('🔍 [DEBUG] Verifying saved meta data...');
            $saved_title = get_post_meta($entity_id, '_aysa_seo_title', true);
            $saved_description = get_post_meta($entity_id, '_aysa_seo_description', true);
            $saved_keywords = get_post_meta($entity_id, '_aysa_seo_keywords', true);
            
            aysa_debug_log('📊 [DEBUG] Verification results:');
            aysa_debug_log('  - Saved title: ' . $saved_title);
            aysa_debug_log('  - Saved description: ' . $saved_description);
            aysa_debug_log('  - Saved keywords: ' . $saved_keywords);
            
            aysa_debug_log('🎉 [SUCCESS] SEO meta update completed successfully');
            $this->track_wallet_usage(
                'aysa_seo_update_post_meta',
                'seo_update_post_meta',
                5,
                array(
                    'module' => 'on_page_optimization',
                    'entity_id' => intval($entity_id),
                    'entity_type' => 'post',
                ),
                '/v1/onpage/seo-update-post-meta'
            );
            
            wp_send_json_success([
                'message' => 'SEO meta updated successfully',
                'entity_id' => $entity_id,
                'updated_fields' => array_keys(array_filter($results)),
                'meta_data' => [
                    'title' => $meta_title,
                    'description' => $meta_description,
                    'keywords' => $meta_keywords
                ],
                'verification' => [
                    'saved_title' => $saved_title,
                    'saved_description' => $saved_description,
                    'saved_keywords' => $saved_keywords
                ]
            ]);
            
        } catch (Exception $e) {
            aysa_debug_log('💥 [FATAL ERROR] Exception in aysa_seo_update_post_meta_handler: ' . $e->getMessage());
            aysa_debug_log('📊 [ERROR] Exception trace: ' . $e->getTraceAsString());
            wp_send_json_error(['message' => 'Server error: ' . $e->getMessage()]);
        }
    }
    
    function aysa_seo_update_category_meta_handler() {
        try {
            // Log the request for debugging
            // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Reviewed callback inventory: this request read is downstream of the handler nonce and capability guard, a shared guarded delegate, or the authenticated WordPress core save/query flow.
            aysa_debug_log('🔧 [DEBUG] Category SEO Update Request keys: ' . implode(',', array_keys($_POST)));
            
            // Check if nonce exists
            if (!isset($_POST['nonce'])) {
                wp_send_json_error(['message' => 'Nonce missing']);
                return;
            }
            
            $provided_nonce = sanitize_text_field((string) wp_unslash($_POST['nonce']));

            // Verify nonce - try different nonce names
            $nonce_valid = false;
            $nonce_names = ['aysa_history_action', 'aysa_seo_nonce', 'aysa_seo_history_nonce', 'nonce'];
            
            foreach ($nonce_names as $nonce_name) {
                if (wp_verify_nonce($provided_nonce, $nonce_name)) {
                    $nonce_valid = true;
                    break;
                }
            }
            
            if (!$nonce_valid) {
                aysa_debug_log('Category SEO - Nonce verification failed.');
                wp_send_json_error(['message' => 'Security check failed']);
                return;
            }
            
            // Check permissions
            if (!current_user_can('manage_categories')) {
                wp_send_json_error(['message' => 'Insufficient permissions']);
                return;
            }
            
            $entity_id = isset($_POST['entity_id']) ? intval((string) wp_unslash($_POST['entity_id'])) : 0;
            $meta_title = isset($_POST['meta_title']) ? sanitize_text_field((string) wp_unslash($_POST['meta_title'])) : '';
            $meta_description = isset($_POST['meta_description']) ? sanitize_textarea_field((string) wp_unslash($_POST['meta_description'])) : '';
            $meta_keywords = isset($_POST['meta_keywords']) ? sanitize_text_field((string) wp_unslash($_POST['meta_keywords'])) : '';
            
            // Category-specific fields
            $category_title = isset($_POST['category_title']) ? sanitize_text_field((string) wp_unslash($_POST['category_title'])) : '';
            $category_description = isset($_POST['category_description']) ? wp_kses_post((string) wp_unslash($_POST['category_description'])) : '';
            $category_permalink = isset($_POST['category_permalink']) ? sanitize_text_field((string) wp_unslash($_POST['category_permalink'])) : '';
            $secondary_keywords = isset($_POST['secondary_keywords']) ? sanitize_text_field((string) wp_unslash($_POST['secondary_keywords'])) : '';
            $entity_type = isset($_POST['entity_type']) ? sanitize_text_field((string) wp_unslash($_POST['entity_type'])) : 'not set';
            
            // Log the entity ID for debugging
            aysa_debug_log('Category SEO Update - Entity ID received: ' . $entity_id);
            aysa_debug_log('Category SEO Update - Entity Type: ' . $entity_type);
            
            // Check if category exists
            $term = get_term($entity_id);
            if (!$term || is_wp_error($term)) {
                aysa_debug_log('Category SEO Update - Category not found for ID: ' . $entity_id);
                wp_send_json_error(['message' => 'Category not found for ID: ' . $entity_id]);
                return;
            }
            if (!current_user_can('edit_term', $entity_id)) {
                wp_send_json_error(['message' => 'Term permission denied'], 403);
                return;
            }
            
            aysa_debug_log('Category SEO Update - Category found: ' . $term->name . ' (ID: ' . $entity_id . ')');
            
            // Update category meta
            $results = [];
            
            // Update SEO meta fields
            if ($meta_title) {
                $results['meta_title'] = update_term_meta($entity_id, '_aysa_seo_title', $meta_title);
            }
            
            if ($meta_description) {
                $results['meta_description'] = update_term_meta($entity_id, '_aysa_seo_description', $meta_description);
            }
            
            if ($meta_keywords) {
                $results['meta_keywords'] = update_term_meta($entity_id, '_aysa_seo_keywords', $meta_keywords);
            }
            
            // Update category-specific fields
            if ($category_title) {
                aysa_debug_log('📝 [DEBUG] Updating category title: ' . $category_title);
                $results['category_title'] = wp_update_term($entity_id, $term->taxonomy, [
                    'name' => $category_title
                ]);
                aysa_debug_log('📝 [DEBUG] Category title update result: ' . aysa_debug_export($results['category_title'], true));
            }
            
            if ($category_description) {
                aysa_debug_log('📝 [DEBUG] Updating category description: ' . substr($category_description, 0, 100) . '...');
                $results['category_description'] = wp_update_term($entity_id, $term->taxonomy, [
                    'description' => $category_description
                ]);
                aysa_debug_log('📝 [DEBUG] Category description update result: ' . aysa_debug_export($results['category_description'], true));
            }
            
            if ($category_permalink) {
                aysa_debug_log('📝 [DEBUG] Updating category permalink: ' . $category_permalink);
                $results['category_permalink'] = wp_update_term($entity_id, $term->taxonomy, [
                    'slug' => sanitize_title($category_permalink)
                ]);
                aysa_debug_log('📝 [DEBUG] Category permalink update result: ' . aysa_debug_export($results['category_permalink'], true));
            }
            
            if ($secondary_keywords) {
                aysa_debug_log('📝 [DEBUG] Updating secondary keywords: ' . $secondary_keywords);
                $results['secondary_keywords'] = update_term_meta($entity_id, '_aysa_secondary_keywords', $secondary_keywords);
                aysa_debug_log('📝 [DEBUG] Secondary keywords update result: ' . ($results['secondary_keywords'] ? 'SUCCESS' : 'FAILED'));
            }
            
            // Update SEO plugin fields for categories
            if (function_exists('is_plugin_active') && is_plugin_active('wordpress-seo/wp-seo.php')) {
                if ($meta_title) {
                    update_term_meta($entity_id, '_yoast_wpseo_title', $meta_title);
                }
                if ($meta_description) {
                    update_term_meta($entity_id, '_yoast_wpseo_desc', $meta_description);
                }
            }
            
            if (function_exists('is_plugin_active') && is_plugin_active('seo-by-rank-math/rank-math.php')) {
                if ($meta_title) {
                    update_term_meta($entity_id, 'rank_math_title', $meta_title);
                }
                if ($meta_description) {
                    update_term_meta($entity_id, 'rank_math_description', $meta_description);
                }
            }

            $this->track_wallet_usage(
                'aysa_seo_update_category_meta',
                'seo_update_category_meta',
                5,
                array(
                    'module' => 'on_page_optimization',
                    'entity_id' => intval($entity_id),
                    'entity_type' => 'category',
                ),
                '/v1/onpage/seo-update-category-meta'
            );
            
            wp_send_json_success([
                'message' => 'Category SEO meta updated successfully',
                'entity_id' => $entity_id,
                'updated_fields' => array_keys(array_filter($results)),
                'meta_data' => [
                    'title' => $meta_title,
                    'description' => $meta_description,
                    'keywords' => $meta_keywords,
                    'category_title' => $category_title,
                    'category_description' => $category_description,
                    'category_permalink' => $category_permalink,
                    'secondary_keywords' => $secondary_keywords
                ]
            ]);
            
        } catch (Exception $e) {
            aysa_debug_log('Category SEO Update Error: ' . $e->getMessage());
            wp_send_json_error(['message' => 'Server error: ' . $e->getMessage()]);
        }
    }
    
    function aysa_seo_update_product_meta_handler() {
        try {
            // Log the request for debugging
            // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Reviewed callback inventory: this request read is downstream of the handler nonce and capability guard, a shared guarded delegate, or the authenticated WordPress core save/query flow.
            aysa_debug_log('Product SEO Update Request keys: ' . implode(',', array_keys($_POST)));
            
            // Check if nonce exists
            if (!isset($_POST['nonce'])) {
                wp_send_json_error(['message' => 'Nonce missing']);
                return;
            }
            $provided_nonce = sanitize_text_field((string) wp_unslash($_POST['nonce']));
            
            // Verify nonce - try different nonce names
            $nonce_valid = false;
            $nonce_names = ['aysa_history_action', 'aysa_seo_nonce', 'aysa_seo_history_nonce', 'nonce'];
            
            foreach ($nonce_names as $nonce_name) {
                if (wp_verify_nonce($provided_nonce, $nonce_name)) {
                    $nonce_valid = true;
                    break;
                }
            }
            
            if (!$nonce_valid) {
                aysa_debug_log('Product SEO Update - Nonce verification failed.');
                wp_send_json_error(['message' => 'Security check failed']);
                return;
            }
            
            // Check permissions
            if (!current_user_can('edit_posts') && !current_user_can('edit_pages')) {
                wp_send_json_error(['message' => 'Insufficient permissions']);
                return;
            }
            
            // Validate and sanitize input
            // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reviewed release input boundary: the guarded callback preserves structured input only until its field-specific validation or normalizer, before persistence, output, SQL, or a broker request.
            $raw_entity_id = isset($_POST['entity_id']) ? (string) wp_unslash($_POST['entity_id']) : '';
            if ($raw_entity_id === '' || !is_numeric($raw_entity_id)) {
                wp_send_json_error(['message' => 'Invalid entity ID']);
                return;
            }
            
            $entity_id = intval($raw_entity_id);
            if (!current_user_can('edit_post', $entity_id)) {
                wp_send_json_error(['message' => 'Product permission denied'], 403);
                return;
            }
            $meta_title = isset($_POST['meta_title']) ? sanitize_text_field((string) wp_unslash($_POST['meta_title'])) : '';
            $meta_description = isset($_POST['meta_description']) ? sanitize_textarea_field((string) wp_unslash($_POST['meta_description'])) : '';
            $meta_keywords = isset($_POST['meta_keywords']) ? sanitize_text_field((string) wp_unslash($_POST['meta_keywords'])) : '';
            $short_description = isset($_POST['short_description']) ? sanitize_textarea_field((string) wp_unslash($_POST['short_description'])) : '';
            // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reviewed release input boundary: the guarded callback preserves structured input only until its field-specific validation or normalizer, before persistence, output, SQL, or a broker request.
            $product_description = isset($_POST['product_description']) ? $this->sanitize_product_description_html((string) wp_unslash($_POST['product_description'])) : '';
            $product_permalink = isset($_POST['product_permalink']) ? sanitize_title((string) wp_unslash($_POST['product_permalink'])) : '';
            $product_title = isset($_POST['product_title']) ? sanitize_text_field((string) wp_unslash($_POST['product_title'])) : '';
            $entity_type = isset($_POST['entity_type']) ? sanitize_text_field((string) wp_unslash($_POST['entity_type'])) : 'not set';
            
            // Log the entity ID for debugging
            aysa_debug_log('Product SEO Update - Entity ID received: ' . $entity_id);
            aysa_debug_log('Product SEO Update - Entity Type: ' . $entity_type);
            aysa_debug_log('Product SEO Update - Short Description: ' . $short_description);
            aysa_debug_log('Product SEO Update - Product Description length: ' . strlen($product_description));
            aysa_debug_log('Product SEO Update - Product Permalink: ' . $product_permalink);
            aysa_debug_log('Product SEO Update - Product Title: ' . $product_title);
            
            // Check if product exists
            $product = get_post($entity_id);
            if (!$product) {
                aysa_debug_log('Product SEO Update - Product not found for ID: ' . $entity_id);
                wp_send_json_error(['message' => 'Product not found for ID: ' . $entity_id]);
                return;
            }
            
            aysa_debug_log('Product SEO Update - Product found: ' . $product->post_title . ' (ID: ' . $entity_id . ')');
            
            // Update product meta
            $results = [];
            
            if ($meta_title) {
                $results['title'] = update_post_meta($entity_id, '_aysa_seo_title', $meta_title);
            }
            
            if ($meta_description) {
                $results['description'] = update_post_meta($entity_id, '_aysa_seo_description', $meta_description);
            }
            
            if ($meta_keywords) {
                $results['keywords'] = update_post_meta($entity_id, '_aysa_seo_keywords', $meta_keywords);
            }
            
            if ($product_title) {
                $results['product_title'] = update_post_meta($entity_id, '_aysa_seo_product_title', $product_title);
                
                // Update WordPress post title
                wp_update_post(array(
                    'ID' => $entity_id,
                    'post_title' => $product_title
                ));
                
                if (class_exists('WooCommerce')) {
                    update_post_meta($entity_id, '_product_title', $product_title);
                }
                aysa_debug_log('Product SEO Update - Updated product title: ' . $product_title);
            }
            
            if ($short_description) {
                $results['short_description'] = update_post_meta($entity_id, '_aysa_seo_short_description', $short_description);
                
                // Update WooCommerce product short description
                if (class_exists('WooCommerce')) {
                    // Update the post excerpt (WooCommerce uses this for short description)
                    wp_update_post(array(
                        'ID' => $entity_id,
                        'post_excerpt' => $short_description
                    ));
                    
                    // Also update the WooCommerce specific meta
                    update_post_meta($entity_id, '_product_short_description', $short_description);
                    aysa_debug_log('Product SEO Update - Updated WooCommerce short description: ' . $short_description);
                }
            }

            if ($product_description) {
                $results['product_description'] = update_post_meta($entity_id, '_aysa_seo_product_description', $product_description);
                
                // Update WordPress post content
                wp_update_post(array(
                    'ID' => $entity_id,
                    'post_content' => $product_description
                ));
                
                if (class_exists('WooCommerce')) {
                    update_post_meta($entity_id, '_product_description', $product_description);
                }
                aysa_debug_log('Product SEO Update - Updated product description: ' . substr($product_description, 0, 100) . '...');
            }

            if ($product_permalink) {
                $results['product_permalink'] = update_post_meta($entity_id, '_aysa_seo_product_permalink', $product_permalink);
                
                // Update WordPress post slug
                wp_update_post(array(
                    'ID' => $entity_id,
                    'post_name' => $product_permalink
                ));
                
                if (class_exists('WooCommerce')) {
                    update_post_meta($entity_id, '_product_slug', $product_permalink);
                }
                aysa_debug_log('Product SEO Update - Updated product permalink: ' . $product_permalink);
            }
            
            // Update WooCommerce product fields if WooCommerce is active
            if (class_exists('WooCommerce')) {
                if ($meta_title) {
                    update_post_meta($entity_id, '_yoast_wpseo_title', $meta_title);
                }
                if ($meta_description) {
                    update_post_meta($entity_id, '_yoast_wpseo_metadesc', $meta_description);
                }
                if ($meta_keywords) {
                    update_post_meta($entity_id, '_yoast_wpseo_focuskw', $meta_keywords);
                }
                if ($short_description) {
                    update_post_meta($entity_id, '_short_description', $short_description);
                }
            }
            
            // Update Yoast fields if plugin is active
            if (function_exists('is_plugin_active') && is_plugin_active('wordpress-seo/wp-seo.php')) {
                if ($meta_title) {
                    update_post_meta($entity_id, '_yoast_wpseo_title', $meta_title);
                }
                if ($meta_description) {
                    update_post_meta($entity_id, '_yoast_wpseo_metadesc', $meta_description);
                }
                if ($meta_keywords) {
                    update_post_meta($entity_id, '_yoast_wpseo_focuskw', $meta_keywords);
                }
            }
            
            // Update RankMath fields if plugin is active
            if (function_exists('is_plugin_active') && is_plugin_active('seo-by-rank-math/rank-math.php')) {
                if ($meta_title) {
                    update_post_meta($entity_id, 'rank_math_title', $meta_title);
                }
                if ($meta_description) {
                    update_post_meta($entity_id, 'rank_math_description', $meta_description);
                }
                if ($meta_keywords) {
                    update_post_meta($entity_id, 'rank_math_focus_keyword', $meta_keywords);
                }
            }

            $this->track_wallet_usage(
                'aysa_seo_update_product_meta',
                'seo_update_product_meta',
                5,
                array(
                    'module' => 'on_page_optimization',
                    'entity_id' => intval($entity_id),
                    'entity_type' => 'product',
                ),
                '/v1/onpage/seo-update-product-meta'
            );
            
            wp_send_json_success([
                'message' => 'Product SEO meta updated successfully',
                'entity_id' => $entity_id,
                'updated_fields' => array_keys(array_filter($results)),
                'meta_data' => [
                    'title' => $meta_title,
                    'description' => $meta_description,
                    'keywords' => $meta_keywords,
                    'short_description' => $short_description,
                    'product_description' => $product_description,
                    'product_permalink' => $product_permalink,
                    'product_title' => $product_title
                ]
            ]);
            
        } catch (Exception $e) {
            aysa_debug_log('Product SEO Update Error: ' . $e->getMessage());
            wp_send_json_error(['message' => 'Server error: ' . $e->getMessage()]);
        }
    }
    
    function aysa_seo_update_product_category_meta_handler() {
        $provided_nonce = isset($_POST['nonce']) ? sanitize_text_field((string) wp_unslash($_POST['nonce'])) : '';
        // Verify nonce
        if (!wp_verify_nonce($provided_nonce, 'aysa_seo_nonce')) {
            wp_send_json_error(['message' => 'Security check failed']);
        }
        
        // Check permissions
        if (!current_user_can('manage_product_terms')) {
            wp_send_json_error(['message' => 'Insufficient permissions']);
        }
        
        $entity_id = isset($_POST['entity_id']) ? intval((string) wp_unslash($_POST['entity_id'])) : 0;
        $term = $entity_id > 0 ? get_term($entity_id) : null;
        if (!$term || is_wp_error($term)) {
            wp_send_json_error(['message' => 'Product category not found']);
        }
        if (!current_user_can('edit_term', $entity_id)) {
            wp_send_json_error(['message' => 'Product category permission denied'], 403);
        }
        $meta_title = isset($_POST['meta_title']) ? sanitize_text_field((string) wp_unslash($_POST['meta_title'])) : '';
        $meta_description = isset($_POST['meta_description']) ? sanitize_textarea_field((string) wp_unslash($_POST['meta_description'])) : '';
        $meta_keywords = isset($_POST['meta_keywords']) ? sanitize_text_field((string) wp_unslash($_POST['meta_keywords'])) : '';
        
        // Update product category meta
        update_term_meta($entity_id, '_aysa_seo_title', $meta_title);
        update_term_meta($entity_id, '_aysa_seo_description', $meta_description);
        update_term_meta($entity_id, '_aysa_seo_keywords', $meta_keywords);
        
        // Update SEO plugin fields
        if (is_plugin_active('wordpress-seo/wp-seo.php')) {
            update_term_meta($entity_id, '_yoast_wpseo_title', $meta_title);
            update_term_meta($entity_id, '_yoast_wpseo_desc', $meta_description);
        }
        
        if (is_plugin_active('seo-by-rank-math/rank-math.php')) {
            update_term_meta($entity_id, 'rank_math_title', $meta_title);
            update_term_meta($entity_id, 'rank_math_description', $meta_description);
        }

        $this->track_wallet_usage(
            'aysa_seo_update_product_category_meta',
            'seo_update_product_category_meta',
            5,
            array(
                'module' => 'on_page_optimization',
                'entity_id' => intval($entity_id),
                'entity_type' => 'product_category',
            ),
            '/v1/onpage/seo-update-product-category-meta'
        );
        
        wp_send_json_success([
            'message' => 'Product Category SEO meta updated successfully',
            'entity_id' => $entity_id,
            'updated_fields' => ['title', 'description', 'keywords']
        ]);
    }
    
    function aysa_seo_output_meta_tags() {
        // Only output on frontend, not in admin
        if (is_admin()) {
            return;
        }
        
        // Debug logging
        aysa_debug_log('AYSA: aysa_seo_output_meta_tags() called');
        aysa_debug_log('AYSA: Current URL: ' . (isset($_SERVER['REQUEST_URI']) ? sanitize_text_field((string) wp_unslash($_SERVER['REQUEST_URI'])) : ''));
        
        global $post;
        
        // ✅ FIXED: Skip singular posts/pages to avoid duplicate meta tags
        // Aysa_Meta_Tags class already handles these
        if (is_singular() && $post) {
            aysa_debug_log('AYSA: Skipping singular post/page - handled by Aysa_Meta_Tags to avoid duplicates');
            return;
        }
        
        if (false) { // Disabled to prevent duplicate meta tags
            // For posts/pages/products
            aysa_debug_log('AYSA: is_singular() is true, post ID: ' . $post->ID . ', post type: ' . $post->post_type);
            
            // Check both our custom fields and standard meta fields
            $meta_title = get_post_meta($post->ID, '_aysa_seo_title', true);
            if (!$meta_title) {
                $meta_title = get_post_meta($post->ID, '_aysa_meta_title', true);
            }
            
            $meta_description = get_post_meta($post->ID, '_aysa_seo_description', true);
            if (!$meta_description) {
                $meta_description = get_post_meta($post->ID, '_aysa_meta_description', true);
            }
            
            $meta_keywords = get_post_meta($post->ID, '_aysa_seo_keywords', true);
            if (!$meta_keywords) {
                $meta_keywords = get_post_meta($post->ID, '_aysa_meta_keywords', true);
            }
            
            aysa_debug_log('AYSA: Meta values - Title: ' . $meta_title . ', Description: ' . $meta_description . ', Keywords: ' . $meta_keywords);
            
            if ($meta_title) {
                echo '<title>' . esc_html($meta_title) . '</title>' . "\n";
                aysa_debug_log('AYSA: Output title tag: ' . $meta_title);
            }
            
            if ($meta_description) {
                echo '<meta name="description" content="' . esc_attr($meta_description) . '">' . "\n";
                aysa_debug_log('AYSA: Output description meta tag: ' . $meta_description);
            }
            
            if ($meta_keywords) {
                echo '<meta name="keywords" content="' . esc_attr($meta_keywords) . '">' . "\n";
                aysa_debug_log('AYSA: Output keywords meta tag: ' . $meta_keywords);
            }
            
            // Also output Open Graph tags if we have the data
            if ($meta_title) {
                echo '<meta property="og:title" content="' . esc_attr($meta_title) . '">' . "\n";
            }
            if ($meta_description) {
                echo '<meta property="og:description" content="' . esc_attr($meta_description) . '">' . "\n";
            }
            
        } elseif (is_category() || is_tag() || is_tax()) {
            // For categories/tags/taxonomies
            $term = get_queried_object();
            if ($term) {
                aysa_debug_log('AYSA: Term page - term ID: ' . $term->term_id . ', taxonomy: ' . $term->taxonomy);
                
                $meta_title = get_term_meta($term->term_id, '_aysa_seo_title', true);
                $meta_description = get_term_meta($term->term_id, '_aysa_seo_description', true);
                $meta_keywords = get_term_meta($term->term_id, '_aysa_seo_keywords', true);
                
                if ($meta_title) {
                    echo '<title>' . esc_html($meta_title) . '</title>' . "\n";
                    aysa_debug_log('AYSA: Output term title tag: ' . $meta_title);
                }
                
                if ($meta_description) {
                    echo '<meta name="description" content="' . esc_attr($meta_description) . '">' . "\n";
                    aysa_debug_log('AYSA: Output term description meta tag: ' . $meta_description);
                }
                
                if ($meta_keywords) {
                    echo '<meta name="keywords" content="' . esc_attr($meta_keywords) . '">' . "\n";
                    aysa_debug_log('AYSA: Output term keywords meta tag: ' . $meta_keywords);
                }
            }
        }
    }

    function aysa_seo_update_generic_meta_handler() {
        $provided_nonce = isset($_POST['nonce']) ? sanitize_text_field((string) wp_unslash($_POST['nonce'])) : '';
        // Verify nonce
        if (!wp_verify_nonce($provided_nonce, 'aysa_seo_nonce')) {
            wp_send_json_error(['message' => 'Security check failed']);
        }
        
        // Check permissions
        if (!current_user_can('edit_posts')) {
            wp_send_json_error(['message' => 'Insufficient permissions']);
        }
        
        $entity_id = isset($_POST['entity_id']) ? intval((string) wp_unslash($_POST['entity_id'])) : 0;
        $entity_type = isset($_POST['entity_type']) ? sanitize_text_field((string) wp_unslash($_POST['entity_type'])) : '';
        $meta_title = isset($_POST['meta_title']) ? sanitize_text_field((string) wp_unslash($_POST['meta_title'])) : '';
        $meta_description = isset($_POST['meta_description']) ? sanitize_textarea_field((string) wp_unslash($_POST['meta_description'])) : '';
        $meta_keywords = isset($_POST['meta_keywords']) ? sanitize_text_field((string) wp_unslash($_POST['meta_keywords'])) : '';
        
        // Determine if it's a post/page or term based on entity type
        $is_term = in_array(strtolower($entity_type), ['category', 'tag', 'product_cat', 'product_tag']);
        
        if ($is_term) {
            $term = $entity_id > 0 ? get_term($entity_id) : null;
            if (!$term || is_wp_error($term)) {
                wp_send_json_error(['message' => 'Term not found']);
            }
            if (!current_user_can('edit_term', $entity_id)) {
                wp_send_json_error(['message' => 'Term permission denied'], 403);
            }
            // Update term meta
            update_term_meta($entity_id, '_aysa_seo_title', $meta_title);
            update_term_meta($entity_id, '_aysa_seo_description', $meta_description);
            update_term_meta($entity_id, '_aysa_seo_keywords', $meta_keywords);
            
            // Update SEO plugin fields for terms
            if (is_plugin_active('wordpress-seo/wp-seo.php')) {
                update_term_meta($entity_id, '_yoast_wpseo_title', $meta_title);
                update_term_meta($entity_id, '_yoast_wpseo_desc', $meta_description);
            }
            
            if (is_plugin_active('seo-by-rank-math/rank-math.php')) {
                update_term_meta($entity_id, 'rank_math_title', $meta_title);
                update_term_meta($entity_id, 'rank_math_description', $meta_description);
            }
        } else {
            $post = $entity_id > 0 ? get_post($entity_id) : null;
            if (!$post) {
                wp_send_json_error(['message' => 'Post not found']);
            }
            if (!current_user_can('edit_post', $entity_id)) {
                wp_send_json_error(['message' => 'Post permission denied'], 403);
            }
            // Update post meta
            update_post_meta($entity_id, '_aysa_seo_title', $meta_title);
            update_post_meta($entity_id, '_aysa_seo_description', $meta_description);
            update_post_meta($entity_id, '_aysa_seo_keywords', $meta_keywords);
            
            // Update SEO plugin fields for posts
            if (is_plugin_active('wordpress-seo/wp-seo.php')) {
                update_post_meta($entity_id, '_yoast_wpseo_title', $meta_title);
                update_post_meta($entity_id, '_yoast_wpseo_metadesc', $meta_description);
                update_post_meta($entity_id, '_yoast_wpseo_focuskw', $meta_keywords);
            }
            
            if (is_plugin_active('seo-by-rank-math/rank-math.php')) {
                update_post_meta($entity_id, 'rank_math_title', $meta_title);
                update_post_meta($entity_id, 'rank_math_description', $meta_description);
                update_post_meta($entity_id, 'rank_math_focus_keyword', $meta_keywords);
            }
        }

        $this->track_wallet_usage(
            'aysa_seo_update_generic_meta',
            'seo_update_generic_meta',
            5,
            array(
                'module' => 'on_page_optimization',
                'entity_id' => intval($entity_id),
                'entity_type' => (string) $entity_type,
            ),
            '/v1/onpage/seo-update-generic-meta'
        );
        
        wp_send_json_success([
            'message' => ucfirst($entity_type) . ' SEO meta updated successfully',
            'entity_id' => $entity_id,
            'entity_type' => $entity_type,
            'updated_fields' => ['title', 'description', 'keywords']
        ]);
    }


    /**
     * AJAX handler for logging a single SEO generation
     */
    public function ajax_log_seo_generation() {
        try {
            $provided_nonce = isset($_POST['nonce']) ? sanitize_text_field((string) wp_unslash($_POST['nonce'])) : '';
            // Verify nonce
            if (!wp_verify_nonce($provided_nonce, 'aysa_history_action')) {
                wp_send_json_error('Security check failed');
            }
            
            // Check user capabilities
            if (!current_user_can('edit_posts')) {
                wp_send_json_error('Insufficient permissions');
            }
            
            // Get and validate log data
            // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reviewed release input boundary: the guarded callback preserves structured input only until its field-specific validation or normalizer, before persistence, output, SQL, or a broker request.
            $log_data = $this->sanitize_log_data(isset($_POST['log_data']) ? wp_unslash($_POST['log_data']) : array());
            
            if (!$log_data) {
                wp_send_json_error('Invalid log data');
            }

            if (!$this->current_user_can_access_entity($log_data['entity_type'], $log_data['entity_id'])) {
                wp_send_json_error('Entity permission denied', 403);
            }
            
            // Log the generation
            $entry_id = $this->seo_history->log_generation($log_data);
            
            wp_send_json_success(array(
                'entry_id' => $entry_id,
                'message' => 'SEO generation logged successfully'
            ));
            
        } catch (Exception $e) {
            wp_send_json_error('Failed to log SEO generation: ' . $e->getMessage());
        }
    }
    
    /**
     * AJAX handler for logging multiple SEO generations in batch
     */
    public function ajax_log_seo_generation_batch() {
        try {
            $provided_nonce = isset($_POST['nonce']) ? sanitize_text_field((string) wp_unslash($_POST['nonce'])) : '';
            // Verify nonce
            if (!wp_verify_nonce($provided_nonce, 'aysa_history_action')) {
                wp_send_json_error('Security check failed');
            }
            
            // Check user capabilities
            if (!current_user_can('edit_posts')) {
                wp_send_json_error('Insufficient permissions');
            }
            
            // Get and validate log data
            // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reviewed release input boundary: the guarded callback preserves structured input only until its field-specific validation or normalizer, before persistence, output, SQL, or a broker request.
            $log_data_batch = isset($_POST['log_data']) ? wp_unslash($_POST['log_data']) : array();
            
            if (!is_array($log_data_batch) || empty($log_data_batch)) {
                wp_send_json_error('Invalid batch data');
            }
            
            $entry_ids = array();
            $errors = array();
            
            foreach ($log_data_batch as $index => $log_data) {
                try {
                    $sanitized_data = $this->sanitize_log_data($log_data);
                    
                    if ($sanitized_data && $this->current_user_can_access_entity($sanitized_data['entity_type'], $sanitized_data['entity_id'])) {
                        $entry_id = $this->seo_history->log_generation($sanitized_data);
                        $entry_ids[] = $entry_id;
                    } else {
                        $errors[] = "Invalid data at index {$index}";
                    }
                    
                } catch (Exception $e) {
                    $errors[] = "Error at index {$index}: " . $e->getMessage();
                }
            }
            
            wp_send_json_success(array(
                'entry_ids' => $entry_ids,
                'logged_count' => count($entry_ids),
                'error_count' => count($errors),
                'errors' => $errors,
                'message' => sprintf('Logged %d of %d entries', count($entry_ids), count($log_data_batch))
            ));
            
        } catch (Exception $e) {
            wp_send_json_error('Failed to log batch: ' . $e->getMessage());
        }
    }
    
    /**
     * AJAX handler for updating history entry status
     */
    public function ajax_update_history_status() {
        try {
            $provided_nonce = isset($_POST['nonce']) ? sanitize_text_field((string) wp_unslash($_POST['nonce'])) : '';
            // Verify nonce
            if (!wp_verify_nonce($provided_nonce, 'aysa_history_action')) {
                wp_send_json_error('Security check failed');
            }
            
            // Check user capabilities
            if (!current_user_can('edit_posts')) {
                wp_send_json_error('Insufficient permissions');
            }
            
            $entry_id = isset($_POST['entry_id']) ? intval((string) wp_unslash($_POST['entry_id'])) : 0;
            $status = isset($_POST['status']) ? sanitize_text_field((string) wp_unslash($_POST['status'])) : '';
            
            if (!$entry_id || !in_array($status, array('applied', 'reverted'))) {
                wp_send_json_error('Invalid parameters');
            }

            $entry = $this->seo_history->get_entry($entry_id);
            if (!$entry || !$this->current_user_can_access_entity($entry->entity_type, $entry->entity_id)) {
                wp_send_json_error('Entry permission denied', 403);
            }
            
            // Update status
            if ($status === 'applied') {
                $result = $this->seo_history->mark_as_applied($entry_id);
            } else {
                $result = $this->seo_history->mark_as_reverted($entry_id);
            }
            
            wp_send_json_success(array(
                'entry_id' => $entry_id,
                'status' => $status,
                'updated' => $result,
                'message' => "Entry marked as {$status}"
            ));
            
        } catch (Exception $e) {
            wp_send_json_error('Failed to update status: ' . $e->getMessage());
        }
    }
    
    /**
     * AJAX handler for getting entity history
     */
    public function ajax_get_entity_history() {
        try {
            $provided_nonce = isset($_POST['nonce']) ? sanitize_text_field((string) wp_unslash($_POST['nonce'])) : '';
            // Verify nonce
            if (!wp_verify_nonce($provided_nonce, 'aysa_history_action')) {
                wp_send_json_error('Security check failed');
            }
            
            // Check user capabilities
            if (!current_user_can('edit_posts')) {
                wp_send_json_error('Insufficient permissions');
            }
            
            $entity_type = isset($_POST['entity_type']) ? sanitize_text_field((string) wp_unslash($_POST['entity_type'])) : '';
            $entity_id = isset($_POST['entity_id']) ? intval((string) wp_unslash($_POST['entity_id'])) : 0;
            $limit = isset($_POST['limit']) ? intval((string) wp_unslash($_POST['limit'])) : 50;
            $offset = isset($_POST['offset']) ? intval((string) wp_unslash($_POST['offset'])) : 0;
            
            if (!$entity_type || !$entity_id) {
                wp_send_json_error('Missing entity type or ID');
            }

            if (!$this->current_user_can_access_entity($entity_type, $entity_id)) {
                wp_send_json_error('Entity permission denied', 403);
            }
            
            $history = $this->seo_history->get_entity_history($entity_id, $entity_type, $limit, $offset);
            
            wp_send_json_success(array(
                'history' => $history,
                'entity_type' => $entity_type,
                'entity_id' => $entity_id,
                'count' => count($history)
            ));
            
        } catch (Exception $e) {
            wp_send_json_error('Failed to get entity history: ' . $e->getMessage());
        }
    }
    
    /**
     * AJAX handler for getting recent history
     */
    public function ajax_get_recent_history() {
        try {
            $provided_nonce = isset($_POST['nonce']) ? sanitize_text_field((string) wp_unslash($_POST['nonce'])) : '';
            // Verify nonce
            if (!wp_verify_nonce($provided_nonce, 'aysa_history_action')) {
                wp_send_json_error('Security check failed');
            }
            
            // Check user capabilities
            if (!current_user_can('manage_options')) {
                wp_send_json_error('Insufficient permissions');
            }
            
            $limit = isset($_POST['limit']) ? intval((string) wp_unslash($_POST['limit'])) : 50;
            $offset = isset($_POST['offset']) ? intval((string) wp_unslash($_POST['offset'])) : 0;
            $entity_type = isset($_POST['entity_type']) ? sanitize_text_field((string) wp_unslash($_POST['entity_type'])) : '';
            $user_id = isset($_POST['user_id']) ? intval((string) wp_unslash($_POST['user_id'])) : 0;
            
            if ($user_id > 0) {
                $history = $this->seo_history->get_user_history($user_id, $limit, $offset);
            } else {
                $history = $this->seo_history->get_recent_history($limit, $offset);
            }
            
            // Filter by entity type if specified
            if (!empty($entity_type) && is_array($history)) {
                $history = array_filter($history, function($entry) use ($entity_type) {
                    return $entry->entity_type === $entity_type;
                });
                $history = array_values($history); // Re-index array
            }
            
            wp_send_json_success(array(
                'history' => $history,
                'count' => count($history),
                'filters' => array(
                    'entity_type' => $entity_type,
                    'user_id' => $user_id,
                    'limit' => $limit,
                    'offset' => $offset
                )
            ));
            
        } catch (Exception $e) {
            wp_send_json_error('Failed to get recent history: ' . $e->getMessage());
        }
    }
    
    /**
     * AJAX handler for searching history
     */
    public function ajax_search_history() {
        try {
            $provided_nonce = isset($_POST['nonce']) ? sanitize_text_field((string) wp_unslash($_POST['nonce'])) : '';
            // Verify nonce
            if (!wp_verify_nonce($provided_nonce, 'aysa_history_action')) {
                wp_send_json_error('Security check failed');
            }
            
            // Check user capabilities
            if (!current_user_can('manage_options')) {
                wp_send_json_error('Insufficient permissions');
            }
            
            $query = isset($_POST['query']) ? sanitize_text_field((string) wp_unslash($_POST['query'])) : '';
            $limit = isset($_POST['limit']) ? intval((string) wp_unslash($_POST['limit'])) : 50;
            $offset = isset($_POST['offset']) ? intval((string) wp_unslash($_POST['offset'])) : 0;
            $entity_type = isset($_POST['entity_type']) ? sanitize_text_field((string) wp_unslash($_POST['entity_type'])) : '';
            $user_id = isset($_POST['user_id']) ? intval((string) wp_unslash($_POST['user_id'])) : 0;
            
            if (empty($query)) {
                wp_send_json_error('Search query is required');
            }
            
            $history = $this->seo_history->search_history($query, $limit, $offset);
            
            // Apply additional filters
            if (!empty($entity_type) && is_array($history)) {
                $history = array_filter($history, function($entry) use ($entity_type) {
                    return $entry->entity_type === $entity_type;
                });
            }
            
            if ($user_id > 0 && is_array($history)) {
                $history = array_filter($history, function($entry) use ($user_id) {
                    return $entry->wp_user_id == $user_id;
                });
            }
            
            $history = array_values($history); // Re-index array
            
            wp_send_json_success(array(
                'history' => $history,
                'count' => count($history),
                'query' => $query,
                'filters' => array(
                    'entity_type' => $entity_type,
                    'user_id' => $user_id,
                    'limit' => $limit,
                    'offset' => $offset
                )
            ));
            
        } catch (Exception $e) {
            wp_send_json_error('Failed to search history: ' . $e->getMessage());
        }
    }
    
    /**
     * AJAX handler for getting history statistics
     */
    public function ajax_get_history_statistics() {
        try {
            $provided_nonce = isset($_POST['nonce']) ? sanitize_text_field((string) wp_unslash($_POST['nonce'])) : '';
            // Verify nonce
            if (!wp_verify_nonce($provided_nonce, 'aysa_history_action')) {
                wp_send_json_error('Security check failed');
            }
            
            // Check user capabilities
            if (!current_user_can('manage_options')) {
                wp_send_json_error('Insufficient permissions');
            }
            
            $stats = $this->seo_history->get_statistics();
            
            wp_send_json_success(array(
                'statistics' => $stats,
                'generated_at' => current_time('mysql')
            ));
            
        } catch (Exception $e) {
            wp_send_json_error('Failed to get statistics: ' . $e->getMessage());
        }
    }
    
    /**
     * AJAX handler for adding SEO history entry
     */
    public function ajax_seo_history_add_entry() {
        try {
            $provided_nonce = isset($_POST['nonce']) ? sanitize_text_field((string) wp_unslash($_POST['nonce'])) : '';
            // Verify nonce
            if (!wp_verify_nonce($provided_nonce, 'aysa_seo_history_nonce')) {
                wp_send_json_error('Security check failed');
            }
            
            // Check user capabilities
            if (!current_user_can('edit_posts')) {
                wp_send_json_error('Insufficient permissions');
            }
            
            // Get and sanitize input data
            $entity_id = isset($_POST['entity_id']) ? intval((string) wp_unslash($_POST['entity_id'])) : 0;
            $entity_type = isset($_POST['entity_type']) ? sanitize_text_field((string) wp_unslash($_POST['entity_type'])) : '';
            $generator_type = isset($_POST['generator_type']) ? sanitize_text_field((string) wp_unslash($_POST['generator_type'])) : 'new';
            $keyword = isset($_POST['keyword']) ? sanitize_text_field((string) wp_unslash($_POST['keyword'])) : '';
            // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reviewed release input boundary: the guarded callback preserves structured input only until its field-specific validation or normalizer, before persistence, output, SQL, or a broker request.
            $generated_data = isset($_POST['generated_data']) ? (string) wp_unslash($_POST['generated_data']) : '{}';
            // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reviewed release input boundary: the guarded callback preserves structured input only until its field-specific validation or normalizer, before persistence, output, SQL, or a broker request.
            $context_data = isset($_POST['context_data']) ? (string) wp_unslash($_POST['context_data']) : '{}';
            
            // Validate required fields
            if (!$entity_id || !$entity_type || !$keyword) {
                wp_send_json_error('Missing required fields: entity_id, entity_type, or keyword');
            }

            if (!$this->current_user_can_access_entity($entity_type, $entity_id)) {
                wp_send_json_error('Entity permission denied', 403);
            }
            
            // Parse JSON data
            $generated_data_array = json_decode($generated_data, true);
            $context_data_array = json_decode($context_data, true);
            
            if (json_last_error() !== JSON_ERROR_NONE) {
                wp_send_json_error('Invalid JSON data provided');
            }
            
            // Prepare data for logging
            $log_data = array(
                'entity_id' => $entity_id,
                'entity_type' => $entity_type,
                'keyword' => $keyword,
                'generator_type' => $generator_type,
                'meta_title' => $generated_data_array['metaTitle'] ?? '',
                'meta_description' => $generated_data_array['metaDescription'] ?? '',
                'meta_keywords' => $generated_data_array['metaKeywords'] ?? '',
                'secondary_keywords' => is_array($generated_data_array['secondaryKeywords'] ?? null) ? 
                    implode(', ', $generated_data_array['secondaryKeywords']) : '',
                'content_title' => $generated_data_array['content'] ?? '',
                'generation_context' => $context_data_array,
                'status' => 'generated'
            );
            
            // Log the SEO generation
            $entry_id = $this->seo_history->log_seo_generation($log_data);
            
            if ($entry_id) {
                wp_send_json_success(array(
                    'entry_id' => $entry_id,
                    'message' => 'SEO history entry created successfully'
                ));
            } else {
                wp_send_json_error('Failed to create SEO history entry');
            }
            
        } catch (Exception $e) {
            wp_send_json_error('Error creating SEO history entry: ' . $e->getMessage());
        }
    }
    
    /**
     * Sanitize and validate log data
     * 
     * @param array $data Raw log data
     * @return array|false Sanitized data or false if invalid
     */
    private function sanitize_log_data($data) {
        if (!is_array($data)) {
            return false;
        }
        
        // Required fields
        $required_fields = array('entity_id', 'entity_type', 'keyword');
        foreach ($required_fields as $field) {
            if (empty($data[$field])) {
                return false;
            }
        }
        
        // Sanitize data
        $sanitized = array(
            'entity_id' => intval($data['entity_id']),
            'entity_type' => sanitize_text_field($data['entity_type']),
            'entity_name' => sanitize_text_field($data['entity_name'] ?? ''),
            'keyword' => sanitize_text_field($data['keyword']),
            'language' => sanitize_text_field($data['language'] ?? 'en'),
            'generator_type' => sanitize_text_field($data['generator_type'] ?? 'new'),
            'generation_method' => sanitize_text_field($data['generation_method'] ?? 'api'),
            
            // Generated content
            'meta_title' => sanitize_text_field($data['meta_title'] ?? ''),
            'meta_description' => sanitize_textarea_field($data['meta_description'] ?? ''),
            'meta_keywords' => sanitize_text_field($data['meta_keywords'] ?? ''),
            'secondary_keywords' => sanitize_text_field($data['secondary_keywords'] ?? ''),
            'product_title' => sanitize_text_field($data['product_title'] ?? ''),
            'product_description' => $this->sanitize_product_description_html($data['product_description'] ?? ''),
            'permalink' => sanitize_text_field($data['permalink'] ?? ''),
            
            // Metadata
            'generation_metadata' => is_array($data['generation_metadata']) ? 
                wp_json_encode($data['generation_metadata']) : '',
            'previous_data' => is_array($data['previous_data']) ? 
                wp_json_encode($data['previous_data']) : '',
            'api_response_data' => is_array($data['api_response_data']) ? 
                wp_json_encode($data['api_response_data']) : '',
            
            // Performance and status
            'api_response_time' => intval($data['api_response_time'] ?? 0),
            'confidence_score' => floatval($data['confidence_score'] ?? 0),
            'status' => sanitize_text_field($data['status'] ?? 'generated'),
            'partial_failure' => !empty($data['partial_failure']),
            'failed_fields' => sanitize_text_field($data['failed_fields'] ?? ''),
            
            // User and session info
            'wp_user_id' => get_current_user_id(),
            'session_id' => sanitize_text_field($data['session_id'] ?? ''),
            'ip_address' => $this->get_client_ip(),
            'user_agent' => sanitize_text_field($data['user_agent'] ?? ''),
            'page_url' => esc_url_raw($data['page_url'] ?? ''),
            'referrer' => esc_url_raw($data['referrer'] ?? '')
        );
        
        return $sanitized;
    }
    
    /**
     * Sanitize product description while preserving FAQ schema microdata attributes.
     *
     * @param string $html Raw HTML from generator.
     * @return string
     */
    private function sanitize_product_description_html($html) {
        if (!is_string($html) || $html === '') {
            return '';
        }

        $allowed = wp_kses_allowed_html('post');
        $schema_attrs = array(
            'itemscope' => true,
            'itemtype'  => true,
            'itemprop'  => true,
        );

        foreach (array('section', 'div', 'h2', 'h3', 'h4', 'p', 'span') as $tag) {
            if (!isset($allowed[$tag]) || !is_array($allowed[$tag])) {
                $allowed[$tag] = array();
            }
            $allowed[$tag] = array_merge($allowed[$tag], $schema_attrs);
        }

        return wp_kses($html, $allowed);
    }

    /**
     * Authorize history reads and writes against the exact WordPress object.
     */
    private function current_user_can_access_entity($entity_type, $entity_id) {
        $entity_type = sanitize_key((string) $entity_type);
        $entity_id = intval($entity_id);

        if ($entity_id <= 0) {
            return false;
        }

        $term_taxonomies = array(
            'category' => 'category',
            'product_cat' => 'product_cat',
            'product_category' => 'product_cat',
        );
        if (isset($term_taxonomies[$entity_type])) {
            $term = get_term($entity_id, $term_taxonomies[$entity_type]);
            return $term && !is_wp_error($term) && current_user_can('edit_term', $entity_id);
        }

        if (in_array($entity_type, array('post', 'page', 'product'), true)) {
            return get_post($entity_id) && current_user_can('edit_post', $entity_id);
        }

        return false;
    }

    /**
     * Get client IP address
     * 
     * @return string
     */
    private function get_client_ip() {
        $ip_keys = array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'REMOTE_ADDR');
        
        foreach ($ip_keys as $key) {
            if (array_key_exists($key, $_SERVER) === true) {
                $forwarded_ips = sanitize_text_field(wp_unslash($_SERVER[$key]));
                foreach (explode(',', $forwarded_ips) as $ip) {
                    $ip = trim($ip);
                    
                    if (filter_var($ip, FILTER_VALIDATE_IP, 
                        FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false) {
                        return $ip;
                    }
                }
            }
        }
        
        $remote_ip = isset($_SERVER['REMOTE_ADDR']) ? sanitize_text_field(wp_unslash($_SERVER['REMOTE_ADDR'])) : '';
        return filter_var($remote_ip, FILTER_VALIDATE_IP) !== false ? $remote_ip : 'unknown';
    }
    
    /**
     * Test handler to verify if meta was saved correctly
     */
    function aysa_test_meta_save_handler() {
        try {
            // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Reviewed callback inventory: this request read is downstream of the handler nonce and capability guard, a shared guarded delegate, or the authenticated WordPress core save/query flow.
            aysa_debug_log('Meta test handler called; POST keys: ' . implode(',', array_keys($_POST)));
            
            // Check if nonce exists
            if (!isset($_POST['nonce'])) {
                wp_send_json_error(['message' => 'Nonce missing']);
                return;
            }
            
            $provided_nonce = sanitize_text_field((string) wp_unslash($_POST['nonce']));

            // Verify nonce - try different nonce names
            $nonce_valid = false;
            $nonce_names = ['aysa_history_action', 'aysa_seo_nonce', 'aysa_seo_history_nonce', 'nonce'];
            
            foreach ($nonce_names as $nonce_name) {
                if (wp_verify_nonce($provided_nonce, $nonce_name)) {
                    $nonce_valid = true;
                    break;
                }
            }
            
            if (!$nonce_valid) {
                aysa_debug_log('Meta test - Nonce verification failed.');
                wp_send_json_error(['message' => 'Security check failed']);
                return;
            }
            
            // Check permissions
            if (!current_user_can('edit_posts') && !current_user_can('edit_pages')) {
                wp_send_json_error(['message' => 'Insufficient permissions']);
                return;
            }
            
            // Validate and sanitize input
            // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reviewed release input boundary: the guarded callback preserves structured input only until its field-specific validation or normalizer, before persistence, output, SQL, or a broker request.
            $raw_entity_id = isset($_POST['entity_id']) ? (string) wp_unslash($_POST['entity_id']) : '';
            if ($raw_entity_id === '' || !is_numeric($raw_entity_id)) {
                wp_send_json_error(['message' => 'Invalid entity ID']);
                return;
            }
            
            $entity_id = intval($raw_entity_id);
            $entity_type = isset($_POST['entity_type']) ? sanitize_text_field((string) wp_unslash($_POST['entity_type'])) : '';

            if (!$this->current_user_can_access_entity($entity_type, $entity_id)) {
                wp_send_json_error(['message' => 'Entity permission denied'], 403);
                return;
            }
            
            aysa_debug_log('Meta test - Entity ID: ' . $entity_id . ', Type: ' . $entity_type);
            
            // Get current meta values
            $current_meta = [];
            
            if (in_array($entity_type, ['post', 'page', 'product'])) {
                // For posts/pages/products
                $current_meta['aysa_title'] = get_post_meta($entity_id, '_aysa_seo_title', true);
                $current_meta['aysa_title_alt'] = get_post_meta($entity_id, '_aysa_meta_title', true);
                $current_meta['aysa_description'] = get_post_meta($entity_id, '_aysa_seo_description', true);
                $current_meta['aysa_description_alt'] = get_post_meta($entity_id, '_aysa_meta_description', true);
                $current_meta['aysa_keywords'] = get_post_meta($entity_id, '_aysa_seo_keywords', true);
                $current_meta['aysa_keywords_alt'] = get_post_meta($entity_id, '_aysa_meta_keywords', true);
                
                // Check Yoast if active
                if (function_exists('is_plugin_active') && is_plugin_active('wordpress-seo/wp-seo.php')) {
                    $current_meta['yoast_title'] = get_post_meta($entity_id, '_yoast_wpseo_title', true);
                    $current_meta['yoast_description'] = get_post_meta($entity_id, '_yoast_wpseo_metadesc', true);
                    $current_meta['yoast_keywords'] = get_post_meta($entity_id, '_yoast_wpseo_focuskw', true);
                }
                
                // Check RankMath if active
                if (function_exists('is_plugin_active') && is_plugin_active('seo-by-rank-math/rank-math.php')) {
                    $current_meta['rankmath_title'] = get_post_meta($entity_id, 'rank_math_title', true);
                    $current_meta['rankmath_description'] = get_post_meta($entity_id, 'rank_math_description', true);
                    $current_meta['rankmath_keywords'] = get_post_meta($entity_id, 'rank_math_focus_keyword', true);
                }
                
            } elseif (in_array($entity_type, ['category', 'product_cat', 'product_category'])) {
                // For categories
                $current_meta['aysa_title'] = get_term_meta($entity_id, '_aysa_seo_title', true);
                $current_meta['aysa_description'] = get_term_meta($entity_id, '_aysa_seo_description', true);
                $current_meta['aysa_keywords'] = get_term_meta($entity_id, '_aysa_seo_keywords', true);
                
                // Check Yoast if active
                if (function_exists('is_plugin_active') && is_plugin_active('wordpress-seo/wp-seo.php')) {
                    $current_meta['yoast_title'] = get_term_meta($entity_id, '_yoast_wpseo_title', true);
                    $current_meta['yoast_description'] = get_term_meta($entity_id, '_yoast_wpseo_desc', true);
                }
                
                // Check RankMath if active
                if (function_exists('is_plugin_active') && is_plugin_active('seo-by-rank-math/rank-math.php')) {
                    $current_meta['rankmath_title'] = get_term_meta($entity_id, 'rank_math_title', true);
                    $current_meta['rankmath_description'] = get_term_meta($entity_id, 'rank_math_description', true);
                }
            }
            
            aysa_debug_log('Meta test - Current meta values: ' . aysa_debug_export($current_meta, true));
            
            $this->track_wallet_usage(
                'aysa_test_meta_save',
                'test_meta_save:' . $entity_type . ':' . $entity_id,
                5,
                array(
                    'module' => 'on_page_optimization',
                    'entity_id' => intval($entity_id),
                    'entity_type' => (string) $entity_type,
                ),
                '/wp_ajax/aysa_test_meta_save'
            );

            wp_send_json_success([
                'message' => 'Meta test completed',
                'entity_id' => $entity_id,
                'entity_type' => $entity_type,
                'current_meta' => $current_meta
            ]);
            
        } catch (Exception $e) {
            aysa_debug_log('Meta test error: ' . $e->getMessage());
            wp_send_json_error(['message' => 'Server error: ' . $e->getMessage()]);
        }
    }
}

// Initialize the AJAX handlers
if (is_admin()) {
    new Aysa_Seo_History_Ajax();
}
