<?php
if (!defined('ABSPATH')) {
    exit;
}


/**
 * Class for handling media-related functionality in Aysa plugin
 *
 * @since      1.0.0
 * @package    Aysa
 * @subpackage Aysa/includes
 */

class Aysa_Media {

    private $audit_logger;
    private $confidence_scorer;
    private static $instance = null;

    /**
     * Get singleton instance
     *
     * @return Aysa_Media
     */
    public static function get_instance() {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    /**
     * Initialize the class and set its properties.
     *
     * @since    1.0.0
     */
    public function __construct() {
        // Prevent direct instantiation if singleton already exists
        if (self::$instance !== null) {
            return self::$instance;
        }
        
        // The old media-library generator bypasses Agent8 approval, verified
        // billing and readback. Keep it available only for explicit local QA;
        // production Image ALT stays on the canonical Agent8 lane.
        if (self::legacy_alt_generator_enabled()) {
            add_filter('attachment_fields_to_edit', array($this, 'add_alt_text_button'), 10, 2);
            add_filter('attachment_fields_to_save', array($this, 'add_alt_text_button'), 10, 2);
            add_action('wp_ajax_aysa_generate_alt_text', array($this, 'ajax_generate_alt_text'));
            add_action('wp_ajax_aysa_create_nonce', array($this, 'ajax_create_nonce'));
            add_action('add_meta_boxes_attachment', array($this, 'add_attachment_meta_box'));
            add_action('wp_insert_attachment', array($this, 'handle_new_attachment'), 10, 2);
            add_action('add_attachment', array($this, 'handle_attachment_added'));
            add_action('wp_ajax_query-attachments', array($this, 'ensure_buttons_in_query'), 1);
            add_action('aysa_clear_new_upload_flag', array($this, 'clear_new_upload_flag'));
            add_action('admin_enqueue_scripts', array($this, 'enqueue_media_scripts'));
        }
        
        $this->audit_logger = class_exists('Aysa_Audit_Logger') ? new Aysa_Audit_Logger() : null;
        $this->confidence_scorer = class_exists('Aysa_Confidence_Scorer') ? new Aysa_Confidence_Scorer() : null;
        
        self::$instance = $this;
    }

    /**
     * The legacy direct provider path is never a production feature switch.
     */
    public static function legacy_alt_generator_enabled() {
        if (!defined('AYSA_ENABLE_LEGACY_MEDIA_ALT_GENERATOR') || AYSA_ENABLE_LEGACY_MEDIA_ALT_GENERATOR !== true) {
            return false;
        }

        $host = strtolower((string) wp_parse_url(home_url(), PHP_URL_HOST));
        return in_array($host, array('localhost', '127.0.0.1', '::1'), true)
            || substr($host, -6) === '.local'
            || substr($host, -5) === '.test';
    }

    /**
     * Enqueue scripts and localize data for media library
     */
    public function enqueue_media_scripts() {
        // Always load on admin pages to ensure compatibility with all contexts
        if (!is_admin()) {
            return;
        }
        
        // Get current screen for context information
        $screen = get_current_screen();
        
        // Define allowed screens (expanded to include more contexts)
        $allowed_screens = array(
            'upload',           // Media library
            'media',            // Media edit page
            'attachment',       // Direct attachment edit
            'post',             // Post edit page
            'product',          // WooCommerce product edit
            'page',             // Page edit
            'edit-product_cat', // Product category list
            'product_cat',      // Product category edit
            'edit-tags',        // General taxonomy edit
            'term',             // Term edit page
            'edit-post',        // Post edit (alternative)
            'edit-page',        // Page edit (alternative)
            'edit-product',     // Product edit (alternative)
        );
        
        // Check if current screen is allowed (more permissive approach)
        $is_allowed_screen = false;
        if ($screen) {
            $is_allowed_screen = in_array($screen->base, $allowed_screens) || 
                               in_array($screen->id, $allowed_screens) ||
                               $screen->taxonomy === 'product_cat' ||
                               $screen->post_type === 'product' ||
                               $screen->post_type === 'page' ||
                               $screen->post_type === 'post' ||
                               strpos($screen->id, 'edit') !== false ||
                               strpos($screen->id, 'upload') !== false ||
                               strpos($screen->id, 'media') !== false ||
                               strpos($screen->id, 'attachment') !== false;
        } else {
            // If no screen info, load anyway for safety
            $is_allowed_screen = true;
        }
        
        if (!$is_allowed_screen) {
            return;
        }
        
        // Enqueue WordPress media scripts for media modal support
        wp_enqueue_media();
        
        // Make sure our script is enqueued with cache busting
        wp_enqueue_script('aysa-media', plugin_dir_url(dirname(__FILE__)) . 'assets/js/aysa-media.js', array('jquery', 'media-upload', 'media-views'), '1.0.0.' . time(), true);
        
        // Localize script with nonce and AJAX URL
        wp_localize_script('aysa-media', 'aysa_media_params', array(
            'ajax_url' => admin_url('admin-ajax.php'),
            'nonce' => wp_create_nonce('aysa_nonce'),
            'plugin_url' => plugin_dir_url(dirname(__FILE__)),
            'debug' => defined('WP_DEBUG') && WP_DEBUG,
            'screen_id' => $screen ? $screen->id : '',
            'screen_base' => $screen ? $screen->base : '',
            'is_category_page' => ($screen && $screen->taxonomy === 'product_cat'),
            'is_product_page' => ($screen && $screen->post_type === 'product'),
            // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reviewed callback inventory: this read-only/core lifecycle request is authenticated by WordPress or an enclosing guard and performs no unapproved write.
            'current_post_id' => isset($_GET['post']) ? intval(wp_unslash($_GET['post'])) : 0,
            // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reviewed callback inventory: this read-only/core lifecycle request is authenticated by WordPress or an enclosing guard and performs no unapproved write.
            'current_term_id' => isset($_GET['tag_ID']) ? intval(wp_unslash($_GET['tag_ID'])) : 0,
            // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reviewed callback inventory: this read-only/core lifecycle request is authenticated by WordPress or an enclosing guard and performs no unapproved write.
            'is_attachment_page' => ($screen && ($screen->base === 'post' && isset($_GET['post']) && wp_attachment_is_image(absint(wp_unslash($_GET['post']))))),
        ));
    }

    /**
     * Add a button to generate alternative text for images
     *
     * @param array $form_fields Fields for the attachment
     * @param object $post The attachment post
     * @return array Modified form fields
     */
    public function add_alt_text_button($form_fields, $post) {
        // Only add button for images
        if (!wp_attachment_is_image($post->ID)) {
            return $form_fields;
        }

        // Check if this is a newly uploaded image
        $new_upload_time = get_post_meta($post->ID, '_aysa_new_upload', true);
        $is_new_upload = $new_upload_time && (time() - $new_upload_time) < 300; // Within 5 minutes
        
        $button_class = 'button aysa-generate-alt-text';
        if ($is_new_upload) {
            $button_class .= ' aysa-new-upload';
            aysa_debug_log('AYSA MEDIA: Adding button for newly uploaded image: ' . $post->ID);
        }

        // Always add the button - no restrictions based on context
        $html = '<button type="button" class="' . esc_attr($button_class) . '" data-attachment-id="' . esc_attr($post->ID) . '">Generate with Aysa AI</button>';
        $html .= '<p class="description">Use Aysa AI to generate SEO-optimized alt text, title, and description.</p>';
        
        if ($is_new_upload) {
            $html .= '<p class="description" style="color:#4caf50;"><strong>New upload detected!</strong> Click the button above to generate AI content.</p>';
        }
        
        $html .= '<div class="aysa-alt-text-status" id="aysa-alt-text-status-' . esc_attr($post->ID) . '"></div>';

        // Add the field with a unique key that won't conflict
        $form_fields['aysa_alt_text_button'] = array(
            'label' => 'Aysa AI Alt Text',
            'input' => 'html',
            'html' => $html,
            'show_in_edit' => true,
            'show_in_modal' => true,
        );

        return $form_fields;
    }

    /**
     * Add meta box for attachment edit page
     */
    public function add_attachment_meta_box() {
        global $post;
        
        if ($post && wp_attachment_is_image($post->ID)) {
            add_meta_box(
                'aysa-attachment-ai',
                'Aysa AI Content Generation',
                array($this, 'render_attachment_meta_box'),
                'attachment',
                'side',
                'default'
            );
        }
    }

    /**
     * Render meta box for attachment edit page
     */
    public function render_attachment_meta_box($post) {
        if (!wp_attachment_is_image($post->ID)) {
            return;
        }

        echo '<div class="aysa-attachment-meta-box">';
        echo '<button type="button" class="button button-primary aysa-generate-alt-text" data-attachment-id="' . esc_attr($post->ID) . '">Generate with Aysa AI</button>';
        echo '<p class="description">Generate SEO-optimized alt text, title, and description for this image.</p>';
        echo '<div class="aysa-alt-text-status" id="aysa-alt-text-status-' . esc_attr($post->ID) . '"></div>';
        echo '</div>';
    }

    /**
     * Add inline JavaScript to inject buttons if they're missing
     */
    public function add_inline_button_injection() {
        $screen = get_current_screen();
        if (!$screen || (!is_admin())) {
            return;
        }
        
        // Only run on relevant pages
        $relevant_pages = array('upload', 'media', 'attachment', 'post', 'page', 'product', 'term', 'edit-tags');
        $is_relevant = in_array($screen->base, $relevant_pages) || 
                      in_array($screen->id, $relevant_pages) ||
                      $screen->post_type === 'product' ||
                      $screen->taxonomy === 'product_cat';
        
        if (!$is_relevant) {
            return;
        }
        ?>
        <script type="text/javascript">
        jQuery(document).ready(function($) {
            // Function to inject Aysa buttons where they might be missing
            function injectAysaButtons() {
                // Check for alt text fields without Aysa buttons
                $('input[name="_wp_attachment_image_alt"], input[id*="alt"], textarea[name*="alt"]').each(function() {
                    const $altField = $(this);
                    const $container = $altField.closest('.compat-field-aysa_alt_text_button, .attachment-details, .media-sidebar, .compat-item');
                    
                    // Check if Aysa button already exists in this container
                    if ($container.find('.aysa-generate-alt-text').length === 0) {
                        // Try to get attachment ID from various sources
                        let attachmentId = null;
                        
                        // Method 1: From URL parameters
                        const urlParams = new URLSearchParams(window.location.search);
                        if (urlParams.get('post')) {
                            attachmentId = urlParams.get('post');
                        }
                        
                        // Method 2: From form data or nearby elements
                        if (!attachmentId) {
                            const $postId = $container.find('input[name="post_ID"], input[name="attachment_id"]');
                            if ($postId.length) {
                                attachmentId = $postId.val();
                            }
                        }
                        
                        // Method 3: From data attributes
                        if (!attachmentId) {
                            attachmentId = $container.closest('[data-id]').attr('data-id');
                        }
                        
                        if (attachmentId) {
                            console.log('Injecting Aysa button for attachment ID:', attachmentId);
                            
                            const buttonHtml = 
                                '<div class="aysa-injected-button" style="margin-top: 10px;">' +
                                '<button type="button" class="button aysa-generate-alt-text" data-attachment-id="' + attachmentId + '">Generate with Aysa AI</button>' +
                                '<p class="description">Use Aysa AI to generate SEO-optimized alt text, title, and description.</p>' +
                                '<div class="aysa-alt-text-status" id="aysa-alt-text-status-' + attachmentId + '"></div>' +
                                '</div>';
                            
                            $altField.after(buttonHtml);
                        }
                    }
                });
            }
            
            // Run injection immediately
            injectAysaButtons();
            
            // Run injection when media modal opens
            if (typeof wp !== 'undefined' && wp.media) {
                $(document).on('click', '.add_media, .insert-media, .set-post-thumbnail, .wp-post-image', function() {
                    setTimeout(injectAysaButtons, 1000);
                    setTimeout(injectAysaButtons, 2000); // Second attempt for stubborn modals
                });
                
                // Also listen for modal state changes
                $(document).on('DOMNodeInserted', '.media-modal', function() {
                    setTimeout(injectAysaButtons, 500);
                });
            }
            
            // Run injection periodically (only in debug mode)
            <?php if (defined('WP_DEBUG') && WP_DEBUG): ?>
            setInterval(injectAysaButtons, 5000);
            <?php endif; ?>
        });
        </script>
        <?php
    }

    /**
     * Handle newly inserted attachments
     */
    public function handle_new_attachment($post_ID, $post) {
        // Only handle images
        if (!wp_attachment_is_image($post_ID)) {
            return;
        }
        
        // Log for debugging
        aysa_debug_log('AYSA MEDIA: New image attachment added: ' . $post_ID);
        
        // Store a flag that this is a new upload so we can handle it differently
        update_post_meta($post_ID, '_aysa_new_upload', time());
        
        // Clear the flag after 5 minutes (it's just for immediate handling)
        wp_schedule_single_event(time() + 300, 'aysa_clear_new_upload_flag', array($post_ID));
    }
    
    /**
     * Handle when attachment is added (alternative hook)
     */
    public function handle_attachment_added($post_ID) {
        if (!wp_attachment_is_image($post_ID)) {
            return;
        }
        
        aysa_debug_log('AYSA MEDIA: Attachment added hook triggered for: ' . $post_ID);
        
        // Store a flag that this is a new upload
        update_post_meta($post_ID, '_aysa_new_upload', time());
    }
    
    /**
     * Ensure buttons are included in AJAX queries for attachments
     */
    public function ensure_buttons_in_query() {
        // This runs before WordPress processes the query-attachments AJAX request
        // We'll add a filter to modify the response
        add_filter('wp_prepare_attachment_for_js', array($this, 'add_button_to_attachment_js'), 10, 3);
    }
    
    /**
     * Add button information to attachment JSON for JavaScript
     */
    public function add_button_to_attachment_js($response, $attachment, $meta) {
        // Only for images
        if (!wp_attachment_is_image($attachment->ID)) {
            return $response;
        }
        
        // Add a flag to indicate this attachment should have Aysa buttons
        $response['aysa_button_needed'] = true;
        $response['aysa_attachment_id'] = $attachment->ID;
        
        // Check if this is a newly uploaded image
        $new_upload_time = get_post_meta($attachment->ID, '_aysa_new_upload', true);
        if ($new_upload_time && (time() - $new_upload_time) < 300) {
            $response['aysa_new_upload'] = true;
            aysa_debug_log('AYSA MEDIA: Marking attachment ' . $attachment->ID . ' as new upload in JS response');
        }
        
        return $response;
    }

    /**
     * Handle AJAX request to generate alternative text for images
     *
     * @return void
     */
    public function ajax_generate_alt_text() {
        if (!self::legacy_alt_generator_enabled()) {
            wp_send_json_error(array('message' => 'Legacy media generator is disabled. Use Agent8 Image ALT.'));
            return;
        }

        // Debug information to help diagnose the issue without exposing full request payload
        // 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('AJAX DEBUG: alt-text request received; keys=' . implode(',', array_keys($_POST)));
        
        // Check nonce - be more flexible about nonce parameter name
        $nonce = '';
        if (isset($_POST['nonce'])) {
            $nonce = sanitize_text_field((string) wp_unslash($_POST['nonce']));
        } else if (isset($_POST['_wpnonce'])) {
            $nonce = sanitize_text_field((string) wp_unslash($_POST['_wpnonce']));
        } else if (isset($_POST['security'])) {
            $nonce = sanitize_text_field((string) wp_unslash($_POST['security']));
        }
        
        // Avoid logging nonce values
        aysa_debug_log('AJAX DEBUG: Nonce present: ' . (!empty($nonce) ? 'yes' : 'no'));
        
        // Verify the nonce with more detailed error reporting
        if (empty($nonce)) {
            aysa_debug_log('AJAX DEBUG: No nonce provided in request');
            wp_send_json_error(array('message' => 'Security check failed: No security token provided. Please refresh the page and try again.'));
            return;
        }
        
        $nonce_valid = wp_verify_nonce($nonce, 'aysa_nonce');
        if ($nonce_valid === false) {
            aysa_debug_log('AJAX DEBUG: Nonce verification failed for action aysa_nonce');
            
            // Get more debug information
            $current_user_id = get_current_user_id();
            $session_token = wp_get_session_token();
            
            aysa_debug_log('AJAX DEBUG: Current user ID: ' . $current_user_id);
            aysa_debug_log('AJAX DEBUG: Session token exists: ' . (!empty($session_token) ? 'Yes' : 'No'));
            
            wp_send_json_error(array(
                'message' => 'Security check failed: Invalid security token. Please refresh the page and try again.',
                'debug_info' => array(
                    'user_logged_in' => is_user_logged_in(),
                    'user_id' => $current_user_id,
                    'has_session' => !empty($session_token)
                )
            ));
            return;
        }
        
        // Check permissions
        if (!current_user_can('upload_files')) {
            wp_send_json_error(array('message' => 'You do not have permission to perform this action.'));
            return;
        }

        // Get attachment ID
        $attachment_id = isset($_POST['attachment_id']) ? intval((string) wp_unslash($_POST['attachment_id'])) : 0;
        if (!$attachment_id) {
            wp_send_json_error(array('message' => 'Invalid attachment ID.'));
            return;
        }

        // Get attachment data
        $attachment = get_post($attachment_id);
        if (!$attachment || $attachment->post_type !== 'attachment') {
            wp_send_json_error(array('message' => 'Attachment not found.'));
            return;
        }
        if (!current_user_can('edit_post', $attachment_id)) {
            wp_send_json_error(array('message' => 'You do not have permission to edit this attachment.'));
            return;
        }

        // Get language, keyword, tone and target audience from request or use defaults
        $language = isset($_POST['language']) ? sanitize_text_field((string) wp_unslash($_POST['language'])) : 'en';
        $primary_keyword = isset($_POST['primary_keyword']) ? sanitize_text_field((string) wp_unslash($_POST['primary_keyword'])) : '';
        $tone = isset($_POST['tone']) ? sanitize_text_field((string) wp_unslash($_POST['tone'])) : 'professional';
        $target_audience = isset($_POST['target_audience']) ? sanitize_text_field((string) wp_unslash($_POST['target_audience'])) : 'general';
        $secondary_keywords_raw = isset($_POST['secondary_keywords']) ? sanitize_text_field((string) wp_unslash($_POST['secondary_keywords'])) : '';
        
        // Parse secondary keywords string into an array
        $secondary_keywords = array();
        if (!empty($secondary_keywords_raw)) {
            $secondary_keywords = array_map('trim', explode(',', $secondary_keywords_raw));
            $secondary_keywords = array_filter($secondary_keywords); // Remove empty values
        }
        
        // Try to get language from context (SEO settings) if not provided or is default
        if ($language === 'en' || empty($language)) {
            $context_language = $this->get_context_language_optimize();
            if (!empty($context_language)) {
                $language = $context_language;
                aysa_debug_log('AYSA MEDIA: Using language from SEO settings: ' . $language);
            }
        }
        
        // Get the image URL - this is the key change
        $image_url = wp_get_attachment_url($attachment_id);
        if (!$image_url) {
            wp_send_json_error(array('message' => 'Could not get image URL.'));
            return;
        }
        
        // Determine primary keyword based on context
        $context_entity_id = isset($_POST['context_entity_id']) ? intval((string) wp_unslash($_POST['context_entity_id'])) : 0;
        $context_entity_type = isset($_POST['context_entity_type']) ? sanitize_text_field((string) wp_unslash($_POST['context_entity_type'])) : '';
        
        if ($context_entity_id && $context_entity_type) {
            // We have context (product or category), get keyword from metabox
            $context_keyword = $this->get_context_keyword();
            if (!empty($context_keyword)) {
                $primary_keyword = $context_keyword;
                aysa_debug_log('AYSA MEDIA: Using keyword from metabox: ' . $primary_keyword);
            } else {
                // Fallback to entity name if no keyword is set in metabox
                if ($context_entity_type === 'category' || $context_entity_type === 'term') {
                    $term = get_term($context_entity_id, 'product_cat');
                    if ($term && !is_wp_error($term)) {
                        $primary_keyword = $term->name;
                        aysa_debug_log('AYSA MEDIA: Using category name as keyword: ' . $primary_keyword);
                    }
                } elseif ($context_entity_type === 'product' || $context_entity_type === 'post') {
                    $post = get_post($context_entity_id);
                    if ($post) {
                        $primary_keyword = $post->post_title;
                        aysa_debug_log('AYSA MEDIA: Using product title as keyword: ' . $primary_keyword);
                    }
                }
            }
        } else {
            // No context (used from media library), keep primary keyword empty
            $primary_keyword = '';
            aysa_debug_log('AYSA MEDIA: No context provided, using empty primary keyword');
            
            // Only try fallbacks if we're in a post context (attachment has parent)
            $parent_post_id = $attachment->post_parent;
            if ($parent_post_id) {
                $parent_post = get_post($parent_post_id);
                if ($parent_post) {
                    $primary_keyword = $parent_post->post_title;
                    aysa_debug_log('AYSA MEDIA: Using parent post title as keyword: ' . $primary_keyword);
                }
            }
            
            // If still empty, use image filename as last resort
            if (empty($primary_keyword)) {
                $primary_keyword = pathinfo($image_url, PATHINFO_FILENAME);
                // Clean up filename for use as keyword
                $primary_keyword = str_replace(array('-', '_'), ' ', $primary_keyword);
                $primary_keyword = ucwords($primary_keyword);
                aysa_debug_log('AYSA MEDIA: Using cleaned filename as keyword: ' . $primary_keyword);
            }
        }
        
        // Get image context (surrounding content from the post if available)
        $image_context = '';
        $parent_post_id = $attachment->post_parent;
        if ($parent_post_id) {
            $parent_post = get_post($parent_post_id);
            if ($parent_post) {
                $image_context = wp_trim_words($parent_post->post_content, 100);
            }
        }
        
        // Make API request - pass the image URL along with other parameters
        $response = $this->request_alt_text_from_api($language, $primary_keyword, $tone, $target_audience, $image_context, $image_url, $secondary_keywords);
        
        // Log what language we're actually sending to the API
        aysa_debug_log('AYSA MEDIA: Sending to API - Language: ' . $language . ', Keyword: ' . $primary_keyword . ', Image URL: ' . $image_url);
        
        // If API fails, return an error
        if (!$response) {
            wp_send_json_error(array('message' => 'Failed to get response from API. Please check your API endpoint.'));
            return;
        }
        
        // Debug the response structure
        aysa_debug_log('AJAX DEBUG: Response type: ' . gettype($response));
        aysa_debug_log('AJAX DEBUG: Response: ' . json_encode($response));
        
        // Process response - be even more flexible about response format
        $alt_text = '';
        $title = '';
        $description = '';
        $caption = '';
        
        // Special handling for JSON string response
        if (is_string($response) && substr($response, 0, 1) === '{') {
            // Try to parse the JSON string
            $parsed = json_decode($response, true);
            
            if (json_last_error() === JSON_ERROR_NONE && is_array($parsed)) {
                aysa_debug_log('AJAX DEBUG: Successfully parsed JSON string response');
                
                // Extract alt text
                if (isset($parsed['alt_text'])) {
                    $alt_text = $parsed['alt_text'];
                }
                
                // Extract title
                if (isset($parsed['title'])) {
                    $title = $parsed['title'];
                }
                
                // Extract description
                if (isset($parsed['description'])) {
                    $description = $parsed['description'];
                }
                
                // Extract associated text for caption
                if (isset($parsed['associated_text'])) {
                    $caption = $parsed['associated_text'];
                }
            } else {
                // If parsing fails, use the whole string as alt text
                $alt_text = $response;
            }
        }
        // First handle direct string format (non-JSON)
        elseif (is_string($response)) {
            $alt_text = $response;
        }
        // Handle object format with various property names
        elseif (is_object($response)) {
            // Try all possible property names for alt text
            $alt_text_props = ['AltText', 'altText', 'alt_text', 'alternativeText', 'alternative_text', 'imageAltText', 'image_alt_text', 'alt', 'text'];
            foreach ($alt_text_props as $prop) {
                if (isset($response->$prop)) {
                    $alt_text = $response->$prop;
                    break;
                }
            }
            
            // Try all possible property names for title
            $title_props = ['Title', 'title', 'imageTitle', 'image_title'];
            foreach ($title_props as $prop) {
                if (isset($response->$prop)) {
                    $title = $response->$prop;
                    break;
                }
            }
            
            // Try all possible property names for description
            $desc_props = ['Description', 'description', 'desc', 'imageDescription', 'image_description', 'content'];
            foreach ($desc_props as $prop) {
                if (isset($response->$prop)) {
                    $description = $response->$prop;
                    break;
                }
            }
            
            // Try all possible property names for caption/associated text
            $caption_props = ['AssociatedText', 'associatedText', 'associated_text', 'caption', 'excerpt'];
            foreach ($caption_props as $prop) {
                if (isset($response->$prop)) {
                    $caption = $response->$prop;
                    break;
                }
            }
        }
        // Handle array format
        elseif (is_array($response)) {
            // Try to get first item or value that looks like alt text
            if (count($response) > 0) {
                $first_item = $response[0];
                
                if (is_string($first_item)) {
                    $alt_text = $first_item;
                }
                elseif (is_object($first_item)) {
                    // Try all possible property names for alt text
                    $alt_text_props = ['AltText', 'altText', 'alt_text', 'alternativeText', 'alternative_text', 'imageAltText', 'image_alt_text', 'alt', 'text'];
                    foreach ($alt_text_props as $prop) {
                        if (isset($first_item->$prop)) {
                            $alt_text = $first_item->$prop;
                            break;
                        }
                    }
                    
                    // Try all possible property names for title
                    $title_props = ['Title', 'title', 'imageTitle', 'image_title'];
                    foreach ($title_props as $prop) {
                        if (isset($first_item->$prop)) {
                            $title = $first_item->$prop;
                            break;
                        }
                    }
                    
                    // Try all possible property names for description
                    $desc_props = ['Description', 'description', 'desc', 'imageDescription', 'image_description', 'content'];
                    foreach ($desc_props as $prop) {
                        if (isset($first_item->$prop)) {
                            $description = $first_item->$prop;
                            break;
                        }
                    }
                    
                    // Try all possible property names for caption/associated text
                    $caption_props = ['AssociatedText', 'associatedText', 'associated_text', 'caption', 'excerpt'];
                    foreach ($caption_props as $prop) {
                        if (isset($first_item->$prop)) {
                            $caption = $first_item->$prop;
                            break;
                        }
                    }
                }
            }
        }
        
        // If we still don't have alt text, return detailed error
        if (empty($alt_text)) {
            $error_msg = 'Invalid API response: No alt text content found. ';
            $error_msg .= 'Response type: ' . gettype($response) . '. ';
            if (is_object($response) || is_array($response)) {
                $error_msg .= 'Response structure: ' . json_encode($response);
            } else {
                $error_msg .= 'Raw response: ' . $response;
            }
            wp_send_json_error(array('message' => $error_msg));
            return;
        }
        
        $confidence_score = null;
        if ($this->confidence_scorer) {
            $confidence_score = $this->confidence_scorer->calculate_image_confidence($attachment_id, $alt_text);
        }
        
        $old_alt_text = get_post_meta($attachment_id, '_wp_attachment_image_alt', true);
        
        // Update the alt text
        update_post_meta($attachment_id, '_wp_attachment_image_alt', sanitize_text_field($alt_text));
        
        // Log the action
        if ($this->audit_logger) {
            $this->audit_logger->log_action(
                'image_optimization',
                $attachment_id,
                'attachment',
                array('alt_text' => $old_alt_text),
                array('alt_text' => $alt_text),
                $confidence_score,
                false
            );
        }
        
        // Update the attachment title if we got one
        if (!empty($title)) {
            wp_update_post(array(
                'ID' => $attachment_id,
                'post_title' => sanitize_text_field($title)
            ));
        }
        
        // Update the attachment description if we got one
        if (!empty($description)) {
            wp_update_post(array(
                'ID' => $attachment_id,
                'post_content' => sanitize_textarea_field($description)
            ));
        }
        
        // Update the attachment caption if we got one
        if (!empty($caption)) {
            wp_update_post(array(
                'ID' => $attachment_id,
                'post_excerpt' => sanitize_textarea_field($caption)
            ));
        }
        
        // Trigger automation reporting
        do_action('aysa_automation_completed', array(
            'action_type' => 'image_optimization',
            'object_id' => $attachment_id,
            'object_type' => 'attachment',
            'confidence_score' => $confidence_score,
            'data' => array(
                'alt_text' => $alt_text,
                'title' => $title,
                'description' => $description,
                'caption' => $caption
            )
        ));
        
        // Success response
        wp_send_json_success(array(
            'message' => 'Alt text and metadata updated successfully!',
            'alt_text' => $alt_text,
            'title' => $title,
            'description' => $description,
            'caption' => $caption,
            'confidence_score' => $confidence_score,
            'api_source' => 'REAL API RESPONSE',
            'response_format' => gettype($response)
        ));
    }

    /**
     * Make API request to get alternative text for images
     *
     * @param string $language Language code
     * @param string $primary_keyword Primary keyword for SEO
     * @param string $tone Tone of the alt text
     * @param string $target_audience Target audience
     * @param string $image_context Context of the image
     * @param string $image_url URL of the image for AI analysis
     * @param array $secondary_keywords Secondary keywords for SEO
     * @return object|false Response object or false on error
     */
    private function request_alt_text_from_api($language, $primary_keyword, $tone, $target_audience, $image_context, $image_url, $secondary_keywords = array()) {
        $api_base = class_exists('Aysa_API_Config')
            ? rtrim(Aysa_API_Config::get_api_base_url(), '/')
            : 'https://api.aysa.ai';
        $api_url = $api_base . '/api/chatgpt/alternative-text-images';
        
        // Get project ID for API request
        $project_id = $this->get_project_id();
        if ($project_id <= 0) {
            aysa_debug_log('AYSA MEDIA: Legacy generator blocked because the installed project binding is missing.');
            return false;
        }
        
        // Build JSON payload with camelCase properties (C# standard)
        // ImageContext should be the image URL as per API specification
        $request_data = array(
            'language' => $language,
            'primaryKeyword' => $primary_keyword,
            'secondaryKeywords' => $secondary_keywords,
            'tone' => $tone,
            'targetAudience' => $target_audience,
            'imageContext' => $image_url,  // This should be the image URL as per API spec
            'projectId' => $project_id
        );
        
        // Log the request for debugging
        aysa_debug_log('API REQUEST: Making API POST request to: ' . $api_url);
        aysa_debug_log('API REQUEST: Request body: ' . json_encode($request_data));
        
        // Make a POST request with JSON body (instead of GET with query parameters)
        $response = wp_remote_post($api_url, array(
            'timeout' => 60,
            'sslverify' => true,  // Important for production URLs
            'headers' => array(
                'Content-Type' => 'application/json',
                'Accept' => 'application/json'
            ),
            'body' => json_encode($request_data)
        ));
        
        // Handle WP_Error responses
        if (is_wp_error($response)) {
            $error_message = $response->get_error_message();
            aysa_debug_log('API ERROR: Request failed: ' . $error_message);
            
            // Try alternative request methods if standard POST fails
            $alt_response = $this->try_alternative_request_methods($api_url, $request_data);
            if ($alt_response !== false) {
                aysa_debug_log('API RECOVERY: Alternate request method succeeded');
                return $alt_response;
            }
            
            return false;
        }
        
        $response_code = wp_remote_retrieve_response_code($response);
        $response_message = wp_remote_retrieve_response_message($response);
        aysa_debug_log('API RESPONSE: Status Code: ' . $response_code . ' ' . $response_message);
        
        // If response code indicates failure
        if ($response_code < 200 || $response_code >= 300) {
            aysa_debug_log('API ERROR: Bad response code: ' . $response_code);
            
            // Try alternative request methods if standard POST fails
            $alt_response = $this->try_alternative_request_methods($api_url, $request_data);
            if ($alt_response !== false) {
                aysa_debug_log('API RECOVERY: Alternate request method succeeded after bad response code');
                return $alt_response;
            }
        }
        
        $body = wp_remote_retrieve_body($response);
        aysa_debug_log('API RESPONSE: Body: ' . $body);

        // First check if it's valid JSON
        if (empty($body)) {
            aysa_debug_log('API ERROR: Empty response body');
            return false;
        }
        
        $data = json_decode($body);
        if (json_last_error() !== JSON_ERROR_NONE) {
            aysa_debug_log('API ERROR: Invalid JSON: ' . json_last_error_msg());
            aysa_debug_log('API ERROR: Raw response: ' . $body);
            return false;
        }
        
        // Check all possible response formats
        aysa_debug_log('API DEBUG: Response Type: ' . gettype($data));
        if (is_object($data)) {
            aysa_debug_log('API DEBUG: Object Properties: ' . json_encode(get_object_vars($data)));
        } elseif (is_array($data)) {
            aysa_debug_log('API DEBUG: Array Length: ' . count($data));
            if (!empty($data)) {
                aysa_debug_log('API DEBUG: First Item Type: ' . gettype($data[0]));
                if (is_object($data[0])) {
                    aysa_debug_log('API DEBUG: First Item Properties: ' . json_encode(get_object_vars($data[0])));
                }
            }
        } elseif (is_string($data)) {
            aysa_debug_log('API DEBUG: String Value: ' . $data);
        }
        
        return $data;
    }
    
    /**
     * Try alternative request methods if the standard method fails
     *
     * @param string $api_url The API URL
     * @param array $request_data The request data
     * @return mixed|false Response data or false on error
     */
    private function try_alternative_request_methods($api_url, $request_data) {
        // Never replay a potentially paid request and never weaken TLS. The
        // canonical Agent8 worker owns retries, idempotency and billing.
        return false;
    }

    /**
     * Create a fresh nonce via AJAX
     * 
     * @return void
     */
    public function ajax_create_nonce() {
        if (!self::legacy_alt_generator_enabled()) {
            wp_send_json_error(array('message' => 'Legacy media generator is disabled.'));
            return;
        }

        // Check if user is logged in
        if (!is_user_logged_in()) {
            wp_send_json_error(array('message' => 'User not logged in'));
            return;
        }
        
        if (!current_user_can('upload_files')) {
            wp_send_json_error(array('message' => 'You do not have permission to perform this action.'));
            return;
        }

        // This endpoint belongs only to the legacy media button. Never mint a
        // caller-selected nonce for unrelated AYSA actions.
        $nonce_action = 'aysa_nonce';
        $nonce = wp_create_nonce('aysa_nonce');
        
        // Return the nonce
        wp_send_json_success(array(
            'nonce' => $nonce,
            'action' => $nonce_action,
            'timestamp' => time()
        ));
    }

    /**
     * Get keyword from current editing context (category or product)
     */
    private function get_context_keyword() {
        // Check if we have context information from the request
        // 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.
        $context_entity_id = isset($_POST['context_entity_id']) ? intval((string) wp_unslash($_POST['context_entity_id'])) : 0;
        // 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.
        $context_entity_type = isset($_POST['context_entity_type']) ? sanitize_text_field((string) wp_unslash($_POST['context_entity_type'])) : '';
        
        if ($context_entity_id && $context_entity_type) {
            if ($context_entity_type === 'category' || $context_entity_type === 'term') {
                // Get keywords from new meta field
                $keywords = get_term_meta($context_entity_id, '_aysa_seo_keywords', true);
                if (!empty($keywords)) {
                    return $keywords;
                }
            } elseif ($context_entity_type === 'product' || $context_entity_type === 'post') {
                // Get keywords from new meta field
                $keywords = get_post_meta($context_entity_id, '_aysa_seo_keywords', true);
                if (!empty($keywords)) {
                    return $keywords;
                }
            }
        }
        
        return '';
    }
    
    /**
     * Get description from current editing context (category or product)
     */
    private function get_context_description() {
        // Check if we have context information from the request
        // 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.
        $context_entity_id = isset($_POST['context_entity_id']) ? intval((string) wp_unslash($_POST['context_entity_id'])) : 0;
        // 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.
        $context_entity_type = isset($_POST['context_entity_type']) ? sanitize_text_field((string) wp_unslash($_POST['context_entity_type'])) : '';
        
        if ($context_entity_id && $context_entity_type) {
            if ($context_entity_type === 'category' || $context_entity_type === 'term') {
                // Get category description
                $term = get_term($context_entity_id, 'product_cat');
                if ($term && !is_wp_error($term) && !empty($term->description)) {
                    return wp_trim_words($term->description, 100);
                }
            } elseif ($context_entity_type === 'product' || $context_entity_type === 'post') {
                // Get product content or excerpt
                $post = get_post($context_entity_id);
                if ($post) {
                    $content = !empty($post->post_excerpt) ? $post->post_excerpt : $post->post_content;
                    if (!empty($content)) {
                        return wp_trim_words($content, 100);
                    }
                }
            }
        }
        
        return '';
    }

    /**
     * Get language optimize value from current editing context (category or product)
     */
    public function get_context_language_optimize() {
        // Check if we have context information from the request
        // 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.
        $context_entity_id = isset($_POST['context_entity_id']) ? intval((string) wp_unslash($_POST['context_entity_id'])) : 0;
        // 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.
        $context_entity_type = isset($_POST['context_entity_type']) ? sanitize_text_field((string) wp_unslash($_POST['context_entity_type'])) : '';
        
        if ($context_entity_id && $context_entity_type) {
            if ($context_entity_type === 'category' || $context_entity_type === 'term') {
                // Get language optimize from category SEO settings
                $seo_settings = get_term_meta($context_entity_id, 'aysa_seo_settings', true);
                if (is_array($seo_settings) && !empty($seo_settings['language_optimize'])) {
                    return $seo_settings['language_optimize'];
                }
            } elseif ($context_entity_type === 'product' || $context_entity_type === 'post') {
                // Get language optimize from product/post meta
                $language_optimize = get_post_meta($context_entity_id, 'aysa_language_optimize', true);
                if (!empty($language_optimize)) {
                    return $language_optimize;
                }
            }
        }
        
        // If no context or no language found in context, try to get global SEO settings
        return $this->get_global_language_optimize();
    }
    
    /**
     * Get global language optimize value from project SEO settings
     */
    public function get_global_language_optimize() {
        // Check cache first to prevent repeated API calls
        $cache_key = 'aysa_global_language_optimize';
        $cached_language = get_transient($cache_key);
        
        if ($cached_language !== false) {
            return $cached_language;
        }
        
        // Get project ID
        $project_id = $this->get_project_id();
        if (!$project_id) {
            return null;
        }
        
        // Build API URL
        $api_base = class_exists('Aysa_API_Config')
            ? rtrim(Aysa_API_Config::get_api_base_url(), '/')
            : 'https://api.aysa.ai';
        $api_url = $api_base . '/api/SeoSettings/ByProject/' . $project_id;
        
        aysa_debug_log('AYSA MEDIA: Fetching global SEO settings from: ' . $api_url);
        
        // Make API request
        $response = wp_remote_get($api_url, array(
            'timeout' => 30,
            'headers' => array(
                'Authorization' => 'Bearer ' . get_option('aysa_auth_token', ''),
                'Content-Type' => 'application/json'
            )
        ));
        
        if (is_wp_error($response)) {
            aysa_debug_log('AYSA MEDIA: Error fetching global settings: ' . $response->get_error_message());
            return null;
        }
        
        $response_code = wp_remote_retrieve_response_code($response);
        if ($response_code !== 200) {
            aysa_debug_log('AYSA MEDIA: API returned status code: ' . $response_code);
            return null;
        }
        
        $body = wp_remote_retrieve_body($response);
        $data = json_decode($body, true);
        
        if (json_last_error() !== JSON_ERROR_NONE || !is_array($data)) {
            aysa_debug_log('AYSA MEDIA: Invalid JSON response: ' . json_last_error_msg());
            return null;
        }
        
        // Extract language optimize setting
        $language_optimize = null;
        if (isset($data['languageOptimize'])) {
            $language_optimize = $data['languageOptimize'];
            aysa_debug_log('AYSA MEDIA: Found global language optimize: ' . $language_optimize);
            
            // Cache for 5 minutes to reduce API calls
            set_transient($cache_key, $language_optimize, 5 * MINUTE_IN_SECONDS);
        } else {
            aysa_debug_log('AYSA MEDIA: Language optimize not found in response');
        }
        
        return $language_optimize;
    }
    
    /**
     * Read the installed site binding. Never discover or mutate tenant scope
     * from a media-library request.
     */
    private function get_project_id() {
        return intval(get_option('aysa_project_id', 0));
    }

    /**
     * Clear the new upload flag for an attachment
     *
     * @param int $attachment_id The ID of the attachment to clear.
     */
    public function clear_new_upload_flag($attachment_id) {
        delete_post_meta($attachment_id, '_aysa_new_upload');
        aysa_debug_log('AYSA MEDIA: Cleared new upload flag for attachment ID: ' . $attachment_id);
    }
}                                
