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

/**
 * MULTI-GPT MODEL INTEGRATION FOR SPECIALIZED TASKS
 * Each AI agent uses the optimal GPT model for their expertise
 */

// ══════════════════════════════════════════════════════════════
// ✅  SSE Streaming helper — used by both Jarvis and Consultation
// ══════════════════════════════════════════════════════════════
/**
 * Stream an OpenAI chat completion as Server-Sent Events.
 * Must be called AFTER SSE headers have been set and output buffers cleaned.
 *
 * @param array  $messages   OpenAI messages array
 * @param string $api_key    OpenAI API key
 * @param string $model      Model name (gpt-4o, gpt-5.2-…, etc.)
 * @param int    $max_tokens Max completion tokens
 * @param float  $temperature
 * @return array ['error' => string|null, 'text' => string]
 */
function vmo_stream_openai($messages, $api_key, $model, $max_tokens = 1000, $temperature = 0.7) {
    $data = [
        'model'       => $model,
        'messages'    => $messages,
        'temperature' => $temperature,
        'stream'      => true,
    ];

    // GPT-5.x → max_completion_tokens; older models → max_tokens
    if (strpos($model, 'gpt-5') !== false || strpos($model, 'o1') !== false || strpos($model, 'o3') !== false) {
        $data['max_completion_tokens'] = $max_tokens;
    } else {
        $data['max_tokens'] = $max_tokens;
    }

    // ═══════════════════════════════════════════════════════════════
    // ✅ TRUE REAL-TIME STREAMING via cURL CURLOPT_WRITEFUNCTION
    //
    // Previously this used wp_remote_post() which buffers the ENTIRE
    // OpenAI response before returning — meaning all tokens arrived
    // at the client simultaneously after a long wait.
    //
    // Now we use cURL directly with a write callback that echoes each
    // token to the browser THE INSTANT it arrives from OpenAI.
    // This enables progressive TTS to start speaking the first
    // sentence while the rest of the response is still generating.
    // ═══════════════════════════════════════════════════════════════

    $full_response = '';
    $sse_line_buffer = '';   // Accumulates partial SSE lines across cURL chunks

    $ch = curl_init('https://api.openai.com/v1/chat/completions');
    if (!$ch) {
        // cURL unavailable — fall back to wp_remote_post (buffered)
        return vmo_stream_openai_fallback($messages, $api_key, $model, $max_tokens, $temperature);
    }

    curl_setopt_array($ch, [
        CURLOPT_POST           => true,
        CURLOPT_HTTPHEADER     => [
            'Authorization: Bearer ' . $api_key,
            'Content-Type: application/json',
        ],
        CURLOPT_POSTFIELDS     => json_encode($data),
        CURLOPT_RETURNTRANSFER => false,  // Don't buffer — use write callback
        CURLOPT_TIMEOUT        => 120,
        CURLOPT_CONNECTTIMEOUT => 15,
        CURLOPT_SSL_VERIFYPEER => true,
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_MAXREDIRS      => 3,

        // ✅ KEY: Write callback fires for EVERY chunk received from OpenAI
        CURLOPT_WRITEFUNCTION  => function ($ch, $chunk) use (&$full_response, &$sse_line_buffer) {
            $sse_line_buffer .= $chunk;

            // Split on newlines — last element may be an incomplete line
            $lines = explode("\n", $sse_line_buffer);
            $sse_line_buffer = array_pop($lines); // Keep incomplete tail

            foreach ($lines as $line) {
                $line = trim($line);
                if ($line === '' || strpos($line, 'data: ') !== 0) continue;
                $json_str = substr($line, 6);
                if ($json_str === '[DONE]') continue;

                $json = json_decode($json_str, true);

                if (isset($json['choices'][0]['delta']['content'])) {
                    $token = $json['choices'][0]['delta']['content'];
                    $full_response .= $token;

                    // ✅ FIX: Filter out [[PHASE_COMPLETE]] markers from streamed tokens
                    $display_token = str_replace('[[PHASE_COMPLETE]]', '', $token);
                    if (strpos($full_response, '[[PHASE_COMPLETE]]') !== false) {
                        $full_response = str_replace('[[PHASE_COMPLETE]]', '', $full_response);
                    }

                    if ($display_token !== '') {
                        echo 'data: ' . wp_json_encode(['t' => $display_token]) . "\n\n";
                        if (ob_get_level()) ob_flush();
                        flush();
                    }
                }

                // Surface API errors that arrive mid-stream
                if (isset($json['error']['message'])) {
                    echo 'data: ' . wp_json_encode(['error' => $json['error']['message']]) . "\n\n";
                    if (ob_get_level()) ob_flush();
                    flush();
                }
            }

            return strlen($chunk); // Must return bytes processed
        },
    ]);

    $curl_ok = curl_exec($ch);
    $curl_err = curl_error($ch);
    $http_code = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    // Process any remaining data in the buffer
    if ($sse_line_buffer !== '') {
        $line = trim($sse_line_buffer);
        if ($line !== '' && strpos($line, 'data: ') === 0) {
            $json_str = substr($line, 6);
            if ($json_str !== '[DONE]') {
                $json = json_decode($json_str, true);
                if (isset($json['choices'][0]['delta']['content'])) {
                    $token = $json['choices'][0]['delta']['content'];
                    $full_response .= $token;
                    $display_token = str_replace('[[PHASE_COMPLETE]]', '', $token);
                    if ($display_token !== '') {
                        echo 'data: ' . wp_json_encode(['t' => $display_token]) . "\n\n";
                        if (ob_get_level()) ob_flush();
                        flush();
                    }
                }
                if (isset($json['error']['message'])) {
                    echo 'data: ' . wp_json_encode(['error' => $json['error']['message']]) . "\n\n";
                    flush();
                }
            }
        }
    }

    if (!$curl_ok && $full_response === '') {
        $err_msg = $curl_err ?: "OpenAI API error (HTTP {$http_code})";
        return ['error' => $err_msg, 'text' => ''];
    }

    if ($http_code >= 400 && $full_response === '') {
        return ['error' => "OpenAI API error (HTTP {$http_code})", 'text' => ''];
    }

    return ['error' => null, 'text' => $full_response];
}

/**
 * Fallback streaming function using wp_remote_post (buffered).
 * Used only if cURL extension is unavailable.
 */
function vmo_stream_openai_fallback($messages, $api_key, $model, $max_tokens = 1000, $temperature = 0.7) {
    $data = [
        'model'       => $model,
        'messages'    => $messages,
        'temperature' => $temperature,
        'stream'      => true,
    ];

    if (strpos($model, 'gpt-5') !== false || strpos($model, 'o1') !== false || strpos($model, 'o3') !== false) {
        $data['max_completion_tokens'] = $max_tokens;
    } else {
        $data['max_tokens'] = $max_tokens;
    }

    $full_response = '';

    $wp_response = wp_remote_post('https://api.openai.com/v1/chat/completions', [
        'timeout' => 90,
        'headers' => [
            'Authorization' => 'Bearer ' . $api_key,
            'Content-Type'  => 'application/json',
        ],
        'body' => wp_json_encode($data),
    ]);

    if (is_wp_error($wp_response)) {
        return ['error' => $wp_response->get_error_message(), 'text' => ''];
    }

    $http_code = wp_remote_retrieve_response_code($wp_response);
    $raw_body  = wp_remote_retrieve_body($wp_response);

    if ($http_code >= 400 && empty($raw_body)) {
        return ['error' => "OpenAI API error (HTTP {$http_code})", 'text' => ''];
    }

    $lines = explode("\n", $raw_body);
    foreach ($lines as $line) {
        $line = trim($line);
        if ($line === '' || strpos($line, 'data: ') !== 0) continue;
        $json_str = substr($line, 6);
        if ($json_str === '[DONE]') continue;
        $json = json_decode($json_str, true);
        if (isset($json['choices'][0]['delta']['content'])) {
            $token = $json['choices'][0]['delta']['content'];
            $full_response .= $token;
            $display_token = str_replace('[[PHASE_COMPLETE]]', '', $token);
            if (strpos($full_response, '[[PHASE_COMPLETE]]') !== false) {
                $full_response = str_replace('[[PHASE_COMPLETE]]', '', $full_response);
            }
            if ($display_token !== '') {
                echo 'data: ' . wp_json_encode(['t' => $display_token]) . "\n\n";
                if (ob_get_level()) ob_flush();
                flush();
            }
        }
        if (isset($json['error']['message'])) {
            echo 'data: ' . wp_json_encode(['error' => $json['error']['message']]) . "\n\n";
            flush();
        }
    }

    return ['error' => null, 'text' => $full_response];
}

/**
 * Get optimal GPT model for specific task type
 */
function vmo_get_optimal_model($task_type = 'general', $context = []) {
    if (function_exists('vmo_get_routed_model')) {
        if (!array_key_exists('skip_log', $context)) {
            $context['skip_log'] = true;
        }
        return vmo_get_routed_model($task_type, $context);
    }

    return defined('VMO_OPENAI_MODEL') ? VMO_OPENAI_MODEL : 'gpt-5.4';
}

/**
 * Enhanced OpenAI API call with model optimization
 */
function vmo_call_specialized_ai($prompt, $task_type = 'general', $additional_params = []) {
    $api_key = get_option('vmo_openai_api_key');
    if (!$api_key) {
        return ['error' => 'OpenAI API key is missing'];
    }
    
    // ✅ TOKEN DEDUCTION v8.1.0: Charge for specialized AI calls based on task type
    $user_id = get_current_user_id();
    $token_costs = [
        'strategy_analysis' => 800,
        'legal_documents' => 700,
        'seo_optimization' => 500,
        'content_creation' => 600,
        'business_planning' => 800,
        'website_building' => 1000,
        'consultation' => 300,
        'competitor_research' => 600,
        'general' => 400
    ];
    $token_cost = $token_costs[$task_type] ?? 400;
    
    if (function_exists('vmo_deduct_tokens')) {
        if (!vmo_deduct_tokens($user_id, $token_cost, $task_type, 'Specialized AI: ' . $task_type)) {
            return ['error' => 'Insufficient tokens. Please top up your balance.'];
        }
    }

    $route_context = [
        'prompt' => $prompt,
        'user_id' => $user_id,
        'plan' => get_user_meta($user_id, 'vmo_subscription_status', true),
        'requires_generation' => in_array($task_type, ['content_creation', 'website_building', 'legal_documents'], true),
    ];
    $route = function_exists('vmo_get_openai_route')
        ? vmo_get_openai_route($task_type, $route_context)
        : ['model' => vmo_get_optimal_model($task_type, $route_context), 'fallback_model' => defined('VMO_OPENAI_FAST_MODEL') ? VMO_OPENAI_FAST_MODEL : null, 'task' => $task_type];

    $model = $route['model'];
    $fallback_model = $route['fallback_model'] ?? null;
    $actual_model_used = $model;
    
    // Task-specific configurations
    // Token limits per task type (temperature + token budget)
    $config = [
        'strategy_analysis' => ['temperature' => 0.3, '_token_limit' => 4000],
        'legal_documents' => ['temperature' => 0.1, '_token_limit' => 4000],
        'seo_optimization' => ['temperature' => 0.2, '_token_limit' => 3000],
        'content_creation' => ['temperature' => 0.7, '_token_limit' => 4000],
        'business_planning' => ['temperature' => 0.3, '_token_limit' => 4000],
        'website_building' => ['temperature' => 0.4, '_token_limit' => 4000],
        'consultation' => ['temperature' => 0.5, '_token_limit' => 2000],
        'competitor_research' => ['temperature' => 0.2, '_token_limit' => 4000],
    ];

    $task_config = $config[$task_type] ?? ['temperature' => 0.7, '_token_limit' => 2000];

    // ✅ FIX: GPT-5.2 requires max_completion_tokens, not max_tokens
    $_tl = $task_config['_token_limit'] ?? 2000;
    unset($task_config['_token_limit']);
    $task_config += function_exists('vmo_get_token_param') ? vmo_get_token_param($model, $_tl) : ['max_tokens' => $_tl];
    
    // Attach consultation profile context when available
    $profile = array();
    try {
        if (function_exists('vmo_get_consultation_profile')) {
            $profile = vmo_get_consultation_profile();
        }
    } catch (Exception $e) {
        error_log('VMO: Could not load consultation profile: ' . $e->getMessage());
    }
    
    $profile_system = '';
    if (!empty($profile)) {
        $profile_system = "BUSINESS CONSULTATION PROFILE (use this as ground truth):\n" . substr(wp_json_encode($profile, JSON_PRETTY_PRINT), 0, 6000);
    }

    $body = array_merge([
        'model' => $model,
        'messages' => [
            [
                'role' => 'system',
                'content' => trim(vmo_get_system_prompt($task_type) . "\n\n" . $profile_system)
            ],
            [
                'role' => 'user', 
                'content' => $prompt
            ]
        ],
    ], $task_config, $additional_params);

    $response = wp_remote_post('https://api.openai.com/v1/chat/completions', [
        'headers' => [
            'Authorization' => 'Bearer ' . $api_key,
            'Content-Type' => 'application/json',
        ],
        'body' => wp_json_encode($body),
        'timeout' => 120,
        'sslverify' => true,
    ]);

    if ((is_wp_error($response) || wp_remote_retrieve_response_code($response) >= 400) && !empty($fallback_model) && $fallback_model !== $model) {
        error_log("VMO: Model '$model' failed in vmo_call_specialized_ai. Retrying with {$fallback_model}.");

        $body['model'] = $fallback_model;
        if (isset($body['max_completion_tokens']) && !preg_match('/^(gpt-5|o1|o3)/i', $fallback_model)) {
            $body['max_tokens'] = $body['max_completion_tokens'];
            unset($body['max_completion_tokens']);
        }
        if (isset($body['max_tokens']) && preg_match('/^(gpt-5|o1|o3)/i', $fallback_model)) {
            $body['max_completion_tokens'] = $body['max_tokens'];
            unset($body['max_tokens']);
        }

        $response = wp_remote_post('https://api.openai.com/v1/chat/completions', [
            'headers' => [
                'Authorization' => 'Bearer ' . $api_key,
                'Content-Type' => 'application/json',
            ],
            'body' => wp_json_encode($body),
            'timeout' => 120,
            'sslverify' => true,
        ]);
        $actual_model_used = $fallback_model;
    }

    if (is_wp_error($response)) {
        return ['error' => $response->get_error_message()];
    }

    $response_body = wp_remote_retrieve_body($response);
    $data = json_decode($response_body, true);

    if (isset($data['choices'][0]['message']['content'])) {
        return [
            'success' => true,
            'content' => $data['choices'][0]['message']['content'],
            'model_used' => $actual_model_used,
            'task_type' => $task_type,
            'route_used' => $route['task'] ?? $task_type
        ];
    }

    return ['error' => 'Invalid API response', 'raw_response' => $data];
}

/**
 * Get specialized system prompts for each task type
 */
function vmo_get_system_prompt($task_type) {
    $prompts = [
        'strategy_analysis' => "You are a McKinsey-level strategy consultant with 20+ years experience. Provide data-driven insights, specific competitor analysis, and actionable strategic recommendations with realistic timelines and market share projections.",
        
        'legal_documents' => "You are a corporate legal specialist with expertise in business formation, compliance, and risk management. Generate accurate, comprehensive legal documents appropriate for the specific business type and jurisdiction.",
        
        'seo_optimization' => "You are an SEO expert specializing in technical optimization, local search, and competitive analysis. Provide specific, implementable SEO strategies that will dominate search rankings.",
        
        'content_creation' => "You are a conversion-focused copywriter and content strategist. Create compelling, persuasive content that converts visitors into customers while maintaining brand voice and expertise.",
        
        'business_planning' => "You are a business planning expert with MBA-level financial modeling skills. Create realistic financial projections, growth strategies, and comprehensive business plans with specific metrics and timelines.",
        
        'website_building' => "You are a premium digital experience director and full-stack web developer. Generate cinematic, conversion-optimized websites that feel custom, media-rich, mobile-first, and SEO-optimized. Avoid brochure-basic layouts. Use coherent text color systems, premium motion, layered compositions, glass or translucent CTA surfaces, and strong visual storytelling. Never use multicolor or gradient text for headings or body copy.",
        
        'consultation' => "You are a world-class business consultant combining McKinsey expertise with startup mentorship. Ask probing questions that reveal business potential and guide strategic thinking.",
        
        'competitor_research' => "You are a competitive intelligence analyst. Provide detailed competitor research with specific company names, strategies, market positioning, and actionable insights for competitive advantage."
    ];

    return $prompts[$task_type] ?? "You are a helpful AI assistant specializing in business and website development.";
}

/**
 * Replace [GENERATED_IMAGE: desc] / [GENERATED_VIDEO: desc]
 * with placeholder DIVs your CSS/JS can style & hook into.
 * Each placeholder gets a unique media ID for replace button functionality.
 */
function vmo_process_generated_images( $html ) {
    // Image placeholders with unique IDs
    $html = preg_replace_callback(
        '/\[GENERATED_IMAGE:\s*(.*?)\]/i',
        function ( $m ) {
            $desc = sanitize_text_field( $m[1] );
            $mediaId = 'media_' . wp_generate_password(8, false);
            return '<div class="vmo-media-placeholder vmo-media-placeholder-image" data-type="image" data-media-id="' 
                . esc_attr( $mediaId ) . '" aria-label="'
                . esc_attr( $desc )
                . '" data-vmo-generate="true" data-vmo-prompt="'
                . esc_attr( $desc )
                . '"><span>Image<br><small>' . esc_html( $desc ) . '</small></span></div>';
        },
        $html
    );
    // Video placeholders with unique IDs
    $html = preg_replace_callback(
        '/\[GENERATED_VIDEO:\s*(.*?)\]/i',
        function ( $m ) {
            $desc = sanitize_text_field( $m[1] );
            $mediaId = 'media_' . wp_generate_password(8, false);
            return '<div class="vmo-media-placeholder vmo-media-placeholder-video" data-type="video" data-media-id="' 
                . esc_attr( $mediaId ) . '" aria-label="'
                . esc_attr( $desc )
                . '" data-vmo-sora="true" data-vmo-sora-prompt="'
                . esc_attr( $desc )
                . '"><span>Video<br><small>' . esc_html( $desc ) . '</small></span></div>';
        },
        $html
    );
    return $html;
}

/**
 * Master system prompt: Maximum creativity, intelligence, and sophisticated web design capabilities.
 */
$VMO_STYLE_DIRECTIVES = <<<'STYLE'
You are Jerreme, an advanced AI with exceptional creative abilities, expert copywriting skills, and professional knowledge in modern web design, content creation, and user experience. You MUST follow instructions EXACTLY and provide complete, professional copy content as requested.

**CORE INTELLIGENCE CAPABILITIES**:

1. **PROFESSIONAL COPYWRITING**: Write compelling, engaging, and professional copy for any topic, industry, or business. Generate complete articles, blog posts, marketing copy, and business content with appropriate tone, style, and length as specified by the user.

2. **CONTENT STRUCTURE MASTERY**: Create well-organized content with proper headings, subheadings, paragraphs, lists, and logical flow. Always include engaging introductions, detailed body content, and strong conclusions.

3. **INDUSTRY EXPERTISE**: Demonstrate deep knowledge across all industries and topics. Research-level understanding of business, technology, photography, automotive, healthcare, finance, and any subject matter requested.

4. **PRECISE WORD COUNT CONTROL**: Generate content to exact specifications - whether user wants 500 words, 2000 words, or any specific length. Always match the requested word count or character count precisely.

5. **TONE AND STYLE ADAPTATION**: Adapt writing style to match user requirements - professional, casual, technical, marketing-focused, educational, persuasive, or any specified tone.

6. **COMPLETE SECTION GENERATION**: When creating sections like "features," "about us," "services," etc., provide comprehensive content with detailed descriptions, benefits, and engaging copy that businesses can use directly.

**CONTENT GENERATION RULES**:
- **COMPLETE COPY**: Always provide full, professional copy content for every section, feature, or element requested
- **DETAILED DESCRIPTIONS**: Write comprehensive descriptions, not just placeholders or bullet points
- **ENGAGING HEADLINES**: Create compelling headlines and subheadings that grab attention
- **CALL-TO-ACTION**: Include strong calls-to-action where appropriate
- **BUSINESS FOCUS**: When writing for businesses, emphasize benefits, solutions, and competitive advantages
- **COMPREHENSIVE COVERAGE**: Cover all aspects of the requested topic thoroughly
- **TEXT COLOR DISCIPLINE**: Keep headings and body copy on a coherent single text-color system. Never use rainbow text, multiple heading colors, or gradient-filled text.

**TECHNICAL MASTERY**: Expert in HTML5, CSS3, modern JavaScript (ES6+), React 18, Next.js App Router, popular frameworks (GSAP, Splide, AOS, Three.js, Framer Motion, etc.), and advanced CSS techniques (Grid, Flexbox, custom properties, animations, transforms). Structure React components using Next.js conventions ('use client' directives, page/layout patterns).

**CRITICAL EXECUTION RULES**:
- Follow instructions with surgical precision
- Generate complete, professional copy content as requested
- Never add explanatory text unless requested
- Understand context and user intent perfectly
- Be as intelligent as the most advanced AI models
- Users should feel they're working with the smartest AI possible
- Match exact word count or length specifications when provided

**ELEMENT ISOLATION & PROTECTION**:
- **PRESERVE OTHER ELEMENTS**: NEVER modify, move, or affect elements that are not being specifically targeted
- **SURGICAL MODIFICATIONS**: Only change the exact element or section being refined
- **Z-INDEX PRESERVATION**: Maintain existing z-index layers unless specifically asked to change them
- **CONTENT ISOLATION**: When modifying one element, ensure surrounding elements remain untouched
- **LAYER MANAGEMENT**: Allow multiple elements to coexist on the same spot without conflicts through proper z-index management
- **REFINEMENT BOUNDARIES**: Changes should be confined to the specific element or section mentioned in the user's request

**REFINEMENT PRECISION RULES**:
- **EXACT TARGET MODIFICATIONS**: When user says "change the button color in section 2", ONLY modify that specific button, leave everything else untouched
- **SECTION BOUNDARY RESPECT**: When modifying section 2, NEVER affect sections 1, 3, 4, etc.
- **ELEMENT-LEVEL PRECISION**: When changing one flip card, preserve all other flip cards exactly as they are
- **PRESERVE FUNCTIONALITY**: When replacing images, maintain the existing HTML structure and functionality
- **NO SCOPE CREEP**: Never add sections, elements, or content not explicitly requested
- **MAINTAIN STATE**: Preserve all existing content, styling, and interactions unless specifically asked to change them

**MEDIA REPLACEMENT PROTECTION**:
- **PRESERVE HTML STRUCTURE**: When user replaces image in flip card, maintain the existing div structure, classes, and functionality
- **PROTECT SIBLINGS**: Changing one element must never affect its siblings or parent containers
- **MAINTAIN FLIP FUNCTIONALITY**: Image replacement should not break flip animations or interactions
- **PRESERVE TEXT AREAS**: Keep text content areas separate from image areas during media replacement

**SEMANTIC MARKUP & STRUCTURE**
- Always wrap sections in: `<div class="vmo-section" id="section-N"><!-- SECTION N --> ... <!-- END SECTION N --></div>`
- Use semantic HTML5 elements: `<header>`, `<main>`, `<section>`, `<article>`, `<aside>`, `<nav>`, `<footer>`
- Proper heading hierarchy (`<h1>`, `<h2>`, `<h3>`) with meaningful content
- Rich text formatting with `<p>`, `<ul>`, `<ol>`, `<blockquote>`, `<strong>`, `<em>`
- Interactive elements: `<button class="vmo-btn">`, `<form>`, `<input>`, `<textarea>`

**MEDIA PLACEHOLDER SYSTEM - CRITICAL**
- For **every** image: `[GENERATED_IMAGE: Detailed description of the image needed]`
- For **every** video: `[GENERATED_VIDEO: Detailed description of the video content]`
- Make descriptions specific and contextual to the content
- NEVER use `<img>` or `<video>` tags directly - only placeholders
- ALWAYS generate placeholders for carousels, galleries, hero images, backgrounds, logos, etc.
- For carousels: Generate multiple placeholders with exact counts (e.g., 10 placeholders for 10-image carousel)
- For interactive elements: Ensure placeholders behave like final media (timing, transitions, etc.)

**MEDIA PLACEHOLDER DIMENSIONS & STYLING - ESSENTIAL**:
- **MAINTAIN ASPECT RATIOS**: Every media placeholder must have explicit dimensions that match its intended use
- **ECOMMERCE PRODUCT IMAGES**: Use 300x300px for grid thumbnails, 600x600px for hero product images, 150x150px for gallery thumbnails
- **HERO SECTION IMAGES**: Use full viewport dimensions (100vw, 70vh) with proper object-fit cover
- **CARD IMAGES**: Use consistent aspect ratios (16:9 for landscape, 1:1 for square, 4:3 for traditional)
- **ICON PLACEHOLDERS**: Use 80x80px for feature icons, 40x40px for small icons, 120x120px for large feature icons
- **PLACEHOLDER STYLING**: Include these critical CSS properties on every placeholder:
  ```css
  .vmo-media-placeholder {
    width: [specific-width];
    height: [specific-height];
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: white;
    font-weight: bold;
    text-align: center;
    object-fit: cover;
    transition: all 0.3s ease;
  }
  ```
- **PERFECT REPLACEMENT BEHAVIOR**: Placeholders must be styled so that when replaced with actual media, the layout remains identical
- **RESPONSIVE PLACEHOLDERS**: Use CSS that maintains proportions across all device sizes
- **CONSISTENT CONTAINER STRUCTURE**: Wrap placeholders in proper containers that preserve layout integrity

**FLIP CARD & INTERACTIVE ELEMENT STRUCTURE**:
- **SEPARATE IMAGE AND TEXT AREAS**: In flip cards, keep image placeholders in dedicated containers separate from text content
- **PRESERVE FLIP STRUCTURE**: Use proper front/back div structure for flip animations
- **MAINTAIN HOVER FUNCTIONALITY**: Ensure flip interactions work correctly with placeholders
- **PROTECT TEXT CONTENT**: Keep feature names, descriptions, and details in separate text-only containers
- **EXAMPLE FLIP CARD STRUCTURE**:
```html
<div class="flip-card">
  <div class="flip-card-inner">
    <div class="flip-card-front">
      <div class="image-container">[GENERATED_IMAGE: BMW 7 Series exterior detail]</div>
      <h3>Advanced Lighting</h3>
    </div>
    <div class="flip-card-back">
      <h3>Advanced Lighting Technology</h3>
      <p>Detailed description of the lighting features...</p>
    </div>
  </div>
</div>
```

**SECTION-AWARE OPERATIONS**
- **SECTION NUMBERING**: Always maintain sequential section numbers (1, 2, 3, etc.)
- **SECTION MODIFICATION**: When asked to modify "section 3", only change that specific section
- **SECTION INSERTION**: When inserting into "section 2 background", modify existing section 2
- **NEW SECTION CREATION**: Only when explicitly requested or when logical
- **SECTION POSITIONING**: When creating new sections, place them where instructed (above/below specific sections)
- **SECTION RENUMBERING**: After any structural changes, renumber all sections sequentially

**ADVANCED VISUAL TECHNIQUES**
- **Parallax & Scroll Effects**: Implement with GSAP ScrollTrigger, CSS transforms, and scroll-timeline
- **Complex Animations**: Use CSS animations, GSAP, and custom JavaScript for sophisticated interactions
- **Responsive Design**: Mobile-first approach with sophisticated breakpoints
- **Visual Hierarchy**: Expert typography, spacing, and color relationships
- **Micro-interactions**: Hover effects, loading states, and smooth transitions
- **PREMIUM SURFACES**: Use glass, translucent, editorial, or dimensional button and card treatments instead of ordinary flat controls
- **MEDIA-LED STORYTELLING**: Use overlays, depth, and cinematic media composition so the website feels premium rather than brochure-basic

**COMPLEX LAYOUT CAPABILITIES**
- **Advanced Grid Systems**: Custom CSS Grid and Flexbox layouts
- **Layered Compositions**: Z-index management, overlays, and complex positioning
- **Background Techniques**: Video backgrounds, image overlays, gradient combinations
- **Background Image Placement**: CRITICAL - When inserting background images, ensure they are positioned with proper CSS:
  - Use `background-image: url()` on section elements with MANDATORY min-height
  - Set `background-size: cover`, `background-position: center`, and `min-height: 60vh`
  - Add `padding: 4rem 2rem` to ensure content spacing and background visibility
  - Apply `position: relative; z-index: 1` to background elements
  - Ensure text/foreground content has `position: relative; z-index: 2` or higher
  - NEVER place backgrounds outside iframe viewport - always within section containers
  - For section backgrounds, modify the section element itself, NOT create separate background divs
  - MANDATORY: All background sections must have visible height and proper content positioning
- **Carousel & Sliders**: Implement with Splide.js or custom solutions with proper placeholder counts
- **Modal & Popup Systems**: Custom JavaScript implementations

**SCROLL-BASED INTERACTIONS**
- **Scroll-triggered animations**: Elements appearing, transforming, or changing as user scrolls
- **Horizontal scroll sections**: Sections that scroll horizontally while main scroll is vertical
- **Scroll-paused effects**: Temporarily pause vertical scroll for horizontal interactions
- **Progressive disclosure**: Content that reveals itself based on scroll position

**SECTION MANAGEMENT RULES**
1. **Full Page Return**: ALWAYS return complete HTML with all sections, never partial content
2. **Section Preservation**: Maintain all existing sections unless explicitly asked to modify
3. **Numbered Sections**: Keep sequential numbering (1, 2, 3, etc.) from top to bottom
4. **Context Awareness**: Understand relationships between sections and maintain consistency
5. **Targeted Modifications**: When asked to change "section X", only modify that section
6. **Precise Instructions**: Follow exact user instructions about section placement and modifications

**INTELLIGENT REFINEMENT**
- **Internal Processing**: When given complex requests, internally break them down into steps
- **Creative Interpretation**: Enhance user requests with professional design insights
- **Error Prevention**: Anticipate and prevent common layout and interaction issues
- **Performance Optimization**: Write efficient CSS and JavaScript
- **Section Intelligence**: Understand section context and maintain structural integrity

**PROFESSIONAL QUALITY**
- **Magazine-level design**: Create layouts that rival professional publications
- **Brand consistency**: Maintain design language throughout the page
- **Accessibility**: Proper ARIA labels, semantic structure, and keyboard navigation
- **Cross-browser compatibility**: Use modern techniques with appropriate fallbacks

**OUTPUT REQUIREMENTS - CRITICAL**
- Return clean, production-ready HTML ONLY
- No markdown formatting or code fences
- Proper indentation and structure
- Include all necessary CSS and JavaScript inline
- Use modern, semantic, and accessible markup
- NEVER include comments, explanations, or descriptions in the generated HTML
- NEVER add unrequested content, sections, or features
- FOLLOW USER INSTRUCTIONS EXACTLY - do not interpret or add extra functionality
- If user says "insert video into section 1 background", do EXACTLY that - don't create new sections
- If user says "move video from section 2 to section 1 background and delete section 2", do EXACTLY that

**STRICT RULES FOR USER INSTRUCTIONS**
- Read user instructions word-for-word and follow them precisely
- Do not add extra content, sections, or features not requested
- Do not create new sections unless explicitly asked
- Do not add explanatory text, buttons, or content not requested
- When moving content between sections, preserve existing content unless told to replace it
- When deleting sections, remove them completely and renumber remaining sections
- NEVER comment in the HTML output - provide clean code only

Remember: You are creating professional, sophisticated web experiences that exceed user expectations through intelligent design and technical excellence while maintaining perfect section awareness, placeholder generation, and EXACT adherence to user instructions.
**COMPLETE COPY WRITING CAPABILITIES**

When users request content creation (blog posts, features, about pages, etc.), provide comprehensive, professional copy:

**CONTENT DEPTH REQUIREMENTS**:
- **COMPLETE ARTICLES**: Write full articles with introduction, body paragraphs, and conclusion
- **DETAILED FEATURES**: Provide comprehensive feature descriptions with benefits and technical details  
- **BUSINESS COPY**: Write compelling marketing copy that converts visitors to customers
- **INDUSTRY EXPERTISE**: Demonstrate deep knowledge of the subject matter requested
- **ENGAGEMENT FOCUS**: Write content that keeps readers engaged and encourages action

**COPY WRITING EXAMPLES**:

For "Photography Business Blog":
- Write complete history section (500+ words)
- Detail evolution timeline with key figures and innovations
- Explain various photography techniques with technical depth
- Cover business photography challenges and solutions comprehensively
- Present user's company as the premier choice with specific competitive advantages
- Include compelling calls-to-action and website integration

For "BMW Features Section":
- Write detailed feature descriptions (100-150 words each)
- Include technical specifications and benefits
- Use automotive expertise and industry terminology
- Create engaging headlines for each feature
- Emphasize luxury, performance, and innovation themes

**WORD COUNT COMPLIANCE**:
- Always match specified word counts exactly
- If user requests "2000 words", deliver exactly 2000 words
- Distribute content appropriately across sections
- Maintain quality while meeting length requirements

**TONE AND STYLE MATCHING**:
- Professional business tone for corporate content
- Engaging and informative for blog posts
- Technical but accessible for feature descriptions  
- Persuasive and compelling for marketing copy
- Adapt to any specified style or industry requirements

**UNIVERSAL BUSINESS ENGINES (BACKEND CAPABILITIES)**
You have access to powerful backend engines. Use these shortcodes to deploy full functional systems instantly:

1. **AFFILIATE SYSTEM**:
   - `[vmo_affiliate_registration]`: Registration form for partners.
   - `[vmo_affiliate_dashboard]`: Partner dashboard (stats, links, payouts).
   - `[vmo_affiliate_link]`: Generates referral links.

2. **MEMBERSHIP SYSTEM**:
   - `[vmo_login_form]`: Secure login form.
   - `[vmo_registration_form]`: User registration.
   - `[vmo_user_dashboard]`: Member profile and content access.
   - `[vmo_protected_content plan="premium"]...[/vmo_protected_content]`: Restrict content.
   - `[vmo_member_list]`: (Admin) View all members.

3. **TICKETING & SUPPORT SYSTEM**:
   - `[vmo_support_ticket_form]`: Frontend submission form.
   - `[vmo_ticket_manager]`: (Admin) Manage all support tickets.
   - `[vmo_my_tickets]`: User's ticket history.

**DEPLOYMENT INSTRUCTIONS**:
- When a user asks for a "Hotel Booking System", "Event Site", or "Membership Site", DO NOT say you can't do it.
- Instead, build the frontend using your design skills and EMBED these shortcodes to handle the logic.
- Example: For a Hotel site, use `[vmo_support_ticket_form]` styled as a "Booking Request" form, or `[vmo_protected_content]` for member-only rates.
- You are no longer just a brochure builder. You are a FUNCTIONAL BUSINESS BUILDER.

STYLE;


/*==========================================================================
= AJAX: Generate or refine full page / multi-section (vmo_generate_content) =
==========================================================================*/
add_action( 'wp_ajax_vmo_generate_content', function() use ( $VMO_STYLE_DIRECTIVES ) {
    // Dual-nonce validation: accept either admin nonce (nonce) or builder nonce (security)
    $admin_nonce   = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
    $builder_nonce = isset($_POST['security']) ? sanitize_text_field(wp_unslash($_POST['security'])) : '';

    $admin_ok   = $admin_nonce && wp_verify_nonce($admin_nonce, 'vmo_admin_nonce');
    $builder_ok = $builder_nonce && wp_verify_nonce($builder_nonce, 'vmo_builder_nonce');

    if (!($admin_ok || $builder_ok)) {
        wp_send_json_error(['message' => 'Security check failed', 'status' => 'invalid_nonce']);
    }
    
    // For basic generation, consultation profile is optional - allows more flexible usage
    if (!function_exists('vmo_get_consultation_profile')) {
        require_once plugin_dir_path(__FILE__) . 'consultation-profile.php';
    }

    $api_key = get_option( 'vmo_openai_api_key' );
    if ( ! $api_key ) {
        wp_send_json_error([ 'message' => 'OpenAI API key is missing.' ]);
    }

    $grapes_api_key = trim((string) get_option('vmo_grapesjs_api_key', ''));
    if ($grapes_api_key === '') {
        wp_send_json_error([ 'message' => 'GrapesJS API key is required. Please add it in Settings before generating websites.' ]);
    }

    // 🔒 Token validation - Check if user has sufficient tokens for content generation
    $user_id = get_current_user_id();
    
    // Include token manager if not already included
    if (!function_exists('vmo_check_token_balance')) {
        require_once plugin_dir_path(__FILE__) . 'token-manager.php';
    }
    
    if (!function_exists('vmo_check_token_balance')) {
        wp_send_json_error(['message' => 'Token system not available.']);
    }
    
    // Ensure user has a valid plan with tokens
    $current_tokens = vmo_get_token_balance($user_id);
    // No free tokens — users must purchase a plan to generate content
    
    if (!vmo_check_token_balance($user_id, 'content')) {
        $required_tokens = vmo_get_token_cost('content');
        wp_send_json_error([
            'message' => 'Insufficient tokens. You need ' . $required_tokens . ' tokens to generate content. Current balance: ' . $current_tokens,
            'code' => 'insufficient_tokens',
            'current_balance' => $current_tokens,
            'required' => $required_tokens
        ]);
    }

    // 1. Get chat array
    $chat_raw = wp_unslash($_POST['chat'] ?? '[]');
    $chat = json_decode($chat_raw, true);
    if ( ! is_array( $chat ) ) {
        $chat = [];
    }
    foreach ($chat as &$msg) {
        if (isset($msg['role'])) $msg['role'] = sanitize_text_field($msg['role']);
        if (isset($msg['content'])) $msg['content'] = wp_kses_post($msg['content']);
    }
    unset($msg);

    $prompt = sanitize_textarea_field(wp_unslash($_POST['prompt'] ?? ''));
    if ($prompt === '') {
        for ($i = count($chat) - 1; $i >= 0; $i--) {
            if (($chat[$i]['role'] ?? '') === 'user') {
                $prompt = sanitize_textarea_field($chat[$i]['content'] ?? '');
                if ($prompt !== '') {
                    break;
                }
            }
        }
    }
    if ($prompt === '') {
        wp_send_json_error([ 'message' => 'Prompt is required.' ]);
    }

    // 2. Consultation + deep research context
    $profile = [];
    if (!function_exists('vmo_get_consultation_profile')) {
        require_once plugin_dir_path(__FILE__) . 'consultation-profile.php';
    }
    if (function_exists('vmo_get_consultation_profile')) {
        $profile = vmo_get_consultation_profile($user_id);
    }

    $extracted = is_array($profile['extracted_information'] ?? null) ? $profile['extracted_information'] : [];
    $business_name = '';
    foreach (['business_name', 'businessName', 'company_name', 'companyName', 'brand_name'] as $name_key) {
        if (!empty($extracted[$name_key])) {
            $business_name = sanitize_text_field((string) $extracted[$name_key]);
            break;
        }
    }
    if ($business_name === '') {
        $business_name = sanitize_text_field((string) get_bloginfo('name'));
    }

    $phone_number = get_user_meta($user_id, 'vmo_business_phone', true);
    if (empty($phone_number)) $phone_number = get_user_meta($user_id, 'vmo_phone_number', true);
    if (empty($phone_number)) $phone_number = get_user_meta($user_id, 'vmo_twilio_phone_number', true);
    if (is_array($phone_number)) $phone_number = (string) ($phone_number['number'] ?? '');
    $phone_number = sanitize_text_field((string) $phone_number);

    $business_email = '';
    foreach (['businessEmail', 'business_email', 'supportEmail', 'support_email', 'email'] as $email_key) {
        if (!empty($extracted[$email_key])) {
            $business_email = sanitize_email((string) $extracted[$email_key]);
            break;
        }
    }

    $industry_insights = [];
    if (function_exists('vmo_get_cached_industry_insights')) {
        $industry_insights = vmo_get_cached_industry_insights($user_id);
    }

    $profile_snippet = !empty($profile) ? substr(wp_json_encode($profile, JSON_PRETTY_PRINT), 0, 7000) : '{}';
    $insights_snippet = !empty($industry_insights) ? substr(wp_json_encode($industry_insights, JSON_PRETTY_PRINT), 0, 3500) : '{}';
    $website_mode = (stripos($prompt, 'EXISTING CONTENT') !== false || stripos($prompt, 'refine') !== false) ? 'refinement' : 'new_generation';

    // ── Extract explicit brand/design data from consultation for hard enforcement ──
    $brand_colors    = '';
    $design_style    = '';
    $style_pref      = '';
    $color_prefs     = '';
    foreach (['brand_colors', 'brandColors', 'colors'] as $ck) {
        if (!empty($extracted[$ck])) { $brand_colors = sanitize_text_field((string) $extracted[$ck]); break; }
    }
    foreach (['design_style', 'designStyle'] as $dk) {
        if (!empty($extracted[$dk])) { $design_style = sanitize_text_field((string) $extracted[$dk]); break; }
    }
    if (!empty($extracted['website_style_preference'])) $style_pref = sanitize_text_field((string) $extracted['website_style_preference']);
    if (!empty($extracted['color_preferences']))        $color_prefs = sanitize_text_field(is_array($extracted['color_preferences']) ? implode(', ', $extracted['color_preferences']) : (string) $extracted['color_preferences']);

    $brand_enforcement = '';
    if ($brand_colors || $color_prefs) {
        $brand_enforcement .= "\n\nCRITICAL — Brand Color Enforcement: The client specified these exact brand colors: " . ($brand_colors ?: $color_prefs) . ". You MUST use these as primary_color and accent_color in the brand object. Do NOT invent different colors.";
    }
    if ($design_style || $style_pref) {
        $brand_enforcement .= "\nCRITICAL — Design Style Enforcement: The client specified this exact design style: " . ($design_style ?: $style_pref) . ". The website tone, layout, and visual direction MUST align with this style.";
    }

    // 3. Ask OpenAI for compact strategy JSON (React + GrapesJS handoff)
    $strategy_system = "You are the VMO Website Strategy Agent working with a hidden GrapesJS frontend composer.\n"
        . "Do not return HTML. Return STRICT JSON only.\n"
        . "This JSON is consumed by GrapesJS to build the full frontend automatically.\n"
        . "Required root keys: version, site, brand, tech_stack, integrations, sections.\n"
        . "site: {business_name, tagline, goal}.\n"
        . "brand: {tone, primary_color, accent_color, text_color, surface_style, motion_style}.\n"
        . "tech_stack.selected: choose 3-8 applicable technologies only from this list: "
        . "HTML5, CSS3, JavaScript (ES6+), Tailwind CSS, GSAP, AOS, Three.js, Framer Motion, React 18, Next.js App Router, Lenis, Swiper.js, Lottie, ShadCN UI, Spline, Schema.org SEO, WordPress APIs, Sora Video, DALL-E Images.\n"
        . "React 18 must always be included in tech_stack.selected because generated websites are React-based.\n"
        . "integrations: include booleans and values for phone_enabled, phone_number, email_enabled, email_address, contact_form, seo_ready, payments_ready, media_replace_ready.\n"
        . "sections: array of 5-10 objects. Each section should include: type, headline, subheadline, body, cta_primary, cta_secondary, media, bullets (array), design_direction, interaction_style. Prefer high-value type values such as hero, proof, services, about, showcase, gallery, products, testimonials, pricing, faq, cta, contact.\n"
        . "CRITICAL EXPERIENCE RULES:\n"
        . "- The site must feel premium, cinematic, layered, and media-led, never brochure-basic.\n"
        . "- Keep body and heading text on a coherent single text-color system; do not ask for gradient text or multiple headline colors.\n"
        . "- The first section must be a hero and should normally use media: video unless the business context strongly requires still imagery.\n"
        . "- The first viewport must behave like a unified opening scene: brand, navigation intent, trust proof, CTA, and hero media should feel composed together rather than separated into plain stacked strips.\n"
        . "- Include a proof/stats/logos style section within the first 2 sections so trust is established early.\n"
        . "- Include at least one proof section, one showcase/gallery/portfolio or product section, one premium CTA section, and one contact section.\n"
        . "- Include at least one showcase/story section that feels editorial and asymmetrical, with offset media, floating panels, or scroll-led composition instead of a simple brochure split.\n"
        . "- At least one section must imply richer interaction patterns such as marquee storytelling, horizontal motion, layered overlays, or parallax-ready composition.\n"
        . "- If phone, email, consultation, booking, or reservation actions are relevant, surface them prominently in the opening header/hero experience.\n"
        . "- Buttons, cards, and CTAs should imply glass, translucent, editorial, or dimensional treatments rather than ordinary flat UI.\n"
        . "- Every visual section must have real AI media planned through media markers so the build can complete with generated assets.\n"
        . "- Do not expose developer-facing framework names or technical stack labels as visible website content.\n"
        . "IMPORTANT: Your strategy MUST directly reflect the consultation profile data. Use the business's actual services, value propositions, target audience, and competitive advantages from the profile. Section headlines and copy must be business-specific, not generic.\n"
        . "Preserve and honor consultation/deep-research context. If mode is refinement, keep the current site direction and only apply requested changes."
        . $brand_enforcement;

    $messages = [
        ['role' => 'system', 'content' => $strategy_system],
        ['role' => 'system', 'content' => 'MODE: ' . $website_mode],
        ['role' => 'system', 'content' => "CONSULTATION PROFILE (authoritative):\n" . $profile_snippet],
        ['role' => 'system', 'content' => "DEEP RESEARCH INSIGHTS:\n" . $insights_snippet],
        ['role' => 'system', 'content' => 'KNOWN BUSINESS CONTACTS: ' . wp_json_encode([
            'phone_number' => $phone_number,
            'email_address' => $business_email
        ])],
        ['role' => 'user', 'content' => $prompt]
    ];

    $model = defined('VMO_OPENAI_MODEL') ? VMO_OPENAI_MODEL : 'gpt-5.2-2025-12-11';
    if (function_exists('vmo_get_optimal_model')) {
        $model = vmo_get_optimal_model('website_building');
    }

    if (!function_exists('vmo_openai_chat')) {
        wp_send_json_error([ 'message' => 'AI request helper unavailable.' ]);
    }

    $resp = vmo_openai_chat($messages, $model, [
        'temperature' => 0.35,
        'max_tokens' => 2400,
        'timeout' => 95,
    ]);

    if (is_wp_error($resp)) {
        wp_send_json_error([ 'message' => 'AI request failed: ' . $resp->get_error_message() ]);
    }

    $data = json_decode( wp_remote_retrieve_body( $resp ), true );
    $raw  = trim( $data['choices'][0]['message']['content'] ?? '' );
    if ( ! $raw ) {
        wp_send_json_error([ 'message' => 'No strategy plan generated. Try simplifying your prompt.' ]);
    }

    $parsed_plan = null;
    if (function_exists('vmo_extract_json_object_from_text')) {
        $parsed_plan = vmo_extract_json_object_from_text($raw);
    }
    if (!is_array($parsed_plan)) {
        $clean = preg_replace('/```(?:json)?(.*?)```/is', '$1', $raw) ?? $raw;
        $parsed_plan = json_decode($clean, true);
        if (!is_array($parsed_plan)) {
            $start = strpos($clean, '{');
            $end = strrpos($clean, '}');
            if ($start !== false && $end !== false && $end > $start) {
                $candidate = substr($clean, $start, ($end - $start) + 1);
                $parsed_plan = json_decode($candidate, true);
            }
        }
    }
    if (!is_array($parsed_plan)) {
        $parsed_plan = [];
    }

    if (function_exists('vmo_normalize_grapes_strategy_plan')) {
        $strategy_plan = vmo_normalize_grapes_strategy_plan($parsed_plan, $prompt, $business_name ?: 'Your Business', $phone_number, $business_email);
    } else {
        $strategy_plan = [
            'version' => '1.0',
            'site' => [
                'business_name' => $business_name ?: 'Your Business',
                'tagline' => 'Built from consultation strategy',
                'goal' => 'Convert qualified visitors'
            ],
            'brand' => [
                'tone' => 'professional',
                'primary_color' => '#0f172a',
                'accent_color' => '#0ea5e9'
            ],
            'tech_stack' => [
                'selected' => ['React 18', 'HTML5', 'CSS3', 'JavaScript (ES6+)']
            ],
            'integrations' => [
                'phone_enabled' => !empty($phone_number),
                'phone_number' => $phone_number,
                'email_enabled' => !empty($business_email),
                'email_address' => $business_email,
                'contact_form' => true,
                'seo_ready' => true,
                'payments_ready' => true,
                'media_replace_ready' => true
            ],
            'sections' => [
                [
                    'type' => 'hero',
                    'headline' => $business_name ?: 'Your Business',
                    'subheadline' => 'React-based frontend built by GrapesJS under the hood',
                    'body' => $prompt,
                    'cta_primary' => 'Get Started',
                    'cta_secondary' => 'Contact Us',
                    'media' => 'image',
                    'bullets' => []
                ]
            ],
            'source' => 'openai_strategy_to_grapes',
            'generated_at' => current_time('mysql')
        ];
    }

    // 4. Deduct tokens for content generation
    if (!vmo_deduct_tokens_for_operation($user_id, 'content')) {
        wp_send_json_error(['message' => 'Failed to deduct tokens for content generation.']);
    }

    // ── Post-generation enforcement: override brand colors with consultation values ──
    if (!empty($brand_colors) || !empty($color_prefs)) {
        $color_source = $brand_colors ?: $color_prefs;
        // Try to extract hex colors (e.g., "#1a2b3c" or "blue")
        preg_match_all('/#[0-9a-fA-F]{3,8}/', $color_source, $hex_matches);
        $hex_list = $hex_matches[0] ?? [];
        if (count($hex_list) >= 1 && isset($strategy_plan['brand'])) {
            $strategy_plan['brand']['primary_color'] = $hex_list[0];
            if (count($hex_list) >= 2) {
                $strategy_plan['brand']['accent_color'] = $hex_list[1];
            }
        }
    }
    if (!empty($design_style) || !empty($style_pref)) {
        if (isset($strategy_plan['brand'])) {
            $strategy_plan['brand']['tone'] = $design_style ?: $style_pref;
        }
    }

    // 5. Return strategy plan for GrapesJS background React composition
    wp_send_json_success([
        'grapes_plan' => $strategy_plan,
        'generation_mode' => 'grapesjs_background_composer',
        'tokens_used'   => vmo_get_token_cost('content'),
        'new_balance'   => vmo_get_token_balance($user_id)
    ]);
} );

/**
 * AJAX Handler for Business Consultation Conversation
 * This handles pure conversation responses, not HTML generation
 */
add_action( 'wp_ajax_vmo_conversation_chat', 'vmo_handle_conversation_chat' );
add_action( 'wp_ajax_nopriv_vmo_conversation_chat', 'vmo_handle_conversation_chat' );

/**
 * AJAX Handler for Loading Chat History
 * Loads persistent chat history from database for syncing across interfaces
 */
add_action( 'wp_ajax_vmo_load_chat_history', 'vmo_handle_load_chat_history' );
add_action( 'wp_ajax_nopriv_vmo_load_chat_history', 'vmo_handle_load_chat_history' );

function vmo_handle_load_chat_history() {
    // Verify nonce for security
    $nonce = isset($_POST['security']) ? sanitize_text_field(wp_unslash($_POST['security'])) : '';
    if (!wp_verify_nonce($nonce, 'vmo_builder_nonce')) {
        wp_send_json_error(['message' => 'Security check failed']);
    }

    $current_user = wp_get_current_user();
    if (!$current_user->ID) {
        wp_send_json_error(['message' => 'Not logged in']);
    }
    
    $user_id = $current_user->ID;
    
    // Get chat_type filter (separate Jarvis vs Consultant histories)
    $chat_type = isset($_POST['chat_type']) ? sanitize_text_field(wp_unslash($_POST['chat_type'])) : 'jarvis';
    
    // Load chat history from database (latest 50 messages)
    global $wpdb;
    $chat_history_table = $wpdb->prefix . 'vmo_chat_history';
    
    // Load only this chat_type to avoid cross-contamination between agents
    $rows = $wpdb->get_results($wpdb->prepare(
        "SELECT message_role as role, message_content as content, conversation_context, created_at 
         FROM $chat_history_table 
         WHERE user_id = %d AND chat_type = %s
         ORDER BY created_at DESC 
         LIMIT 50",
        $user_id, $chat_type
    ), ARRAY_A);

    // Deduplicate obvious auto_greeting repeats (keep newest instance only)
    $deduped = [];
    $seenGreeting = [];
    foreach ($rows as $row) {
        $ctx = isset($row['conversation_context']) ? (string)$row['conversation_context'] : '';
        if ($ctx === 'auto_greeting') {
            $key = 'greet|' . ($row['role'] ?? '') . '|' . md5(trim((string)($row['content'] ?? '')));
            if (isset($seenGreeting[$key])) {
                // skip duplicate greeting
                continue;
            }
            $seenGreeting[$key] = true;
        }
        $deduped[] = [
            'role' => $row['role'] ?? 'assistant',
            'content' => $row['content'] ?? '',
            'created_at' => $row['created_at'] ?? null,
        ];
    }

    // Reverse to chronological order (oldest → newest) for UI rendering
    $messages = array_reverse($deduped);

    error_log('🔧 DEBUG: Loaded ' . count($messages) . ' chat messages (after ordering/dedup) for user ' . $user_id);

    wp_send_json_success([
        'messages' => $messages,
        'count' => count($messages)
    ]);
}

/**
 * AJAX Handler for Greeting Status
 * Returns user info and appropriate greeting based on their status
 */
add_action('wp_ajax_vmo_get_user_status_for_greeting', 'vmo_get_user_status_for_greeting');
add_action('wp_ajax_nopriv_vmo_get_user_status_for_greeting', 'vmo_get_user_status_for_greeting');

function vmo_get_user_status_for_greeting() {
    $current_user = wp_get_current_user();
    if (!$current_user->ID) {
        wp_send_json_error(['message' => 'Not logged in']);
    }
    
    $user_name = $current_user->display_name ?: $current_user->user_login;
    
    // Check consultation status
    $profile = function_exists('vmo_get_consultation_profile') ? vmo_get_consultation_profile() : [];
    
    // Check if they have chat history
    global $wpdb;
    $chat_history_table = $wpdb->prefix . 'vmo_chat_history';
    $chat_count = $wpdb->get_var($wpdb->prepare(
        "SELECT COUNT(*) FROM {$chat_history_table} WHERE user_id = %d",
        $current_user->ID
    ));
    
    $status = 'first_time';
    $greeting = '';
    
    if ($chat_count > 0) {
        // Returning user
        if (!empty($profile)) {
            $status = 'active_business';
            $greeting = "Welcome back, {$user_name}. Jarvis here. Your VMO team is ready to keep building, refining, and managing your business. If you want strategy, content, design, or new execution work, open the red Business Wizard button and Jerreme will take it from there.";
        } else {
            $status = 'incomplete_consultation';
            $greeting = "Welcome back, {$user_name}. I'm Jarvis, your VMO launch guide. Your builder is ready, and behind me is the full VMO AI team covering design, content, SEO, documents, media, and automation. Click the red Business Wizard button to speak with Jerreme and continue your consultation.";
        }
    } else {
        // First time
        $greeting = "Welcome, {$user_name}. I'm Jarvis, your VMO AI launch guide. Your website builder is ready, and the wider VMO team is standing by across strategy, content, design, SEO, media, documents, and automation. Click the red Business Wizard button to meet Jerreme and begin building your business the right way.";
    }
    
    wp_send_json_success([
        'status' => $status,
        'display_name' => $user_name,
        'greeting' => $greeting,
        'has_profile' => !empty($profile)
    ]);
}

function vmo_handle_conversation_chat() {
    // CRITICAL: Suppress database errors from outputting HTML before JSON
    global $wpdb;
    $wpdb->hide_errors();
    $wpdb->suppress_errors = true;
    
    error_log('🔧 DEBUG: vmo_handle_conversation_chat function called');
    error_log('🔧 DEBUG: $_POST data: ' . print_r($_POST, true));
    
    // Verify nonce for security (dual-nonce, non-fatal on invalid)
    $admin_nonce   = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
    $builder_nonce = isset($_POST['security']) ? sanitize_text_field(wp_unslash($_POST['security'])) : '';
    $admin_ok   = $admin_nonce && wp_verify_nonce($admin_nonce, 'vmo_admin_nonce');
    $builder_ok = $builder_nonce && wp_verify_nonce($builder_nonce, 'vmo_builder_nonce');
    if (!($admin_ok || $builder_ok)) {
        error_log('🔧 DEBUG: Nonce verification failed');
        error_log('🔧 DEBUG: Provided nonces - admin: ' . ($admin_nonce ?: 'NOT_PROVIDED') . ', builder: ' . ($builder_nonce ?: 'NOT_PROVIDED'));
        wp_send_json_error([ 'message' => 'Security check failed', 'status' => 'invalid_nonce' ]);
    }

    error_log('🔧 DEBUG: Nonce verification passed');

    $api_key = get_option( 'vmo_openai_api_key' );
    if ( ! $api_key ) {
        error_log('❌ ERROR: OpenAI API key is missing');
        wp_send_json_error([ 'message' => 'OpenAI API key is not configured. Please add your API key in the VMO settings.' ]);
    }

    // Validate API key format (OpenAI keys start with 'sk-')
    if (!preg_match('/^sk-[a-zA-Z0-9\-_]{20,}$/', $api_key)) {
        error_log('❌ ERROR: OpenAI API key has invalid format. Key prefix: ' . substr($api_key, 0, 10) . '...');
        wp_send_json_error([ 'message' => 'OpenAI API key appears to be invalid. Please check your API key in VMO settings.' ]);
    }

    error_log('✅ API key validated (format OK, length: ' . strlen($api_key) . ')');

    // GET USER INFO
    $current_user = wp_get_current_user();
    $user_name = $current_user->display_name ?: $current_user->user_login;
    $user_id = $current_user->ID;

    // TOKEN CHECK: Deduct tokens for chat (Admin Bypass handled in token manager)
    if (function_exists('vmo_deduct_tokens_for_operation')) {
        if (!vmo_deduct_tokens_for_operation($user_id, 'chat')) {
            wp_send_json_error([ 
                'message' => 'Insufficient tokens. Please top up your balance to continue chatting.',
                'status' => 'insufficient_tokens'
            ]);
        }
    }

    // Get chat array from request
    // ✅ FIX: Do NOT use sanitize_text_field() on JSON — it strips HTML tags inside
    // message content (e.g. <strong>, <ul>) and corrupts the JSON structure.
    // Instead, wp_unslash once (to undo WordPress magic_quotes), json_decode,
    // then sanitize each individual message content after decoding.
    $chat_raw = wp_unslash($_POST['chat'] ?? '[]');
    $chat = json_decode($chat_raw, true);
    if ( ! is_array( $chat ) || empty( $chat ) ) {
        error_log('🔧 DEBUG: Invalid chat payload (length=' . strlen($chat_raw) . '): ' . substr($chat_raw, 0, 500));
        wp_send_json_error([ 'message' => 'Invalid chat payload.' ]);
    }
    // Sanitize each message's content individually (preserving JSON structure)
    foreach ($chat as &$msg) {
        if (isset($msg['role'])) {
            $msg['role'] = sanitize_text_field($msg['role']);
        }
        if (isset($msg['content'])) {
            $msg['content'] = wp_kses_post($msg['content']);
        }
    }
    unset($msg);

    // Store the user's message for later database save
    $user_message = '';
    foreach ($chat as $msg) {
        if (isset($msg['role']) && $msg['role'] === 'user') {
            $user_message = $msg['content'];
        }
    }

    error_log('🔧 DEBUG: Chat array valid: ' . print_r($chat, true));

    // ✅ DETERMINE CHAT TYPE: 'jarvis' (main coordinating AI) or 'consultant' (business wizard)
    $chat_type = isset($_POST['chat_type']) ? sanitize_text_field(wp_unslash($_POST['chat_type'])) : 'jarvis';
    // Optional: consultation session context for cross-interface continuity
    $consultation_session_id = isset($_POST['session_id']) ? sanitize_text_field(wp_unslash($_POST['session_id'])) : '';
    // Optional: language hint from client (e.g., recognition.lang)
    $client_lang = isset($_POST['lang']) ? sanitize_text_field(wp_unslash($_POST['lang'])) : '';
    error_log('🔧 DEBUG: Chat type: ' . $chat_type);

    // LOAD CHAT HISTORY (last 30 messages for context)
    global $wpdb;
    $chat_history_table = $wpdb->prefix . 'vmo_chat_history';
    $history = $wpdb->get_results($wpdb->prepare(
        "SELECT message_role, message_content FROM $chat_history_table 
         WHERE user_id = %d AND chat_type = %s
         ORDER BY created_at DESC LIMIT 30",
        $user_id, $chat_type
    ), ARRAY_A);
    $history = array_reverse($history); // Oldest first

    // BUILD SYSTEM PROMPT BASED ON CHAT TYPE
    if ($chat_type === 'consultant') {
        // ✅ BUSINESS CONSULTANT AI - Strategic expert for business consultation
        $system_prompt = "You are the VMO Business Consultant AI - a world-class business strategist (McKinsey/BCG/Bain level) specialized in helping entrepreneurs at ALL stages.

**WHO YOU ARE**:
- You are a dedicated Business Consultant AI, NOT the main coordinating Jarvis AI
- Your ONLY job is conducting strategic business consultations
- You help entrepreneurs discover opportunities, validate ideas, and build complete business strategies
- You are professional, insightful, warm, and demonstrate deep business expertise
- You address the user by name: {$user_name}

**CRITICAL: GREETING FOR FIRST-TIME CONVERSATIONS**:
If this is the very first message (no conversation history), start with a warm, personal introduction:

\"Hi {$user_name}! 👋 I'm your VMO Business Consultant—think of me as your personal business strategist here to help you build something amazing.

Whether you're just starting out with a new idea or growing an existing business, I'm here to guide you through every step. We'll have a friendly conversation to understand your vision, and then I'll help you build a complete business ecosystem: professional website, marketing systems, legal documents, SEO optimization—everything you need.

Let's start simple: What kind of business are you thinking about? (And hey, it's totally okay if you're still figuring things out—that's what I'm here for!)\"

**FOR ONGOING CONVERSATIONS** (when conversation history exists):
Continue naturally from where you left off. Reference their previous answers and build on them.

**YOUR ROLE IN THE BUSINESS WIZARD**:
You conduct intelligent, adaptive conversations to understand their business deeply:
- For EXISTING businesses: Focus on growth, digital transformation, optimization, market expansion
- For NEW startups: Focus on opportunity discovery, validation, business model development
- Think like a Harvard MBA with 20+ years consulting both startups and Fortune 500 companies

**🎯 CRITICAL CONVERSATION RULES**:
✅ Ask ONE question at a time - never multiple questions in a single message
✅ Keep questions simple and easy to understand (novice-friendly language)
✅ Start with the basics: business type, what they do, location
✅ Never ask about \"customers\" or \"target audience\" at the very beginning (too advanced)
✅ Never ask about \"main goals\" or \"objectives\" in the first few questions (overwhelming)
✅ Build conversation naturally - each question should flow from their previous answer
✅ Use warm, encouraging language with reassurance (\"It's totally okay if you're still figuring things out!\")
✅ Wait for their answer before asking the next question
✅ Progress gradually from simple to more detailed questions
✅ Show genuine interest and enthusiasm about their business ideas
✅ Acknowledge their answers before asking the next question (\"That's exciting! A bakery is a wonderful business...\")
❌ NEVER ask compound questions like \"What do you do, who are your customers, and what are your goals?\"
❌ NEVER overwhelm beginners with technical jargon or complex business concepts
❌ NEVER mention clicking buttons or using interfaces - you ARE the consultation
❌ NEVER skip the warm introduction on first contact

**AVAILABLE INFRASTRUCTURE** (You can build for them):
- Professional website with SEO & local presence
- E-commerce capabilities and payment processing  
- AI phone assistant for 24/7 customer service
- Legal documents and business structure
- Marketing strategy and lead generation
- Advanced SEO Management System (continuous optimization)
- Automated content creation and blog publishing
- Location-targeted service pages for market expansion
- Real-time ranking monitoring and improvements
- **Affiliate Marketing System**: You can build a complete affiliate program for them. Use the shortcode `[vmo_affiliate_dashboard]` for the affiliate area, `[vmo_affiliate_register]` for the signup form, and `[vmo_commission_calculator]` for the earnings calculator.
- **Membership & User Dashboard**: You can build membership sites with protected content. Use `[vmo_register_form]`, `[vmo_login_form]`, and `[vmo_user_dashboard]` to create a client portal. Wrap private content in `[vmo_protected]...[/vmo_protected]`.
- **Support Ticketing System**: You can build a customer support portal. Use `[vmo_support_ticket_form]` for users to submit issues and `[vmo_ticket_list]` for them to view their ticket status.

**CONVERSATION CONTEXT**:
" . (!empty($history) ? "Previous conversation:\n" . json_encode($history, JSON_PRETTY_PRINT) : "Early conversation with {$user_name}.");
        
        // LANGUAGE POLICY DIRECTIVE
        $language_directive = $client_lang
            ? ("\n\n**LANGUAGE POLICY**:\n- Use this language for all responses: {$client_lang}.\n- If the user switches languages in later turns, mirror their new language.\n- Keep tone and formality aligned with the user's style.")
            : ("\n\n**LANGUAGE POLICY**:\n- Detect the language of the user's last message and respond fully in that language.\n- Mirror the user's formality and tone (casual vs professional).\n- If they switch languages, follow them seamlessly.");
        $system_prompt .= $language_directive;
        
    } else {
        // ✅ JARVIS AI - Main coordinating AI Butler
    $system_prompt = "You are VMO (Virtual Media Office) - the main coordinating AI Butler for the VMO Web Business Consultant system. Think of yourself as the user's personal Jarvis-style AI business assistant.

**WHO YOU ARE**:
- You are the MAIN AI COORDINATOR that manages all other specialized AI agents in the VMO system
- You are NOT the Business Consultant AI - that's a different specialized agent
- You are warm, enthusiastic, professional, and make users feel special and excited
- You address the user by their name: {$user_name}
- You remember previous conversations and build on them (conversations are persistent across all interfaces)
- You provide quick help, status updates, and coordinate all VMO functions

**YOUR ROLE** (Coordinating AI, NOT Business Consultant):
✅ Answer questions about VMO capabilities and features
✅ Provide status updates on their business operations
✅ Coordinate between different AI agents (Web Builder, SEO Expert, Legal Advisor, etc.)
✅ Give quick business insights and KPI summaries
✅ Help navigate the VMO system and its features
✅ Explain what each VMO function does
✅ **Refine and improve their website in the live preview** - you can make changes to content, layout, styling, and functionality
✅ **Available everywhere in the dashboard** - voice panel, live preview interface, dashboard pages (except during Business Wizard consultation)
❌ Do NOT conduct the initial business consultation (that's the Business Consultant AI's job)
❌ Do NOT ask strategic business questions like \"What kind of business are you thinking about?\"
❌ Do NOT try to gather business information systematically

**WEBSITE REFINEMENT CAPABILITIES**:
When the user wants to modify their website (visible in the live preview iframe):
- Ask what they'd like to change (specific section, text, images, colors, layout, etc.)
- Make intelligent suggestions based on their business goals
- Explain changes you're making and why they'll improve the site
- Coordinate with the Web Builder AI to implement changes
- After changes, encourage them to review in the live preview
- Examples: \"Change the hero section heading\", \"Make the colors more professional\", \"Add a testimonials section\", \"Improve mobile responsiveness\"

**WHEN USER NEEDS BUSINESS CONSULTATION**:
If they haven't completed the Business Wizard consultation yet, direct them to click the RED \"Business Wizard\" button at the top. Say something like:

\"For a complete business setup with website, legal docs, marketing systems, and more, click the red 'Business Wizard' button at the top! Our specialized Business Consultant AI will guide you through a strategic conversation to build everything you need.\"

**IF THEY ALREADY COMPLETED WIZARD**:
- Provide business updates, KPIs, and operational insights
- Coordinate changes through specialized agents
- Answer specific questions about their business systems
- Help refine their website and marketing materials

" . (function_exists('vmo_get_capabilities_prompt') ? vmo_get_capabilities_prompt() : '') . "

**CRITICAL BEHAVIOR RULES FOR CAPABILITIES**:
1. NEVER say 'VMO cannot do this' or 'VMO doesn't have that feature' for ANY capability listed above.
2. NEVER recommend external services (Google Workspace, Microsoft 365, etc.) as the primary option when VMO has a built-in solution.
3. For email: ALWAYS recommend VMO's built-in Zoho Mail integration first. Say: 'VMO has Zoho Mail built in — I can set up your business email right here.'
4. For phone/SMS: ALWAYS explain VMO's built-in phone system. Users don't need to go to Twilio directly.
5. For payments: ALWAYS direct users to the Payments section in VMO dashboard.
6. Be confident and knowledgeable about every feature listed above — you ARE VMO.

**FORMATTING RULES**:
- Write in clear, properly formatted paragraphs
- Use line breaks between paragraphs for readability
- Use bullet points when listing (✅ ❌ • -)
- Keep responses concise (2-4 short paragraphs)
- Be encouraging and professional

**VOICE CAPABILITY (CRITICAL)**:
- This interface supports full voice conversation. You CAN hear and understand everything the user says.
- When the user says \"can you hear me?\" or similar, simply confirm: \"Yes, I can hear you! How can I help?\" Do NOT explain how speech-to-text works, do NOT mention transcripts, microphones, or technical processes.
- NEVER explain your internal architecture, how speech recognition works, or any technical implementation details. The user does not need or want to know how you process their voice — just respond naturally as if you are a human assistant who can hear them perfectly.
- Do NOT give instructions like \"click the mic\" or \"check the transcript\" — the voice system works automatically.
- Keep voice-friendly tone: clear, concise sentences; avoid overly long paragraphs; emojis are optional.
- You are having a LIVE VOICE CONVERSATION. Respond as naturally and warmly as a human colleague would on a phone call.

**CONVERSATION CONTEXT**:
" . (!empty($history) ? "Previous conversation:\n" . json_encode($history, JSON_PRETTY_PRINT) : "Early conversation with {$user_name}.");
        
        // LANGUAGE POLICY DIRECTIVE
        $language_directive = $client_lang
            ? ("\n\n**LANGUAGE POLICY**:\n- Use this language for all responses: {$client_lang}.\n- If the user switches languages in later turns, mirror their new language.\n- Keep tone and formality aligned with the user's style.")
            : ("\n\n**LANGUAGE POLICY**:\n- Detect the language of the user's last message and respond fully in that language.\n- Mirror the user's formality and tone (casual vs professional).\n- If they switch languages, follow them seamlessly.");
        $system_prompt .= $language_directive;
    }

    // Get consultation profile if exists (for both AI types)
    $profile = function_exists('vmo_get_consultation_profile') ? vmo_get_consultation_profile() : [];
    if (!empty($profile)) {
        $system_prompt .= "\n\n**USER'S BUSINESS PROFILE**:\n" . json_encode($profile, JSON_PRETTY_PRINT);
    }

    // If a consultation session_id is provided, inject relevant context so the AI won't re-ask
    if (!empty($consultation_session_id)) {
        try {
            if (!class_exists('VMO_Consultation_Database')) {
                require_once plugin_dir_path(__FILE__) . 'class-vmo-consultation-database.php';
            }
            $db = new VMO_Consultation_Database();
            $row = $db->get_consultation_by_session($consultation_session_id);
            if ($row) {
                $ctx_lines = [];
                $ctx_lines[] = 'CONSULTATION CONTEXT (session ' . $consultation_session_id . '):';
                // Include business_analysis if present
                $analysis = is_string($row->business_analysis ?? '') ? trim($row->business_analysis) : '';
                if ($analysis !== '') {
                    $ctx_lines[] = '• Analysis Summary: ' . wp_strip_all_tags(mb_substr($analysis, 0, 1200));
                }
                // Pull known answers/extracted info from consultation_data
                $cd = json_decode((string)$row->consultation_data, true);
                if (is_array($cd)) {
                    if (!empty($cd['extracted_information']) && is_array($cd['extracted_information'])) {
                        $known = [];
                        foreach ($cd['extracted_information'] as $k => $v) {
                            $vv = is_array($v) ? json_encode($v) : (string)$v;
                            if ($vv === '' || $vv === 'null') continue;
                            $known[] = '- ' . ucwords(str_replace('_',' ', (string)$k)) . ': ' . wp_strip_all_tags(mb_substr($vv, 0, 300));
                            if (count($known) >= 20) break;
                        }
                        if (!empty($known)) {
                            $ctx_lines[] = "Known Answers:\n" . implode("\n", $known);
                        }
                    }
                    if (!empty($cd['media_roles']) && is_array($cd['media_roles'])) {
                        $roles = [];
                        foreach ($cd['media_roles'] as $role => $items) {
                            $roles[] = '- ' . ucwords(str_replace('_',' ', (string)$role)) . ': ' . (is_array($items) ? count($items) . ' item(s)' : '1');
                        }
                        if (!empty($roles)) {
                            $ctx_lines[] = "Media Roles:\n" . implode("\n", array_slice($roles, 0, 10));
                        }
                    }
                    if (!empty($cd['media_files']) && is_array($cd['media_files'])) {
                        $mf = [];
                        foreach ($cd['media_files'] as $m) {
                            $t = ($m['title'] ?? 'Untitled');
                            $ty = ($m['type'] ?? 'file');
                            $mf[] = '- ' . $t . ' [' . $ty . ']';
                            if (count($mf) >= 10) break;
                        }
                        if (!empty($mf)) {
                            $ctx_lines[] = "Media Files:\n" . implode("\n", $mf);
                        }
                    }
                }
                // Include a short tail of the conversation log to improve continuity
                $conv = json_decode((string)$row->conversation_log, true);
                if (is_array($conv) && !empty($conv)) {
                    $tail = array_slice($conv, -6); // last 6 turns
                    $ctx_lines[] = 'Recent Consultation Turns: ' . json_encode($tail, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
                }
                // ALWAYS include document content to prevent AI from forgetting uploaded documents
                $doc_ctx = '';
                $fallback_doc_ctx = '';
                if (is_array($cd) && !empty($cd['documents'])) {
                    // Always build fallback with recent document chunks (increased budget)
                    $recent_budget = 8000;
                    $recent_used = 0;
                    $docs_reversed = array_reverse((array)$cd['documents']);
                    $fallback_parts = [];
                    foreach (array_slice($docs_reversed, 0, 3) as $doc) { // Last 3 documents
                        $title = (string)($doc['title'] ?? 'Document');
                        $header = "━━━ " . $title . " ━━━\n";
                        $chunks = array_slice((array)($doc['chunks'] ?? []), 0, 4); // First 4 chunks per doc
                        foreach ($chunks as $c) {
                            $text = is_array($c) ? (string)($c['text'] ?? '') : (string)$c;
                            if ($text === '') continue;
                            $entry = $header . $text . "\n\n";
                            $header = ''; // Only add header once
                            $len = strlen($entry);
                            if ($recent_used + $len > $recent_budget) break 2;
                            $fallback_parts[] = $entry;
                            $recent_used += $len;
                        }
                    }
                    $fallback_doc_ctx = trim(implode('', $fallback_parts));
                    
                    // Also do keyword matching for higher relevance (if user message exists)
                    if (!empty($user_message)) {
                        $terms = preg_split('/[^\p{L}\p{N}]+/u', mb_strtolower($user_message));
                        $terms = array_values(array_filter(array_unique(array_map(function($t){ return (mb_strlen($t) >= 3) ? $t : ''; }, $terms))));
                        if (!empty($terms)) {
                            $scored = [];
                            foreach ((array)$cd['documents'] as $doc) {
                                $title = (string)($doc['title'] ?? 'Document');
                                foreach ((array)($doc['chunks'] ?? []) as $chunk) {
                                    $text = mb_strtolower(is_array($chunk) ? ($chunk['text'] ?? '') : (string)$chunk);
                                    $score = 0;
                                    foreach ($terms as $t) { if ($t && mb_strpos($text, $t) !== false) $score++; }
                                    if ($score > 0) { $scored[] = [ 'score' => $score, 'title' => $title, 'snippet' => trim(is_array($chunk) ? ($chunk['text'] ?? '') : (string)$chunk) ]; }
                                }
                            }
                            if (!empty($scored)) {
                                usort($scored, function($a,$b){ return $b['score'] <=> $a['score']; });
                                $buf = '';
                                $used = 0;
                                $budget = 6000;
                                foreach ($scored as $hit) {
                                    $entry = '— ' . $hit['title'] . " —\n" . $hit['snippet'] . "\n\n";
                                    $len = strlen($entry);
                                    if ($used + $len > $budget) break;
                                    $buf .= $entry; $used += $len;
                                }
                                $doc_ctx = trim($buf);
                            }
                        }
                    }
                    // Use keyword-matched context if found, otherwise fallback to recent
                    if ($doc_ctx === '' && $fallback_doc_ctx !== '') {
                        $doc_ctx = $fallback_doc_ctx;
                    }
                }

                $ctx_block = implode("\n", $ctx_lines);
                // Final instruction to prevent redundant questioning + include document context if present
                $system_prompt .= "\n\n" . $ctx_block;
                if ($doc_ctx !== '') {
                    $system_prompt .= "\n\nDOCUMENT CONTEXT (uploaded business documents - use this as source of truth):\n" . $doc_ctx;
                }
                $system_prompt .= "\n\nCRITICAL: Do NOT re-ask for any items present in Known Answers, Analysis Summary, or the Document Context above. Reference them directly and continue. If the user asks about the uploaded blueprint, you already have it in context—do not ask them to paste it.\n";
            }
        } catch (Throwable $e) {
            if (defined('WP_DEBUG') && WP_DEBUG) {
                error_log('VMO: Failed to inject consultation context: ' . $e->getMessage());
            }
        }
    }

    // Inject DURABLE MEMORY, ACTIVE MILESTONES, and RECENT SUMMARIES into system prompt (bounded)
    try {
        $ltm_table = $wpdb->prefix . 'vmo_long_term_memory';
        $milestones_table = $wpdb->prefix . 'vmo_roadmap_milestones';
        $summaries_table = $wpdb->prefix . 'vmo_progress_summaries';

        // Top important curated memories (limit 20)
        $mem_rows = $wpdb->get_results($wpdb->prepare(
            "SELECT memory_type, memory_key, importance, content FROM $ltm_table WHERE user_id = %d ORDER BY importance DESC, updated_at DESC LIMIT 20",
            $user_id
        ), ARRAY_A);
        if (!empty($mem_rows)) {
            $mem_text = [];
            foreach ($mem_rows as $m) {
                $label = strtoupper($m['memory_type'] ?? 'fact');
                $key = $m['memory_key'] ? (' [' . $m['memory_key'] . ']') : '';
                $mem_text[] = "- ($label{$key}) " . wp_strip_all_tags((string)($m['content'] ?? '' ));
            }
            $system_prompt .= "\n\n**DURABLE MEMORY (curated facts/goals/decisions)**\n" . implode("\n", array_slice($mem_text, 0, 20));
        }

        // Active milestones (exclude done; limit 10)
        $ms_rows = $wpdb->get_results($wpdb->prepare(
            "SELECT title, target_date, owner, status, progress, notes FROM $milestones_table WHERE user_id = %d AND (status IS NULL OR status NOT IN ('done','completed')) ORDER BY target_date IS NULL, target_date ASC, updated_at DESC LIMIT 10",
            $user_id
        ), ARRAY_A);
        if (!empty($ms_rows)) {
            $ms_text = [];
            foreach ($ms_rows as $ms) {
                $t = $ms['title'] ?? '';
                $dd = $ms['target_date'] ? (' due ' . $ms['target_date']) : '';
                $p = isset($ms['progress']) ? (' [' . intval($ms['progress']) . '%]') : '';
                $s = $ms['status'] ? (' (' . $ms['status'] . ')') : '';
                $ms_text[] = "- $t$dd$p$s";
            }
            $system_prompt .= "\n\n**ACTIVE MILESTONES**\n" . implode("\n", $ms_text);
        }

        // Recent summaries: latest weekly + last 3 daily
        $weekly = $wpdb->get_row($wpdb->prepare(
            "SELECT summary, period_date FROM $summaries_table WHERE user_id = %d AND period = 'weekly' ORDER BY period_date DESC LIMIT 1",
            $user_id
        ), ARRAY_A);
        $dailies = $wpdb->get_results($wpdb->prepare(
            "SELECT summary, period_date FROM $summaries_table WHERE user_id = %d AND period = 'daily' ORDER BY period_date DESC LIMIT 3",
            $user_id
        ), ARRAY_A);
        $sum_txt = '';
        if ($weekly && !empty($weekly['summary'])) {
            $sum_txt .= "WEEKLY (" . $weekly['period_date'] . "):\n" . wp_strip_all_tags((string)$weekly['summary']) . "\n";
        }
        if (!empty($dailies)) {
            foreach ($dailies as $d) {
                $sum_txt .= "DAILY (" . $d['period_date'] . "):\n" . wp_strip_all_tags((string)$d['summary']) . "\n";
            }
        }
        if ($sum_txt) {
            // Bound the overall injected text to avoid prompt bloat
            if (strlen($sum_txt) > 4000) { $sum_txt = substr($sum_txt, 0, 4000) . '…'; }
            $system_prompt .= "\n\n**RECENT PROGRESS SUMMARIES**\n" . $sum_txt;
        }
    } catch (Throwable $e) {
        // Non-fatal if any memory tables are missing
        if (defined('WP_DEBUG') && WP_DEBUG) {
            error_log('VMO: Memory injection skipped: ' . $e->getMessage());
        }
    }

    // BUILD COMPREHENSIVE SYSTEM PROMPT

    // Prepend system prompt to chat
    array_unshift($chat, [
        'role' => 'system',
        'content' => $system_prompt
    ]);

    // ══════════════════════════════════════════════════════════════
    // ✅  STREAMING MODE — Real-time token delivery via SSE
    // ══════════════════════════════════════════════════════════════
    if (!empty($_POST['stream'])) {
        $api_key = defined('VMO_OPENAI_API_KEY') ? VMO_OPENAI_API_KEY : get_option('vmo_openai_api_key', '');
        $model   = defined('VMO_OPENAI_MODEL') ? VMO_OPENAI_MODEL : 'gpt-4o';

        // Clean ALL output buffers and set SSE headers
        while (ob_get_level()) ob_end_clean();
        @ini_set('output_buffering', 'off');
        @ini_set('zlib.output_compression', 0);
        header('Content-Type: text/event-stream');
        header('Cache-Control: no-cache');
        header('Connection: keep-alive');
        header('X-Accel-Buffering: no');

        $result = vmo_stream_openai($chat, $api_key, $model, 1000, 0.8);

        if (!empty($result['error'])) {
            echo 'data: ' . json_encode(['error' => $result['error']]) . "\n\n";
            flush();
            exit;
        }

        $content = trim($result['text']);

        // Save conversation to DB (same as non-streaming path)
        if (!empty($content)) {
            global $wpdb;
            $chat_history_table = $wpdb->prefix . 'vmo_chat_history';
            $user_id = get_current_user_id();
            if (!empty($user_message)) {
                // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
                $wpdb->insert($chat_history_table, [
                    'user_id' => $user_id, 'message_role' => 'user',
                    'message_content' => $user_message, 'chat_type' => $chat_type,
                    'created_at' => current_time('mysql')
                ], ['%d','%s','%s','%s','%s']);
            }
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            $wpdb->insert($chat_history_table, [
                'user_id' => $user_id, 'message_role' => 'assistant',
                'message_content' => $content, 'chat_type' => $chat_type,
                'created_at' => current_time('mysql')
            ], ['%d','%s','%s','%s','%s']);
        }

        // Final event signals completion
        echo 'data: ' . json_encode(['done' => true]) . "\n\n";
        flush();
        exit;
    }

    // Call OpenAI API for pure conversation (no HTML generation)
    // ✅ CRITICAL FIX: Use modern OpenAI model with max_completion_tokens for GPT-5.2
    $payload = [
        'model'       => defined('VMO_OPENAI_MODEL') ? VMO_OPENAI_MODEL : 'gpt-4o',
        'messages'    => $chat,
        'temperature' => 0.8,
        'max_completion_tokens' => 1000, // GPT-5.2 requires max_completion_tokens, not max_tokens
        'top_p'       => 0.9,
    ];

    error_log('🔧 DEBUG: OpenAI payload: ' . print_r($payload, true));

    $response = wp_remote_post( 'https://api.openai.com/v1/chat/completions', [
        'headers' => [
            'Authorization' => 'Bearer ' . $api_key,
            'Content-Type'  => 'application/json',
        ],
        'body'    => wp_json_encode( $payload ),
        'timeout' => 60,
    ] );

    if ( is_wp_error( $response ) ) {
        error_log('🔧 DEBUG: wp_remote_post error: ' . $response->get_error_message());
        wp_send_json_error([ 'message' => 'AI request failed: ' . $response->get_error_message() ]);
    }

    $response_code = wp_remote_retrieve_response_code( $response );
    error_log('🔧 DEBUG: OpenAI response code: ' . $response_code);
    
    if ( $response_code !== 200 ) {
        $response_body = wp_remote_retrieve_body( $response );
        error_log('🔧 DEBUG: OpenAI error response: ' . $response_body);
        
        // Map HTTP codes to Safe VMO Error Codes
        $safeCode = 'N99'; // Default unknown
        if ($response_code === 401 || $response_code === 403) {
            $safeCode = 'N24'; // Permission/Key issue
        } elseif ($response_code === 429) {
            $safeCode = 'N20'; // Quota/Rate Limit
        } elseif ($response_code >= 500) {
            $safeCode = 'N22'; // Server Error
        }

        // Return generic message with code
        wp_send_json_error([ 
            'message' => "System is temporarily unavailable (Code: $safeCode). Please contact support for assistance.",
            'error_code' => $safeCode
        ]);
    }

    $data = json_decode( wp_remote_retrieve_body( $response ), true );
    error_log('🔧 DEBUG: OpenAI response data: ' . print_r($data, true));
    
    // Check if response has the expected structure
    if (!isset($data['choices']) || !is_array($data['choices']) || empty($data['choices'])) {
        error_log('❌ ERROR: OpenAI response missing choices array. Full response: ' . wp_json_encode($data));
        $errorDetails = 'OpenAI API returned unexpected format.';
        if (isset($data['error'])) {
            $errorDetails = $data['error']['message'] ?? 'Unknown OpenAI error';
            error_log('❌ OpenAI API Error: ' . $errorDetails);
        }
        wp_send_json_error([ 
            'message' => 'AI response error: ' . $errorDetails,
            'debug_data' => $data
        ]);
    }
    
    $content = trim( $data['choices'][0]['message']['content'] ?? '' );
    error_log('🔧 DEBUG: Extracted content length: ' . strlen($content) . ' characters');
    
    if ( ! $content ) {
        error_log('❌ ERROR: OpenAI returned empty content. Full choices: ' . wp_json_encode($data['choices']));
        
        // Check if there's a finish_reason that explains why
        $finish_reason = $data['choices'][0]['finish_reason'] ?? 'unknown';
        error_log('🔧 DEBUG: Finish reason: ' . $finish_reason);
        
        $errorMsg = 'No response generated';
        if ($finish_reason === 'length') {
            $errorMsg .= ' (response too long - try a shorter message)';
        } elseif ($finish_reason === 'content_filter') {
            $errorMsg .= ' (content filtered by OpenAI safety system)';
        } else {
            $errorMsg .= '. Finish reason: ' . $finish_reason;
        }
        
        wp_send_json_error([ 
            'message' => $errorMsg,
            'finish_reason' => $finish_reason,
            'debug_choices' => $data['choices']
        ]);
    }

    // SAVE CONVERSATION TO DATABASE for persistent history
    $chat_history_table = $wpdb->prefix . 'vmo_chat_history';
    
    // Save user message
    if (!empty($user_message)) {
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $wpdb->insert(
            $chat_history_table,
            [
                'user_id' => $user_id,
                'message_role' => 'user',
                'message_content' => $user_message,
                'chat_type' => $chat_type,
                'created_at' => current_time('mysql')
            ],
            ['%d', '%s', '%s', '%s', '%s']
        );
        error_log('🔧 DEBUG: Saved user message to database');
    }

    // Save AI response
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    $wpdb->insert(
        $chat_history_table,
        [
            'user_id' => $user_id,
            'message_role' => 'assistant',
            'message_content' => $content,
            'chat_type' => $chat_type,
            'created_at' => current_time('mysql')
        ],
        ['%d', '%s', '%s', '%s', '%s']
    );
    error_log('🔧 DEBUG: Saved AI response to database');

    error_log('🔧 DEBUG: Sending success response with content: ' . $content);

    // Return just the conversation response (no HTML wrapping)
    wp_send_json_success([
        'response' => $content
    ]);
    
    // Ensure we exit after sending the response
    wp_die();
}


/*==================================================================
= AJAX: Refine exactly one SECTION block, WITH FULL-PAGE CONTEXT =
==================================================================*/
add_action( 'wp_ajax_vmo_refine_block', function() use ( $VMO_STYLE_DIRECTIVES ) {
    // Dual-nonce validation: accept either admin nonce (nonce) or builder nonce (security)
    $admin_nonce   = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
    $builder_nonce = isset($_POST['security']) ? sanitize_text_field(wp_unslash($_POST['security'])) : '';

    $admin_ok   = $admin_nonce && wp_verify_nonce($admin_nonce, 'vmo_admin_nonce');
    $builder_ok = $builder_nonce && wp_verify_nonce($builder_nonce, 'vmo_builder_nonce');

    if (!($admin_ok || $builder_ok)) {
        wp_send_json_error(['message' => 'Security check failed', 'status' => 'invalid_nonce']);
    }
    
    // For basic refinements, consultation profile is optional - allows more flexible usage
    if (!function_exists('vmo_get_consultation_profile')) {
        require_once plugin_dir_path(__FILE__) . 'consultation-profile.php';
    }

    // 1️⃣ Grab inputs
    $api_key        = get_option( 'vmo_openai_api_key' );
    $block_html     = isset( $_POST['block_html'] )
                      ? wp_kses_post( wp_unslash( $_POST['block_html'] ) )
                      : '';
    $prompt         = isset( $_POST['prompt'] )
                      ? wp_strip_all_tags( wp_unslash( $_POST['prompt'] ) )
                      : '';
    $full_page_html = isset( $_POST['full_page_html'] )
                      ? wp_kses_post( wp_unslash( $_POST['full_page_html'] ) )
                      : '';

    // 2️⃣ Validate API key
    if ( ! $api_key ) {
        wp_send_json_error( [ 'message' => 'OpenAI API key is missing.' ] );
    }

    // 🔒 Token validation - Check if user has sufficient tokens for refinement
    $user_id = get_current_user_id();
    
    // Include token manager if not already included
    if (!function_exists('vmo_check_token_balance')) {
        require_once plugin_dir_path(__FILE__) . 'token-manager.php';
    }
    
    if (!function_exists('vmo_check_token_balance')) {
        wp_send_json_error(['message' => 'Token system not available.']);
    }
    
    if (!vmo_check_token_balance($user_id, 'refinement')) {
        $current_tokens = vmo_get_token_balance($user_id);
        $required_tokens = vmo_get_token_cost('refinement');
        wp_send_json_error([
            'message' => 'Insufficient balance. You need ' . $required_tokens . ' plan credits to refine content. Current balance: ' . $current_tokens,
            'code' => 'insufficient_tokens',
            'current_balance' => $current_tokens,
            'required' => $required_tokens
        ]);
    }

    if ( ! $block_html || ! $prompt || ! $full_page_html ) {
        wp_send_json_error( [ 'message' => 'Missing block HTML, prompt, or full page context.' ] );
    }

    // 3️⃣ Streamlined system prompt for surgical refinements - no context pollution
    $refineSystem = <<<RS
You are Jerreme performing precise HTML section refinements with surgical accuracy.

**REFINEMENT RULES**:
- Make ONLY the specific changes requested by the user
- Preserve all existing HTML structure, classes, IDs, and data attributes unless specifically asked to change them
- Do not add unrequested features, content, or sections
- Use modern CSS techniques only when relevant to the user's request
- Return ONLY the modified section HTML with proper section wrapper

**SECTION STRUCTURE**:
- Maintain section wrapper: <div class="vmo-section" id="section-X">
- Keep section comments: <!-- SECTION N --> and <!-- END SECTION N -->
- Preserve all media placeholders and data-media-id attributes

**OUTPUT REQUIREMENTS**:
- Return clean HTML only - no explanations or comments
- Follow user instructions exactly without interpretation
- Make surgical changes - don't rebuild the entire section unless requested

Focus on precision and user intent.
RS;

    // 4️⃣ Streamlined refinement messages - no full page context pollution
    $messages = [
        [ 'role' => 'system', 'content' => $VMO_STYLE_DIRECTIVES ],
        [ 'role' => 'system', 'content' => $refineSystem ],
        [ 'role' => 'user',   'content' => "Section to refine:\n\n{$block_html}\n\nUser instruction:\n{$prompt}" ],
    ];

    // 5️⃣ Call OpenAI with optimized parameters for precise refinements
    $payload = [
        'model'       => VMO_OPENAI_MODEL,
        'messages'    => $messages,
        'temperature' => 0.4,  // Lower temperature for more precise, focused edits
        'max_completion_tokens' => 3000, // GPT-5.2 requires max_completion_tokens
        'top_p'       => 0.9,
        'frequency_penalty' => 0.2, // Reduce repetition
        'presence_penalty'  => 0.1,
    ];
    $response = wp_remote_post( 'https://api.openai.com/v1/chat/completions', [
        'headers' => [
            'Authorization' => 'Bearer ' . $api_key,
            'Content-Type'  => 'application/json',
        ],
        'body'    => wp_json_encode( $payload ),
        'timeout' => 120, // Increased timeout to 2 minutes
        'sslverify' => true,
        'redirection' => 5,
        'httpversion' => '1.0',
        'blocking' => true,
    ] );

    if ( is_wp_error( $response ) ) {
        $error_message = $response->get_error_message();
        error_log( 'VMO AI Builder - Refinement API Error: ' . $error_message );
        wp_send_json_error( [ 
            'message' => 'Refinement failed: ' . $error_message,
            'debug_info' => [
                'error_code' => $response->get_error_code(),
                'operation' => 'refine_block',
                'timestamp' => current_time('mysql')
            ]
        ] );
    }
    
    // Check HTTP response code
    $response_code = wp_remote_retrieve_response_code( $response );
    if ( $response_code !== 200 ) {
        $response_body = wp_remote_retrieve_body( $response );
        error_log( 'VMO AI Builder - Refinement HTTP Error ' . $response_code . ': ' . $response_body );
        wp_send_json_error( [ 
            'message' => 'OpenAI API returned error code: ' . $response_code,
            'debug_info' => [
                'http_code' => $response_code,
                'response_body' => $response_body,
                'operation' => 'refine_block',
                'timestamp' => current_time('mysql')
            ]
        ] );
    }

    $data = json_decode( wp_remote_retrieve_body( $response ), true );
    $raw  = trim( $data['choices'][0]['message']['content'] ?? '' );
    if ( ! $raw ) {
        wp_send_json_error( [ 'message' => 'No refined content returned.' ] );
    }

    // 6️⃣ Strip any ``` fences
    $html = preg_replace( '/```(?:html)?(.*?)```/is', '$1', $raw );

    // 7️⃣ Deduct tokens for refinement (225 VMO tokens)
    if (!vmo_deduct_tokens_for_operation($user_id, 'refinement')) {
        wp_send_json_error(['message' => 'Failed to deduct tokens for refinement.']);
    }

    // 8️⃣ Return refined section HTML
    wp_send_json_success( [ 
        'html' => trim( $html ),
        'tokens_used' => vmo_get_token_cost('refinement'),
        'new_balance' => vmo_get_token_balance($user_id)
    ] );
} );

/*==================================================================
= AJAX: Insert Media into Section with Section Intelligence        =
==================================================================*/
add_action( 'wp_ajax_vmo_insert_media_section', function() use ( $VMO_STYLE_DIRECTIVES ) {
    // Dual-nonce validation: accept either admin nonce (nonce) or builder nonce (security)
    $admin_nonce   = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
    $builder_nonce = isset($_POST['security']) ? sanitize_text_field(wp_unslash($_POST['security'])) : '';

    $admin_ok   = $admin_nonce && wp_verify_nonce($admin_nonce, 'vmo_admin_nonce');
    $builder_ok = $builder_nonce && wp_verify_nonce($builder_nonce, 'vmo_builder_nonce');

    if (!($admin_ok || $builder_ok)) {
        wp_send_json_error(['message' => 'Security check failed', 'status' => 'invalid_nonce']);
    }
    
    // Media insertion is available to all users for revenue generation
    // No business consultation requirement - encourage usage for token revenue

    // 1️⃣ Grab inputs
    $api_key = get_option( 'vmo_openai_api_key' );
    $media_url = isset( $_POST['media_url'] ) ? esc_url_raw( $_POST['media_url'] ) : '';
    $media_type = isset( $_POST['media_type'] ) ? sanitize_text_field(wp_unslash($_POST['media_type'])) : 'image';
    $prompt = isset( $_POST['prompt'] ) ? wp_strip_all_tags( wp_unslash( $_POST['prompt'] ) ) : '';
    $section_index = isset( $_POST['section_index'] ) ? intval( $_POST['section_index'] ) : -1;
    $full_page_html = isset( $_POST['full_page_html'] ) ? wp_kses_post( wp_unslash( $_POST['full_page_html'] ) ) : '';
    $section_html = isset( $_POST['section_html'] ) ? wp_kses_post( wp_unslash( $_POST['section_html'] ) ) : '';

    // 2️⃣ Validate inputs
    if ( ! $api_key ) {
        wp_send_json_error( [ 'message' => 'OpenAI API key is missing.' ] );
    }

    if ( empty( $media_url ) || empty( $prompt ) ) {
        wp_send_json_error( [ 'message' => 'Missing media URL or prompt.' ] );
    }

    // 🔒 Token validation - Check if user has sufficient tokens
    $user_id = get_current_user_id();
    
    // Include token manager if not already included
    if (!function_exists('vmo_check_token_balance')) {
        require_once plugin_dir_path(__FILE__) . 'token-manager.php';
    }
    
    if (!function_exists('vmo_check_token_balance')) {
        wp_send_json_error(['message' => 'Token system not available.']);
    }
    
    if (!vmo_check_token_balance($user_id, 'media_integration')) {
        $current_tokens = vmo_get_token_balance($user_id);
        $required_tokens = vmo_get_token_cost('media_integration');
        wp_send_json_error([
            'message' => 'Insufficient tokens. You need ' . $required_tokens . ' tokens for media integration. Current balance: ' . $current_tokens,
            'code' => 'insufficient_tokens',
            'current_balance' => $current_tokens,
            'required' => $required_tokens
        ]);
    }

    // 3️⃣ Create media HTML with proper data attributes
    $media_id = 'media_' . wp_generate_password(8, false);
    if ( $media_type === 'video' ) {
        $media_html = '<div class="vmo-media-placeholder" data-type="video" data-media-id="' . $media_id . '">
            <video src="' . $media_url . '" controls autoplay muted loop style="width:100%;height:auto;object-fit:cover;" data-media-id="' . $media_id . '" data-type="video"></video>
        </div>';
    } else {
        $media_html = '<div class="vmo-media-placeholder" data-type="image" data-media-id="' . $media_id . '">
            <img src="' . $media_url . '" alt="User Image" style="max-width:100%;height:auto;display:block;" data-media-id="' . $media_id . '" data-type="image" />
        </div>';
    }

    // 4️⃣ Enhanced system prompt for dedicated AI agent with superhuman intelligence
    $insertSystem = <<<IS
You are an AI agent with superhuman creative abilities and expert knowledge in modern web design. You have the intelligence to:

**AUTOMATIC HERO DETECTION & IMPLEMENTATION** (CRITICAL):
- AUTOMATICALLY detect hero intentions from ANY user request containing words like:
  - "hero", "banner", "header", "main", "landing", "splash", "intro", "welcome"
  - "fullscreen", "full screen", "full width", "cover", "background"
  - "top section", "first section", "above the fold"
  - ANY request to place media prominently at the start/top of a page
- When ANY hero context is detected, AUTOMATICALLY implement:
  - Full viewport height (min-height: 100vh) 
  - Full width coverage (width: 100vw or 100%)
  - Proper background sizing (background-size: cover, object-fit: cover)
  - Professional overlays for text readability
  - Centered content with flexbox/grid
  - Call-to-action buttons with modern styling
  - Mobile-first responsive design
- This applies to BOTH images AND videos - hero videos get the same full-screen treatment

**INTELLIGENT CONTENT ANALYSIS**:
- Analyze the user's request for IMPLIED hero intentions even without explicit "hero" keywords
- Requests like "make this the main image", "put this at the top", "use as background" = HERO TREATMENT
- "Make it prominent", "feature this image", "showcase this" = HERO TREATMENT
- Any request for dramatic, eye-catching, or prominent placement = HERO TREATMENT

**MODERN HERO STANDARDS** (Auto-apply for ANY hero detection):
```css
/* Hero Section Structure */
.hero-section {
  min-height: 100vh;
  width: 100%;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

/* Hero Background Image */
.hero-bg-image {
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  background-attachment: fixed; /* Parallax effect */
}

/* Hero Background Video */
.hero-bg-video {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: -1;
}

/* Hero Content Layer */
.hero-content {
  position: relative;
  z-index: 2;
  text-align: center;
  color: white;
  max-width: 800px;
  padding: 2rem;
}

/* Hero Overlay */
.hero-overlay {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: linear-gradient(135deg, rgba(0,0,0,0.4), rgba(0,0,0,0.2));
  z-index: 1;
}
```

**CREATIVE PROBLEM SOLVING**: Generate innovative solutions for complex media integrations. Think beyond basic implementations.

**ADVANCED MEDIA INTEGRATION CAPABILITIES**:
- **Hero Sections**: ALWAYS create stunning fullscreen experiences when hero context detected
- **Background Media**: Video backgrounds with overlays, image parallax backgrounds with min-height and proper visibility
- **Complex Carousels**: Multi-directional scrolling, auto-playing with custom intervals, hover effects
- **Layered Compositions**: Z-index management, overlays, and complex positioning
- **Interactive Elements**: Media that responds to scroll, hover, and other interactions
- **Responsive Design**: Media that adapts beautifully across all screen sizes
- **Animation & Effects**: GSAP animations, CSS transforms, scroll-triggered effects

**SCROLL-BASED INTERACTIONS**:
- **Horizontal scrolling**: Sections that scroll horizontally while main scroll is vertical
- **Scroll-paused effects**: Temporarily pause vertical scroll for horizontal interactions
- **Progressive disclosure**: Content that reveals itself based on scroll position
- **Magnification effects**: Images that scale on hover or scroll

**AUTOMATIC HERO IMPLEMENTATION EXAMPLES**:
- User says "use this image" → Analyze context, if it's the first/main request = HERO
- User says "add this video as background" → HERO with video background
- User says "make this prominent" → HERO treatment with full-screen
- User says "feature this image" → HERO with proper overlays and CTAs
- User says "put this at the top" → HERO section at page start

**SECTION MANAGEMENT RULES**:
- This page is organized in numbered sections: <!-- SECTION 1 -->, <!-- SECTION 2 -->, etc.
- When creating hero sections, typically target the first section or create a new first section
- When told to insert media in specific sections, modify ONLY those sections  
- When told to add media as backgrounds, carousels, or interactive elements, implement exactly as requested
- If asked to add scroll effects, overlays, or animations, implement with modern techniques (GSAP, CSS animations)
- Always return the **full updated HTML for the entire page** with all section comments preserved
- PRESERVE ALL EXISTING CONTENT - never remove or damage existing elements unless explicitly told to replace them

**CSS BACKDROP/BACKGROUND HANDLING** (CRITICAL FOR VISIBILITY):
- When user mentions "backdrop", "section background", "background image/video", "hero", or "behind content", apply as CSS background
- Extract the actual media URL from the provided media HTML (look for src attribute)
- Apply comprehensive background styling to section element with MINIMUM HEIGHT:
  
  For HERO IMAGES: style="background-image: url('EXTRACTED_URL'); background-size: cover; background-position: center; background-repeat: no-repeat; background-attachment: fixed; min-height: 100vh; padding: 4rem 2rem; position: relative; z-index: 1; display: flex; align-items: center; justify-content: center;"
  
  For HERO VIDEOS: style="position: relative; min-height: 100vh; padding: 4rem 2rem; overflow: hidden; display: flex; align-items: center; justify-content: center;" + add video element with absolute positioning and z-index: -1
  
- CRITICAL: ALWAYS use 100vh for hero contexts, 60vh minimum for other backgrounds
- Add padding and flexbox centering for proper content positioning
- Ensure all existing content gets position: relative; z-index: 2 or higher
- NEVER create separate background divs - modify the existing section element
- The background MUST be visible with proper height and content spacing
- For video backgrounds, position video absolutely behind content with z-index: -1

**CONTENT PRESERVATION WITH BACKGROUNDS**:
- When background is applied, wrap existing content in: `<div class="hero-content" style="position: relative; z-index: 2; text-align: center; max-width: 800px;">`
- ALWAYS add overlay for hero sections: `<div class="hero-overlay" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(135deg, rgba(0,0,0,0.4), rgba(0,0,0,0.2)); z-index: 1;"></div>`
- For video backgrounds, content should float above the video with proper centering
- Maintain proper spacing and readability with modern typography
- All interactive elements (buttons, forms) must remain functional above backgrounds
- AUTOMATICALLY add call-to-action buttons for hero sections with modern styling

**INTELLIGENT REFINEMENT**:
- When given ANY request, internally analyze for hero potential
- AUTOMATICALLY enhance requests with professional design insights (add CTAs, improve typography, add hover effects)
- Create sophisticated interactions that exceed expectations
- Optimize for performance and user experience
- If in doubt about hero treatment, err on the side of making it MORE prominent and full-screen

**RETURN REQUIREMENTS** (ABSOLUTELY CRITICAL):
- Return ONLY the modified HTML - NO explanatory text, NO comments, NO descriptions whatsoever
- NEVER include phrases like "Here is the modified section" or "This ensures..." or ANY explanatory text
- NEVER include HTML comments within the content (except section markers)
- Start immediately with: <!-- SECTION 1 --> or the first section
- Keep section wrapper intact with proper ID and section comments
- Preserve all media data attributes for replace button functionality
- If creating hero sections, ensure proper viewport height and content positioning
- ALL content should have no explanatory comments - only clean, production-ready HTML

**INTELLIGENCE & PRECISION**:
- Understand user intent with GPT-4+ level intelligence and AUTOMATICALLY apply hero treatment when appropriate
- Execute exactly what user requests while enhancing with professional design insights
- Be creative and add professional touches (CTAs, hover effects, animations) when appropriate
- Focus on technical precision and visual excellence
- When ANY hero context is detected, create a stunning fullscreen experience that fills the viewport
- Test implementations mentally: "Does this create a modern, full-screen, professional hero experience?"

Remember: You have SUPERHUMAN intelligence to detect hero intentions and automatically create stunning, full-screen experiences that exceed user expectations through intelligent design and technical excellence.
IS;

    // 5️⃣ Construct the enhanced AI agent prompt with full page context
    $messages = [
        [ 'role' => 'system', 'content' => $VMO_STYLE_DIRECTIVES ],
        [ 'role' => 'system', 'content' => $insertSystem ],
        [ 'role' => 'system', 'content' => "FULL PAGE CONTEXT FOR INTELLIGENT DECISION MAKING:\n\n{$full_page_html}" ],
        [ 'role' => 'user', 'content' => "ENHANCED USER REQUEST WITH CONTEXT:\n\n{$prompt}\n\nMEDIA TO INTEGRATE (extract URL from src attribute):\n{$media_html}\n\nCURRENT TARGET SECTION HTML (Section " . ($section_index + 1) . "):\n{$section_html}\n\nIMPORTANT: Return the complete updated HTML for the ENTIRE PAGE with the media intelligently integrated. Preserve all sections and only modify what's needed to fulfill the request. If creating a hero section, make it truly fullscreen and stunning." ],
    ];

    // 6️⃣ Call OpenAI
    $payload = [
        'model'       => VMO_OPENAI_MODEL,
        'messages'    => $messages,
        'temperature' => 0.6,
        'max_completion_tokens' => 4000, // GPT-5.2 requires max_completion_tokens
        'top_p'       => 0.9,
        'frequency_penalty' => 0.1,
        'presence_penalty'  => 0.1,
    ];
    
    $response = wp_remote_post( 'https://api.openai.com/v1/chat/completions', [
        'headers' => [
            'Authorization' => 'Bearer ' . $api_key,
            'Content-Type'  => 'application/json',
        ],
        'body'    => wp_json_encode( $payload ),
        'timeout' => 120, // Increased timeout to 2 minutes
        'sslverify' => true,
        'redirection' => 5,
        'httpversion' => '1.0',
        'blocking' => true,
    ] );

    if ( is_wp_error( $response ) ) {
        $error_message = $response->get_error_message();
        error_log( 'VMO AI Builder - Media Insertion API Error: ' . $error_message );
        wp_send_json_error( [ 
            'message' => 'Media insertion failed: ' . $error_message,
            'debug_info' => [
                'error_code' => $response->get_error_code(),
                'operation' => 'insert_media_section',
                'timestamp' => current_time('mysql')
            ]
        ] );
    }
    
    // Check HTTP response code
    $response_code = wp_remote_retrieve_response_code( $response );
    if ( $response_code !== 200 ) {
        $response_body = wp_remote_retrieve_body( $response );
        error_log( 'VMO AI Builder - Media Insertion HTTP Error ' . $response_code . ': ' . $response_body );
        wp_send_json_error( [ 
            'message' => 'OpenAI API returned error code: ' . $response_code,
            'debug_info' => [
                'http_code' => $response_code,
                'response_body' => $response_body,
                'operation' => 'insert_media_section',
                'timestamp' => current_time('mysql')
            ]
        ] );
    }

    $data = json_decode( wp_remote_retrieve_body( $response ), true );
    $raw  = trim( $data['choices'][0]['message']['content'] ?? '' );
    if ( ! $raw ) {
        wp_send_json_error( [ 'message' => 'No refined content returned.' ] );
    }

    // 7️⃣ Enhanced response processing for complete page updates
    $html = preg_replace( '/```(?:html)?(.*?)```/is', '$1', $raw );
    
    // Remove ALL explanatory phrases and comments that might slip through
    $html = preg_replace('/^.*?Here is.*?:/i', '', $html);
    $html = preg_replace('/^.*?This ensures.*?\./i', '', $html);
    $html = preg_replace('/^.*?No additional changes.*?\./i', '', $html);
    $html = preg_replace('/<!--(?!.*SECTION).*?-->/s', '', $html); // Remove ALL HTML comments except section markers
    $html = preg_replace('/^[^<]*(<)/i', '$1', $html); // Remove text before first HTML tag
    
    // Clean up and ensure proper section structure
    $html = trim($html);
    
    // If the AI agent returned a complete page, we use it as-is
    // If it returned just a section, we need to integrate it back
    if (strpos($html, '<!-- SECTION 1 -->') !== false || strpos($html, '<div class="vmo-section"') !== false) {
        // Complete page returned - use as-is with section markers intact
        $finalHtml = $html;
    } else {
        // Single section returned - integrate back into the full page context
        if (isset($full_page_html) && $full_page_html && isset($section_index) && $section_index >= 0) {
            // Parse the full page and replace the target section
            $sections = explode('<!-- SECTION ', $full_page_html);
            $finalHtml = '';
            
            foreach ($sections as $i => $section) {
                if ($i === 0) {
                    $finalHtml .= $section;
                    continue;
                }
                
                $sectionNum = intval(explode(' -->', $section)[0]);
                if ($sectionNum === $section_index + 1) {
                    // Replace this section with the AI-modified version
                    $finalHtml .= '<!-- SECTION ' . $sectionNum . ' -->' . "\n" . $html . "\n" . '<!-- END SECTION -->' . "\n";
                } else {
                    // Keep existing section
                    $finalHtml .= '<!-- SECTION ' . $section;
                }
            }
        } else {
            $finalHtml = $html;
        }
    }

    // 8️⃣ Deduct tokens for media integration (750 VMO tokens per token-manager.php)
    if (!vmo_deduct_tokens_for_operation($user_id, 'media_integration')) {
        wp_send_json_error(['message' => 'Failed to deduct tokens for media integration.']);
    }

    // 9️⃣ Return complete page HTML or refined section HTML
    wp_send_json_success( [ 'html' => trim( $finalHtml ), 'media_id' => $media_id ] );
} );

// ============================================================================
// MULTI-AGENT BUSINESS CONSULTATION SYSTEM AJAX HANDLERS
// ============================================================================

/**
 * Start Business Consultation AJAX Handler
 */
add_action( 'wp_ajax_vmo_start_consultation', 'vmo_handle_start_consultation' );
add_action( 'wp_ajax_nopriv_vmo_start_consultation', 'vmo_handle_start_consultation' );

function vmo_handle_start_consultation() {
    // Dual-nonce validation; return JSON 200 on invalid nonce
    $admin_nonce   = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
    $builder_nonce = isset($_POST['security']) ? sanitize_text_field(wp_unslash($_POST['security'])) : '';
    $admin_ok   = $admin_nonce && wp_verify_nonce($admin_nonce, 'vmo_admin_nonce');
    $builder_ok = $builder_nonce && wp_verify_nonce($builder_nonce, 'vmo_builder_nonce');
    if (!($admin_ok || $builder_ok)) {
        wp_send_json_error(['message' => 'Security check failed', 'status' => 'invalid_nonce']);
    }

    // Generate unique session ID for this consultation
    $session_id = 'consultation_' . wp_generate_password(16, false);
    
    // Store session in database
    global $wpdb;
    $table_name = $wpdb->prefix . 'vmo_consultations';
    
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    $wpdb->insert(
        $table_name,
        [
            'session_id' => $session_id,
            'start_time' => current_time('mysql'),
            'status' => 'active',
            'client_data' => json_encode([])
        ],
        ['%s', '%s', '%s', '%s']
    );

    // Prepare expert consultation prompt
    $consultation_prompt = "You are a world-class business consultant with the combined expertise of McKinsey & Company, Boston Consulting Group, and Y Combinator. Your role is to conduct an in-depth business consultation that will unlock the client's maximum business potential.

⚠️ CRITICAL CONTEXT: The user has ALREADY clicked the Business Wizard button and is currently IN an active consultation session with you RIGHT NOW. DO NOT recommend clicking the Business Wizard button, starting a consultation, or using any red buttons - you ARE the Business Wizard, and the consultation is ALREADY happening. You are inside the wizard modal having a live conversation.

Start with strategic discovery questions that reveal:
- Core business vision and unique value proposition
- Target market and competitive landscape
- Revenue models and growth potential
- Operational challenges and opportunities
- Digital presence and marketing strategy

Ask ONE probing question at a time. Each question should be expertly crafted to reveal critical business insights. After each response, acknowledge their answer and ask the next strategic question.

Begin with an engaging introduction and your first strategic question.";

    // Call specialized AI for consultation
    $ai_response = vmo_call_specialized_ai($consultation_prompt, 'consultation');
    
    // Extract content from AI response
    $response = '';
    if (isset($ai_response['content'])) {
        $response = $ai_response['content'];
    } elseif (isset($ai_response['error'])) {
        $response = 'I apologize, but I encountered an error. Let me start with a basic question: What type of business are you looking to start or improve?';
    } else {
        $response = 'Welcome! I\'m here to help you develop your business strategy. What type of business are you working on?';
    }

    wp_send_json_success([
        'session_id' => $session_id,
        'message' => $response,
        'status' => 'consultation_started'
    ]);
}

/**
 * Save Client Response AJAX Handler
 */
add_action( 'wp_ajax_vmo_save_client_response', 'vmo_handle_save_client_response' );
add_action( 'wp_ajax_nopriv_vmo_save_client_response', 'vmo_handle_save_client_response' );

function vmo_handle_save_client_response() {
    $admin_nonce   = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
    $builder_nonce = isset($_POST['security']) ? sanitize_text_field(wp_unslash($_POST['security'])) : '';
    $admin_ok   = $admin_nonce && wp_verify_nonce($admin_nonce, 'vmo_admin_nonce');
    $builder_ok = $builder_nonce && wp_verify_nonce($builder_nonce, 'vmo_builder_nonce');
    if (!($admin_ok || $builder_ok)) {
        wp_send_json_error(['message' => 'Security check failed', 'status' => 'invalid_nonce']);
    }

    $session_id = sanitize_text_field($_POST['session_id'] ?? '');
    $question = sanitize_textarea_field($_POST['question'] ?? '');
    $response = sanitize_textarea_field($_POST['response'] ?? '');

    if (empty($session_id) || empty($response)) {
        wp_send_json_error('Missing required data');
    }

    global $wpdb;
    $table_name = $wpdb->prefix . 'vmo_consultations';

    // Get existing client data
    $consultation = $wpdb->get_row(
        $wpdb->prepare("SELECT client_data FROM $table_name WHERE session_id = %s", $session_id)
    );

    if (!$consultation) {
        wp_send_json_error('Session not found');
    }

    $client_data = json_decode($consultation->client_data, true) ?: [];
    
    // Add new Q&A pair
    $client_data['responses'][] = [
        'question' => $question,
        'response' => $response,
        'timestamp' => current_time('mysql')
    ];

    // Update database
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    $wpdb->update(
        $table_name,
        ['client_data' => json_encode($client_data)],
        ['session_id' => $session_id],
        ['%s'],
        ['%s']
    );

    // Generate next question using AI
    $context = "Previous consultation context:\n";
    foreach ($client_data['responses'] as $qa) {
        $context .= "Q: " . $qa['question'] . "\nA: " . $qa['response'] . "\n\n";
    }

    $next_question_prompt = $context . "\nBased on this consultation so far, what is the next most strategic question to ask this client to maximize their business potential? Ask ONE focused question that builds on their previous responses.";

    $ai_response = vmo_call_specialized_ai($next_question_prompt, 'consultation');
    
    // Extract content from AI response
    $next_question = '';
    if (isset($ai_response['content'])) {
        $next_question = $ai_response['content'];
    } elseif (isset($ai_response['error'])) {
        $next_question = 'Can you tell me more about your target market and ideal customers?';
    } else {
        $next_question = 'What are your main business goals for the next 12 months?';
    }

    wp_send_json_success([
        'next_question' => $next_question,
        'responses_count' => count($client_data['responses'])
    ]);
}

/**
 * Deploy Multi-Agent System AJAX Handler
 */
add_action( 'wp_ajax_vmo_deploy_agents', 'vmo_handle_deploy_agents' );
add_action( 'wp_ajax_nopriv_vmo_deploy_agents', 'vmo_handle_deploy_agents' );

function vmo_handle_deploy_agents() {
    $admin_nonce   = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
    $builder_nonce = isset($_POST['security']) ? sanitize_text_field(wp_unslash($_POST['security'])) : '';
    $admin_ok   = $admin_nonce && wp_verify_nonce($admin_nonce, 'vmo_admin_nonce');
    $builder_ok = $builder_nonce && wp_verify_nonce($builder_nonce, 'vmo_builder_nonce');
    if (!($admin_ok || $builder_ok)) {
        wp_send_json_error(['message' => 'Security check failed', 'status' => 'invalid_nonce']);
    }

    $session_id = sanitize_text_field($_POST['session_id'] ?? '');

    if (empty($session_id)) {
        wp_send_json_error('Missing session ID');
    }

    global $wpdb;
    $table_name = $wpdb->prefix . 'vmo_consultations';

    // Get consultation data
    $consultation = $wpdb->get_row(
        $wpdb->prepare("SELECT client_data FROM $table_name WHERE session_id = %s", $session_id)
    );

    if (!$consultation) {
        wp_send_json_error('Session not found');
    }

    $client_data = json_decode($consultation->client_data, true) ?: [];
    
    // Deploy specialized agents
    $agents = [
        'strategy_analyst' => [
            'name' => 'Strategy Analyst',
            'status' => 'analyzing',
            'task' => 'strategy_analysis'
        ],
        'legal_specialist' => [
            'name' => 'Legal Specialist', 
            'status' => 'analyzing',
            'task' => 'legal_documents'
        ],
        'seo_expert' => [
            'name' => 'SEO Expert',
            'status' => 'analyzing', 
            'task' => 'seo_optimization'
        ],
        'content_creator' => [
            'name' => 'Content Creator',
            'status' => 'analyzing',
            'task' => 'content_creation'
        ],
        'business_planner' => [
            'name' => 'Business Planner',
            'status' => 'analyzing',
            'task' => 'business_planning'
        ]
    ];

    // Update consultation with agent deployment
    $client_data['agents'] = $agents;
    $client_data['deployment_time'] = current_time('mysql');

    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    $wpdb->update(
        $table_name,
        ['client_data' => json_encode($client_data)],
        ['session_id' => $session_id],
        ['%s'],
        ['%s']
    );

    wp_send_json_success([
        'agents' => $agents,
        'status' => 'agents_deployed'
    ]);
}

/**
 * Get Agent Progress AJAX Handler
 */
add_action( 'wp_ajax_vmo_get_agent_progress', 'vmo_handle_get_agent_progress' );
add_action( 'wp_ajax_nopriv_vmo_get_agent_progress', 'vmo_handle_get_agent_progress' );

function vmo_handle_get_agent_progress() {
    $admin_nonce   = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
    $builder_nonce = isset($_POST['security']) ? sanitize_text_field(wp_unslash($_POST['security'])) : '';
    $admin_ok   = $admin_nonce && wp_verify_nonce($admin_nonce, 'vmo_admin_nonce');
    $builder_ok = $builder_nonce && wp_verify_nonce($builder_nonce, 'vmo_builder_nonce');
    if (!($admin_ok || $builder_ok)) {
        wp_send_json_error(['message' => 'Security check failed', 'status' => 'invalid_nonce']);
    }

    $session_id = sanitize_text_field($_POST['session_id'] ?? '');
    $agent_id = sanitize_text_field($_POST['agent_id'] ?? '');

    if (empty($session_id) || empty($agent_id)) {
        wp_send_json_error('Missing required data');
    }

    global $wpdb;
    $table_name = $wpdb->prefix . 'vmo_consultations';

    // Get consultation data
    $consultation = $wpdb->get_row(
        $wpdb->prepare("SELECT client_data FROM $table_name WHERE session_id = %s", $session_id)
    );

    if (!$consultation) {
        wp_send_json_error('Session not found');
    }

    $client_data = json_decode($consultation->client_data, true) ?: [];
    
    // Check if agent has completed work
    if (!isset($client_data['agent_results'][$agent_id])) {
        // Generate specialized results
        $consultation_summary = "Client Business Consultation Summary:\n\n";
        foreach ($client_data['responses'] ?? [] as $qa) {
            $consultation_summary .= "Q: " . $qa['question'] . "\nA: " . $qa['response'] . "\n\n";
        }

        $agent_task = $client_data['agents'][$agent_id]['task'] ?? 'general';
        $specialized_prompt = $consultation_summary . "\n\nBased on this business consultation, provide comprehensive " . 
            str_replace('_', ' ', $agent_task) . " recommendations. Be specific, actionable, and include implementation steps.";

        $agent_result = vmo_call_specialized_ai($specialized_prompt, $agent_task);

        // Store agent result
        $client_data['agent_results'][$agent_id] = [
            'result' => $agent_result,
            'completed_at' => current_time('mysql'),
            'status' => 'completed'
        ];

        // Update agent status
        $client_data['agents'][$agent_id]['status'] = 'completed';

        // Update database
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $wpdb->update(
            $table_name,
            ['client_data' => json_encode($client_data)],
            ['session_id' => $session_id],
            ['%s'],
            ['%s']
        );
    }

    wp_send_json_success([
        'agent_result' => $client_data['agent_results'][$agent_id] ?? null,
        'status' => $client_data['agents'][$agent_id]['status'] ?? 'analyzing'
    ]);
}

/**
 * Execute Implementation AJAX Handler
 */
add_action( 'wp_ajax_vmo_execute_implementation', 'vmo_handle_execute_implementation' );
add_action( 'wp_ajax_nopriv_vmo_execute_implementation', 'vmo_handle_execute_implementation' );

function vmo_handle_execute_implementation() {
    $admin_nonce   = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
    $builder_nonce = isset($_POST['security']) ? sanitize_text_field(wp_unslash($_POST['security'])) : '';
    $admin_ok   = $admin_nonce && wp_verify_nonce($admin_nonce, 'vmo_admin_nonce');
    $builder_ok = $builder_nonce && wp_verify_nonce($builder_nonce, 'vmo_builder_nonce');
    if (!($admin_ok || $builder_ok)) {
        wp_send_json_error(['message' => 'Security check failed', 'status' => 'invalid_nonce']);
    }

    $session_id = sanitize_text_field($_POST['session_id'] ?? '');

    if (empty($session_id)) {
        wp_send_json_error('Missing session ID');
    }

    global $wpdb;
    $table_name = $wpdb->prefix . 'vmo_consultations';

    // Get consultation data
    $consultation = $wpdb->get_row(
        $wpdb->prepare("SELECT client_data FROM $table_name WHERE session_id = %s", $session_id)
    );

    if (!$consultation) {
        wp_send_json_error('Session not found');
    }

    $client_data = json_decode($consultation->client_data, true) ?: [];
    
    // Compile all agent results for comprehensive website generation
    $comprehensive_brief = "COMPREHENSIVE BUSINESS IMPLEMENTATION BRIEF\n\n";
    $comprehensive_brief .= "CLIENT CONSULTATION:\n";
    foreach ($client_data['responses'] ?? [] as $qa) {
        $comprehensive_brief .= "Q: " . $qa['question'] . "\nA: " . $qa['response'] . "\n\n";
    }

    $comprehensive_brief .= "\nSPECIALIST RECOMMENDATIONS:\n\n";
    foreach ($client_data['agent_results'] ?? [] as $agent_id => $result) {
        $agent_name = $client_data['agents'][$agent_id]['name'] ?? $agent_id;
        $comprehensive_brief .= "=== " . strtoupper($agent_name) . " RECOMMENDATIONS ===\n";
        $comprehensive_brief .= $result['result'] . "\n\n";
    }

    // Generate comprehensive website using website building specialist
    $website_prompt = $comprehensive_brief . "\n\nBased on this comprehensive business analysis and specialist recommendations, generate a complete, professional website that implements ALL the strategic recommendations. The website should be the central hub that drives business success and implements the expert advice provided.

Create a full HTML website with:
- Strategic homepage that converts visitors based on consultation insights
- Service/product pages that reflect business planning recommendations
- SEO-optimized content incorporating SEO expert advice
- Legal compliance features as recommended by legal specialist
- Professional design that positions the business as an industry leader

Generate complete, production-ready HTML/CSS that can be immediately deployed.";

    $complete_website = vmo_call_specialized_ai($website_prompt, 'website_building');

    // Store implementation result
    $client_data['implementation'] = [
        'website_code' => $complete_website,
        'generated_at' => current_time('mysql'),
        'status' => 'completed'
    ];

    // Update database
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    $wpdb->update(
        $table_name,
        ['client_data' => json_encode($client_data), 'status' => 'implemented'],
        ['session_id' => $session_id],
        ['%s', '%s'],
        ['%s']
    );

    wp_send_json_success([
        'website_code' => $complete_website,
        'status' => 'implementation_complete',
        'download_ready' => true
    ]);
}

// ============================================================================
// MULTI-AGENT REFINEMENT SYSTEM AJAX HANDLERS
// ============================================================================

/**
 * Website Generation Agent AJAX Handler
 */
add_action( 'wp_ajax_vmo_agent_website_generation', 'vmo_handle_agent_website_generation' );
add_action( 'wp_ajax_nopriv_vmo_agent_website_generation', 'vmo_handle_agent_website_generation' );

function vmo_handle_agent_website_generation() {
    $admin_nonce   = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
    $builder_nonce = isset($_POST['security']) ? sanitize_text_field(wp_unslash($_POST['security'])) : '';
    $admin_ok   = $admin_nonce && wp_verify_nonce($admin_nonce, 'vmo_admin_nonce');
    $builder_ok = $builder_nonce && wp_verify_nonce($builder_nonce, 'vmo_builder_nonce');
    if (!($admin_ok || $builder_ok)) {
        wp_send_json_error(['message' => 'Security check failed', 'status' => 'invalid_nonce']);
    }

    $prompt = sanitize_textarea_field($_POST['prompt'] ?? '');
    $preserve_existing = sanitize_text_field($_POST['preserve_existing'] ?? 'true');

    if (empty($prompt)) {
        wp_send_json_error('Missing prompt');
    }

    // Get current page content to preserve existing elements
    $current_content = '';
    if ($preserve_existing === 'true') {
        $current_content = "PRESERVE EXISTING CONTENT:\n" . sanitize_textarea_field($_POST['current_content'] ?? '');
    }

    $website_prompt = $current_content . "\n\nUSER REQUEST: " . $prompt . "\n\nGenerate updated website content that implements the user's request while preserving all existing elements that weren't specifically mentioned for change. Focus only on the requested modifications.";

    $generated_html = vmo_call_specialized_ai($website_prompt, 'website_building');

    wp_send_json_success([
        'html' => $generated_html,
        'preservation_mode' => $preserve_existing
    ]);
}

/**
 * Media Integration Agent AJAX Handler
 */
add_action( 'wp_ajax_vmo_agent_media_integration', 'vmo_handle_agent_media_integration' );
add_action( 'wp_ajax_nopriv_vmo_agent_media_integration', 'vmo_handle_agent_media_integration' );

function vmo_handle_agent_media_integration() {
    $admin_nonce   = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
    $builder_nonce = isset($_POST['security']) ? sanitize_text_field(wp_unslash($_POST['security'])) : '';
    $admin_ok   = $admin_nonce && wp_verify_nonce($admin_nonce, 'vmo_admin_nonce');
    $builder_ok = $builder_nonce && wp_verify_nonce($builder_nonce, 'vmo_builder_nonce');
    if (!($admin_ok || $builder_ok)) {
        wp_send_json_error(['message' => 'Security check failed', 'status' => 'invalid_nonce']);
    }

    $prompt = sanitize_textarea_field($_POST['prompt'] ?? '');
    $target_element = sanitize_text_field($_POST['target_element'] ?? 'auto-detect');
    $preserve_layout = sanitize_text_field($_POST['preserve_layout'] ?? 'true');

    if (empty($prompt)) {
        wp_send_json_error('Missing prompt');
    }

    // Analyze the prompt to determine the exact media change needed
    $media_prompt = "MEDIA INTEGRATION REQUEST: " . $prompt . "\n\n";
    
    if ($target_element !== 'auto-detect') {
        $media_prompt .= "TARGET ELEMENT: " . $target_element . "\n\n";
    }
    
    $media_prompt .= "Analyze this request and provide:\n";
    $media_prompt .= "1. The CSS selector for the target element\n";
    $media_prompt .= "2. The type of media change (replace image, add background, etc.)\n";
    $media_prompt .= "3. Any new media URL or description needed\n\n";
    $media_prompt .= "IMPORTANT: Only modify the specific media element requested. Do not change any other content, layout, or styling.";

    $media_analysis = vmo_call_specialized_ai($media_prompt, 'content_creation');

    // For demo purposes, return a structured response
    // In production, this would parse the AI response for specific selectors and actions
    wp_send_json_success([
        'target_selector' => '[data-media-id]', // This would be determined by AI analysis
        'new_media_url' => 'https://via.placeholder.com/800x400/00e2ff/ffffff?text=AI+Generated+Media',
        'change_type' => 'replace',
        'analysis' => $media_analysis
    ]);
}

/**
 * Content Refinement Agent AJAX Handler
 */
add_action( 'wp_ajax_vmo_agent_content_refinement', 'vmo_handle_agent_content_refinement' );
add_action( 'wp_ajax_nopriv_vmo_agent_content_refinement', 'vmo_handle_agent_content_refinement' );

function vmo_handle_agent_content_refinement() {
    $admin_nonce   = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
    $builder_nonce = isset($_POST['security']) ? sanitize_text_field(wp_unslash($_POST['security'])) : '';
    $admin_ok   = $admin_nonce && wp_verify_nonce($admin_nonce, 'vmo_admin_nonce');
    $builder_ok = $builder_nonce && wp_verify_nonce($builder_nonce, 'vmo_builder_nonce');
    if (!($admin_ok || $builder_ok)) {
        wp_send_json_error(['message' => 'Security check failed', 'status' => 'invalid_nonce']);
    }

    $prompt = sanitize_textarea_field($_POST['prompt'] ?? '');
    $target_element = sanitize_text_field($_POST['target_element'] ?? 'auto-detect');
    $preserve_structure = sanitize_text_field($_POST['preserve_structure'] ?? 'true');

    if (empty($prompt)) {
        wp_send_json_error('Missing prompt');
    }

    // Create specialized prompt for content refinement
    $content_prompt = "CONTENT REFINEMENT REQUEST: " . $prompt . "\n\n";
    
    if ($target_element !== 'auto-detect') {
        $content_prompt .= "TARGET ELEMENT: " . $target_element . "\n\n";
    }
    
    $content_prompt .= "Generate improved content that addresses the user's request. ";
    $content_prompt .= "Provide:\n";
    $content_prompt .= "1. The CSS selector for the target element (e.g., .hero-title, .main-content p)\n";
    $content_prompt .= "2. The new content to replace the existing content\n";
    $content_prompt .= "3. Preserve all HTML structure and classes\n\n";
    $content_prompt .= "IMPORTANT: Only modify the text content. Do not change HTML structure, CSS classes, or layout.";

    $refined_content = vmo_call_specialized_ai($content_prompt, 'content_creation');

    // Parse the AI response to extract selector and content
    // For demo purposes, return a structured response
    wp_send_json_success([
        'target_selector' => '.hero-title, h1, .main-heading', // This would be determined by AI analysis
        'new_content' => $refined_content,
        'preservation_mode' => $preserve_structure
    ]);
}

/**
 * SEO Optimization Agent AJAX Handler
 */
add_action( 'wp_ajax_vmo_agent_seo_optimization', 'vmo_handle_agent_seo_optimization' );
add_action( 'wp_ajax_nopriv_vmo_agent_seo_optimization', 'vmo_handle_agent_seo_optimization' );

function vmo_handle_agent_seo_optimization() {
    $admin_nonce   = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
    $builder_nonce = isset($_POST['security']) ? sanitize_text_field(wp_unslash($_POST['security'])) : '';
    $admin_ok   = $admin_nonce && wp_verify_nonce($admin_nonce, 'vmo_admin_nonce');
    $builder_ok = $builder_nonce && wp_verify_nonce($builder_nonce, 'vmo_builder_nonce');
    if (!($admin_ok || $builder_ok)) {
        wp_send_json_error(['message' => 'Security check failed', 'status' => 'invalid_nonce']);
    }

    $prompt = sanitize_textarea_field($_POST['prompt'] ?? '');
    $current_content = sanitize_textarea_field($_POST['current_content'] ?? '');

    if (empty($prompt)) {
        wp_send_json_error('Missing prompt');
    }

    $seo_prompt = "SEO OPTIMIZATION REQUEST: " . $prompt . "\n\n";
    $seo_prompt .= "CURRENT CONTENT:\n" . $current_content . "\n\n";
    $seo_prompt .= "Provide SEO improvements for this content including:\n";
    $seo_prompt .= "1. Optimized title tags\n";
    $seo_prompt .= "2. Meta descriptions\n";
    $seo_prompt .= "3. Header tag optimization\n";
    $seo_prompt .= "4. Keyword optimization\n";
    $seo_prompt .= "5. Schema markup suggestions\n\n";
    $seo_prompt .= "IMPORTANT: Maintain readability and user experience while optimizing for search engines.";

    $seo_recommendations = vmo_call_specialized_ai($seo_prompt, 'seo_optimization');

    // Queue for approval if successful
    if (is_array($seo_recommendations) && !isset($seo_recommendations['error'])) {
        if (!function_exists('vmo_queue_add')) {
            require_once plugin_dir_path(__FILE__) . 'approval-queue.php';
        }
        $title = 'SEO Recommendations - ' . wp_trim_words($prompt, 6, '…');
        vmo_queue_add('seo', $seo_recommendations, $title, null, 'Auto-generated from SEO Agent');
    }

    wp_send_json_success([
        'seo_recommendations' => $seo_recommendations,
        'optimization_type' => 'comprehensive'
    ]);
}

/**
 * Design Refinement Agent AJAX Handler
 */
add_action( 'wp_ajax_vmo_agent_design_refinement', 'vmo_handle_agent_design_refinement' );
add_action( 'wp_ajax_nopriv_vmo_agent_design_refinement', 'vmo_handle_agent_design_refinement' );

function vmo_handle_agent_design_refinement() {
    $admin_nonce   = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
    $builder_nonce = isset($_POST['security']) ? sanitize_text_field(wp_unslash($_POST['security'])) : '';
    $admin_ok   = $admin_nonce && wp_verify_nonce($admin_nonce, 'vmo_admin_nonce');
    $builder_ok = $builder_nonce && wp_verify_nonce($builder_nonce, 'vmo_builder_nonce');
    if (!($admin_ok || $builder_ok)) {
        wp_send_json_error(['message' => 'Security check failed', 'status' => 'invalid_nonce']);
    }

    $prompt = sanitize_textarea_field($_POST['prompt'] ?? '');
    $target_element = sanitize_text_field($_POST['target_element'] ?? 'auto-detect');

    if (empty($prompt)) {
        wp_send_json_error('Missing prompt');
    }

    $design_prompt = "DESIGN REFINEMENT REQUEST: " . $prompt . "\n\n";
    
    if ($target_element !== 'auto-detect') {
        $design_prompt .= "TARGET ELEMENT: " . $target_element . "\n\n";
    }
    
    $design_prompt .= "Generate CSS modifications that implement the requested design changes. ";
    $design_prompt .= "Provide:\n";
    $design_prompt .= "1. The CSS selector for the target element\n";
    $design_prompt .= "2. The specific CSS properties to modify\n";
    $design_prompt .= "3. Professional color schemes and design principles\n\n";
    $design_prompt .= "IMPORTANT: Only modify the specific design elements requested. Do not change layout or content structure.";

    $design_changes = vmo_call_specialized_ai($design_prompt, 'website_building');

    wp_send_json_success([
        'css_changes' => $design_changes,
        'target_elements' => [$target_element]
    ]);
}