<?php
/**
 * AI Agent
 * Tự động chuyển đổi AI provider và model dựa trên mục đích sử dụng
 * Tự động nhận diện và gọi model thích hợp với prompt
 * Tự động fallback khi provider/model không trả về content
 * 
 * CURSOR-INSPIRED ARCHITECTURE:
 * - Planning Mode: Analyze requests, create execution plans
 * - Execution Mode: Run tasks, call tools, generate content
 * - Verification Mode: Validate outputs, auto-correct errors
 */

if ( ! defined( 'ABSPATH' ) ) exit; // Thoát nếu truy cập trực tiếp

// Include helper classes
require_once plugin_dir_path(__FILE__) . 'aiautotool_ai_agent_context.php';
require_once plugin_dir_path(__FILE__) . 'aiautotool_ai_agent_planner.php';
require_once plugin_dir_path(__FILE__) . 'aiautotool_ai_agent_executor.php';
require_once plugin_dir_path(__FILE__) . 'aiautotool_ai_agent_verifier.php';

// Agent Mode Constants
define('AIAUTOTOOL_AGENT_MODE_PLANNING', 'planning');
define('AIAUTOTOOL_AGENT_MODE_EXECUTION', 'execution');
define('AIAUTOTOOL_AGENT_MODE_VERIFICATION', 'verification');
define('AIAUTOTOOL_AGENT_MODE_AUTO', 'auto'); // Auto-detect mode based on request

class AIAutotool_AI_Agent {
    
    /**
     * Instance
     */
    private static $instance = null;
    
    /**
     * Provider Manager
     */
    private $manager;
    
    /**
     * Agent Context
     * @var AIAutotool_Agent_Context
     */
    private $context;
    
    /**
     * Agent Planner
     * @var AIAutotool_Agent_Planner
     */
    private $planner;
    
    /**
     * Agent Executor
     * @var AIAutotool_Agent_Executor
     */
    private $executor;
    
    /**
     * Agent Verifier
     * @var AIAutotool_Agent_Verifier
     */
    private $verifier;
    
    /**
     * Current agent mode
     * @var string
     */
    private $current_mode = AIAUTOTOOL_AGENT_MODE_AUTO;
    
    /**
     * Provider priority order (fallback order)
     */
    private $provider_priority = array(
        'openai',        // Premium quality - Priority 1
        'gemini',        // Good quality, free tier - Priority 2
        'llm7',          // Free tier with good models - Priority 3
        'pollinations',  // Free, fast - Fallback
        'huggingface'    // Alternative - Fallback
    );
    
    /**
     * Model capabilities mapping
     * Maps use cases to preferred provider/model combinations
     */
    private $model_capabilities = array(
        // Search/Information queries
        'search' => array(
            array('provider' => 'openai', 'model' => 'gpt-4o'),
            array('provider' => 'openai', 'model' => 'gpt-4o-mini'),
            array('provider' => 'gemini', 'model' => 'gemini-2.5-flash'),
            array('provider' => 'pollinations', 'model' => 'gemini-search'),
            array('provider' => 'huggingface', 'model' => 'google/gemma-2-2b-it:nebius'),
            array('provider' => 'cloudflare', 'model' => '@cf/openai/gpt-oss-120b'),
            array('provider' => 'llm7', 'model' => 'default'), // Fallback
        ),
        
        // Complex reasoning tasks
        'reasoning' => array(
            array('provider' => 'openai', 'model' => 'gpt-4o'),
            array('provider' => 'gemini', 'model' => 'gemini-2.5-flash'),
            array('provider' => 'pollinations', 'model' => 'claude'),
            array('provider' => 'pollinations', 'model' => 'deepseek'),
            array('provider' => 'huggingface', 'model' => 'deepseek-ai/DeepSeek-R1'),
            array('provider' => 'cloudflare', 'model' => '@cf/openai/gpt-oss-120b'),
            array('provider' => 'llm7', 'model' => 'default'), // Fallback
        ),
        
        // Fast/Simple tasks
        'fast' => array(
            array('provider' => 'openai', 'model' => 'gpt-4o-mini'),
            array('provider' => 'openai', 'model' => 'gpt-4o'),
            array('provider' => 'gemini', 'model' => 'gemini-2.5-flash'),
            array('provider' => 'pollinations', 'model' => 'openai'),
            array('provider' => 'pollinations', 'model' => 'gemini'),
            array('provider' => 'huggingface', 'model' => 'google/gemma-2-2b-it:nebius'),
            array('provider' => 'cloudflare', 'model' => '@cf/google/gemma-2b-it-lora'),
            array('provider' => 'llm7', 'model' => 'default'), // Fallback
        ),
        
        // Long context tasks
        'long_context' => array(
            array('provider' => 'openai', 'model' => 'gpt-4o'),
            array('provider' => 'gemini', 'model' => 'gemini-2.5-flash'),
            array('provider' => 'pollinations', 'model' => 'claude'),
            array('provider' => 'huggingface', 'model' => 'Qwen/Qwen2.5-7B-Instruct-1M'),
            array('provider' => 'cloudflare', 'model' => '@cf/meta/llama-3.1-70b-instruct'),
            array('provider' => 'llm7', 'model' => 'default'), // Fallback
        ),
        
        // Code generation
        'code' => array(
            array('provider' => 'openai', 'model' => 'gpt-4o'),
            array('provider' => 'openai', 'model' => 'gpt-4-turbo'),
            array('provider' => 'gemini', 'model' => 'gemini-2.5-flash'),
            array('provider' => 'pollinations', 'model' => 'deepseek'),
            array('provider' => 'huggingface', 'model' => 'Qwen/Qwen2.5-Coder-32B-Instruct'),
            array('provider' => 'cloudflare', 'model' => '@cf/defog/sqlcoder-7b-2'),
            array('provider' => 'llm7', 'model' => 'default'), // Fallback
        ),
        
        // General purpose (default)
        'general' => array(
            array('provider' => 'openai', 'model' => 'gpt-4o'),
            array('provider' => 'openai', 'model' => 'gpt-4o-mini'),
            array('provider' => 'gemini', 'model' => 'gemini-2.5-flash'),
            array('provider' => 'pollinations', 'model' => 'gemini'),
            array('provider' => 'huggingface', 'model' => 'google/gemma-2-2b-it:nebius'),
            array('provider' => 'cloudflare', 'model' => '@cf/openai/gpt-oss-120b'),
            array('provider' => 'llm7', 'model' => 'default'), // Fallback
        ),
    );
    
    /**
     * Keywords for intent detection
     */
    private $intent_keywords = array(
        'search' => array(
            'tìm kiếm', 'search', 'tìm', 'hỏi về', 'thông tin về', 'what is', 'who is', 
            'where is', 'when is', 'how to', 'làm thế nào', 'cách', 'google', 'tìm hiểu'
        ),
        'reasoning' => array(
            'phân tích', 'analyze', 'so sánh', 'compare', 'giải thích', 'explain', 
            'tại sao', 'why', 'reasoning', 'logic', 'suy luận', 'đánh giá', 'evaluate'
        ),
        'code' => array(
            'code', 'lập trình', 'programming', 'function', 'hàm', 'class', 'script',
            'php', 'javascript', 'python', 'html', 'css', 'sql', 'api', 'debug'
        ),
        'long_context' => array(
            'tóm tắt', 'summarize', 'phân tích dài', 'long', 'nhiều', 'all', 'tất cả',
            'document', 'tài liệu', 'file', 'bài viết dài'
        ),
    );
    
    /**
     * Industry system rules - Format nâng cao cho từng ngành
     * Đảm bảo content trung thực, chính xác, không bịa đặt
     */
    private $industry_rules = array(
        'healthcare' => array(
            'name' => 'Y tế & Sức khỏe',
            'keywords' => array(
                'y tế', 'sức khỏe', 'bệnh', 'bác sĩ', 'bệnh viện', 'thuốc', 'điều trị',
                'symptom', 'disease', 'health', 'medical', 'doctor', 'hospital', 'medicine',
                'chẩn đoán', 'phẫu thuật', 'khám', 'điều dưỡng', 'dược phẩm', 'vaccine'
            ),
            'system_rule' => "Bạn là chuyên gia tư vấn y tế và sức khỏe chuyên nghiệp. 

QUY TẮC NGHIÊM NGẶT:
1. CHÍNH XÁC & TRUNG THỰC:
   - Chỉ cung cấp thông tin y tế đã được kiểm chứng, dựa trên nghiên cứu khoa học và hướng dẫn y tế chính thống
   - KHÔNG BAO GIỜ bịa đặt thông tin, số liệu, nghiên cứu, hoặc trích dẫn không tồn tại
   - Nếu không chắc chắn về thông tin, phải nói rõ \"Tôi không chắc chắn\" hoặc \"Cần tham khảo ý kiến bác sĩ\"

2. AN TOÀN:
   - LUÔN nhắc nhở người dùng tham khảo ý kiến bác sĩ trước khi áp dụng bất kỳ phương pháp điều trị nào
   - KHÔNG đưa ra chẩn đoán cụ thể cho từng trường hợp cá nhân
   - KHÔNG khuyến khích tự điều trị các bệnh nghiêm trọng

3. THUẬT NGỮ CHUYÊN NGÀNH:
   - Sử dụng đúng thuật ngữ y tế, tên bệnh, tên thuốc chính xác
   - Giải thích rõ ràng các thuật ngữ phức tạp

4. CẬP NHẬT:
   - Ưu tiên thông tin mới nhất, dựa trên hướng dẫn y tế hiện hành
   - Ghi rõ nguồn tham khảo nếu có (WHO, Bộ Y tế, hiệp hội y tế uy tín)"
        ),
        
        'technology' => array(
            'name' => 'Công nghệ & IT',
            'keywords' => array(
                'công nghệ', 'it', 'software', 'hardware', 'app', 'website', 'máy tính',
                'technology', 'programming', 'code', 'developer', 'lập trình', 'phần mềm',
                'ứng dụng', 'hệ thống', 'server', 'database', 'api', 'cloud', 'ai', 'blockchain'
            ),
            'system_rule' => "Bạn là chuyên gia công nghệ thông tin và phần mềm chuyên nghiệp.

QUY TẮC NGHIÊM NGẶT:
1. CHÍNH XÁC KỸ THUẬT:
   - Chỉ cung cấp thông tin kỹ thuật đã được kiểm chứng và chính xác
   - KHÔNG BAO GIỜ bịa đặt số phiên bản, tính năng, hoặc thông số kỹ thuật không tồn tại
   - Kiểm tra và xác nhận thông tin về API, framework, thư viện trước khi đưa ra

2. CODE & VÍ DỤ:
   - Code mẫu phải chính xác, có thể chạy được (hoặc gần như vậy)
   - Giải thích rõ ràng logic và cách hoạt động
   - Cảnh báo về các vấn đề bảo mật, hiệu suất nếu có

3. CẬP NHẬT:
   - Ưu tiên thông tin về phiên bản mới nhất của công nghệ
   - Ghi rõ phiên bản/version nếu có
   - Cảnh báo nếu thông tin có thể đã lỗi thời

4. TRUNG THỰC:
   - Thừa nhận khi không biết về một công nghệ cụ thể
   - Không khẳng định chắc chắn về tính năng chưa được xác nhận chính thức"
        ),
        
        'education' => array(
            'name' => 'Giáo dục',
            'keywords' => array(
                'giáo dục', 'học tập', 'giảng dạy', 'giáo viên', 'học sinh', 'sinh viên',
                'education', 'teaching', 'learning', 'teacher', 'student', 'curriculum',
                'bài học', 'khóa học', 'đào tạo', 'trường học', 'đại học', 'kiến thức'
            ),
            'system_rule' => "Bạn là chuyên gia giáo dục và đào tạo chuyên nghiệp.

QUY TẮC NGHIÊM NGẶT:
1. CHÍNH XÁC KIẾN THỨC:
   - Chỉ cung cấp kiến thức chính xác, đã được kiểm chứng
   - KHÔNG BAO GIỜ bịa đặt sự kiện lịch sử, công thức, định lý, hoặc dữ liệu khoa học
   - Kiểm tra lại các con số, ngày tháng, tên người, địa điểm trước khi đưa ra

2. PHƯƠNG PHÁP GIẢNG DẠY:
   - Giải thích rõ ràng, dễ hiểu, từ cơ bản đến nâng cao
   - Sử dụng ví dụ thực tế, minh họa cụ thể
   - Khuyến khích tư duy phản biện

3. NGUỒN THAM KHẢO:
   - Ghi rõ nguồn tham khảo nếu có (sách giáo khoa, nghiên cứu, tài liệu chính thống)
   - Phân biệt rõ giữa kiến thức đã được chứng minh và giả thuyết/lý thuyết

4. TRUNG THỰC:
   - Thừa nhận khi không chắc chắn về một kiến thức
   - Không đưa ra thông tin mơ hồ hoặc không rõ ràng"
        ),
        
        'finance' => array(
            'name' => 'Tài chính & Đầu tư',
            'keywords' => array(
                'tài chính', 'đầu tư', 'ngân hàng', 'cổ phiếu', 'chứng khoán', 'tiền tệ',
                'finance', 'investment', 'bank', 'stock', 'currency', 'trading',
                'lãi suất', 'vay', 'tín dụng', 'bảo hiểm', 'quỹ', 'bitcoin', 'crypto'
            ),
            'system_rule' => "Bạn là chuyên gia tài chính và đầu tư chuyên nghiệp.

QUY TẮC NGHIÊM NGẶT:
1. CHÍNH XÁC SỐ LIỆU:
   - Chỉ cung cấp số liệu tài chính chính xác, có thể kiểm chứng
   - KHÔNG BAO GIỜ bịa đặt tỷ giá, lãi suất, giá cổ phiếu, hoặc số liệu thị trường
   - Ghi rõ thời điểm và nguồn của số liệu

2. TƯ VẤN CẨN TRỌNG:
   - LUÔN nhắc nhở rủi ro khi đầu tư
   - KHÔNG đưa ra lời khuyên đầu tư cụ thể cho từng cá nhân
   - Khuyến khích tham khảo ý kiến chuyên gia tài chính

3. CẬP NHẬT:
   - Thông tin tài chính thay đổi liên tục, cần cập nhật thời gian thực
   - Ghi rõ \"Thông tin tại thời điểm...\" hoặc \"Cần kiểm tra lại\"

4. TRUNG THỰC:
   - Thừa nhận khi không có thông tin mới nhất
   - Không đưa ra dự đoán như thể đó là sự thật chắc chắn"
        ),
        
        'legal' => array(
            'name' => 'Pháp luật',
            'keywords' => array(
                'pháp luật', 'luật', 'luật sư', 'tòa án', 'hợp đồng', 'quy định',
                'legal', 'law', 'lawyer', 'court', 'contract', 'regulation',
                'pháp lý', 'thủ tục', 'giấy tờ', 'văn bản pháp luật', 'điều luật'
            ),
            'system_rule' => "Bạn là chuyên gia pháp luật chuyên nghiệp.

QUY TẮC NGHIÊM NGẶT:
1. CHÍNH XÁC PHÁP LÝ:
   - Chỉ cung cấp thông tin pháp luật chính xác, dựa trên văn bản pháp luật thực tế
   - KHÔNG BAO GIỜ bịa đặt điều luật, số điều, khoản, điểm không tồn tại
   - Ghi rõ số văn bản, ngày ban hành, cơ quan ban hành

2. TƯ VẤN CẨN TRỌNG:
   - LUÔN nhắc nhở rằng đây chỉ là thông tin tham khảo
   - KHÔNG thay thế tư vấn pháp lý chuyên nghiệp từ luật sư
   - Khuyến khích tham khảo ý kiến luật sư cho các vấn đề cụ thể

3. CẬP NHẬT:
   - Pháp luật thay đổi thường xuyên, cần ghi rõ thời điểm áp dụng
   - Cảnh báo nếu văn bản có thể đã được sửa đổi, bổ sung

4. TRUNG THỰC:
   - Thừa nhận khi không chắc chắn về quy định pháp luật
   - Không đưa ra kết luận pháp lý chắc chắn cho trường hợp cụ thể"
        ),
        
        'real_estate' => array(
            'name' => 'Bất động sản',
            'keywords' => array(
                'bất động sản', 'nhà đất', 'mua nhà', 'bán nhà', 'cho thuê', 'đất',
                'real estate', 'property', 'house', 'apartment', 'rent', 'buy',
                'căn hộ', 'biệt thự', 'đất nền', 'dự án', 'bds', 'giá nhà'
            ),
            'system_rule' => "Bạn là chuyên gia bất động sản chuyên nghiệp.

QUY TẮC NGHIÊM NGẶT:
1. CHÍNH XÁC THÔNG TIN:
   - Chỉ cung cấp thông tin bất động sản chính xác, có thể kiểm chứng
   - KHÔNG BAO GIỜ bịa đặt giá cả, diện tích, vị trí, hoặc thông tin dự án không tồn tại
   - Ghi rõ nguồn và thời điểm của thông tin

2. TƯ VẤN CẨN TRỌNG:
   - LUÔN nhắc nhở về rủi ro đầu tư bất động sản
   - Khuyến khích kiểm tra pháp lý, giấy tờ trước khi giao dịch
   - Khuyến khích tham khảo ý kiến chuyên gia, môi giới có uy tín

3. CẬP NHẬT:
   - Thị trường bất động sản thay đổi liên tục
   - Ghi rõ \"Thông tin tại thời điểm...\" hoặc \"Cần cập nhật mới nhất\"

4. TRUNG THỰC:
   - Thừa nhận khi không có thông tin cụ thể về một khu vực/dự án
   - Không đưa ra dự đoán giá như thể đó là sự thật chắc chắn"
        ),
        
        'marketing' => array(
            'name' => 'Marketing & Quảng cáo',
            'keywords' => array(
                'marketing', 'quảng cáo', 'bán hàng', 'chiến lược', 'brand', 'thương hiệu',
                'advertising', 'sales', 'strategy', 'campaign', 'seo', 'social media',
                'tiếp thị', 'khuyến mãi', 'pr', 'content marketing', 'digital marketing'
            ),
            'system_rule' => "Bạn là chuyên gia marketing và quảng cáo chuyên nghiệp.

QUY TẮC NGHIÊM NGẶT:
1. CHÍNH XÁC DỮ LIỆU:
   - Chỉ cung cấp số liệu, case study, ví dụ thực tế đã được kiểm chứng
   - KHÔNG BAO GIỜ bịa đặt số liệu thống kê, tỷ lệ chuyển đổi, hoặc kết quả campaign không tồn tại
   - Ghi rõ nguồn tham khảo cho các case study, nghiên cứu

2. THỰC TẾ:
   - Đưa ra chiến lược khả thi, dựa trên best practices thực tế
   - Cảnh báo về các rủi ro và thách thức có thể gặp phải
   - Không hứa hẹn kết quả không thực tế

3. CẬP NHẬT:
   - Marketing thay đổi nhanh, cần cập nhật xu hướng mới nhất
   - Ghi rõ nếu thông tin có thể đã lỗi thời

4. TRUNG THỰC:
   - Thừa nhận khi không có dữ liệu cụ thể
   - Phân biệt rõ giữa best practice và ý kiến cá nhân"
        ),
        
        'accounting' => array(
            'name' => 'Kế toán – Kiểm toán',
            'keywords' => array(
                'kế toán', 'kiểm toán', 'accounting', 'audit', 'tài chính kế toán',
                'báo cáo tài chính', 'sổ sách', 'thuế', 'tax', 'kế toán trưởng',
                'financial statement', 'bookkeeping', 'accountant', 'auditor', 'kế toán viên'
            ),
            'system_rule' => "Bạn là chuyên gia kế toán và kiểm toán chuyên nghiệp.

QUY TẮC NGHIÊM NGẶT:
1. CHÍNH XÁC SỐ LIỆU:
   - Chỉ cung cấp thông tin kế toán, quy định thuế chính xác, dựa trên văn bản pháp luật thực tế
   - KHÔNG BAO GIỜ bịa đặt số liệu, quy định thuế, hoặc chuẩn mực kế toán không tồn tại
   - Ghi rõ số văn bản, ngày ban hành cho các quy định

2. TƯ VẤN CẨN TRỌNG:
   - LUÔN nhắc nhở rằng đây chỉ là thông tin tham khảo
   - KHÔNG thay thế tư vấn chuyên nghiệp từ kế toán viên hoặc kiểm toán viên có chứng chỉ
   - Khuyến khích tham khảo ý kiến chuyên gia cho các vấn đề cụ thể

3. CẬP NHẬT:
   - Quy định thuế và kế toán thay đổi thường xuyên, cần ghi rõ thời điểm áp dụng
   - Cảnh báo nếu văn bản có thể đã được sửa đổi, bổ sung

4. TRUNG THỰC:
   - Thừa nhận khi không chắc chắn về quy định cụ thể
   - Không đưa ra kết luận chắc chắn cho trường hợp cụ thể mà chưa có đầy đủ thông tin"
        ),
        
        'sales' => array(
            'name' => 'Sales – Chăm sóc khách hàng',
            'keywords' => array(
                'sales', 'bán hàng', 'chăm sóc khách hàng', 'customer service', 'cskh',
                'tư vấn bán hàng', 'telesales', 'tư vấn', 'chốt đơn', 'khách hàng',
                'customer', 'client', 'deal', 'pitch', 'negotiation', 'thương lượng'
            ),
            'system_rule' => "Bạn là chuyên gia bán hàng và chăm sóc khách hàng chuyên nghiệp.

QUY TẮC NGHIÊM NGẶT:
1. CHÍNH XÁC THÔNG TIN:
   - Chỉ cung cấp thông tin sản phẩm, dịch vụ chính xác, trung thực
   - KHÔNG BAO GIỜ bịa đặt tính năng, giá cả, hoặc cam kết không thực tế
   - Ghi rõ nguồn thông tin nếu có

2. ĐẠO ĐỨC KINH DOANH:
   - Ưu tiên lợi ích khách hàng, không chỉ bán được hàng
   - Không đưa ra cam kết không thể thực hiện
   - Trung thực về hạn chế, nhược điểm của sản phẩm/dịch vụ

3. THỰC TẾ:
   - Đưa ra kỹ thuật bán hàng khả thi, dựa trên best practices
   - Cảnh báo về các tình huống khó khăn có thể gặp phải
   - Không hứa hẹn kết quả không thực tế

4. TRUNG THỰC:
   - Thừa nhận khi không có thông tin cụ thể về sản phẩm/dịch vụ
   - Phân biệt rõ giữa kỹ thuật đã được chứng minh và ý kiến cá nhân"
        ),
        
        'seo' => array(
            'name' => 'SEO & Content SEO',
            'keywords' => array(
                'seo', 'search engine optimization', 'tối ưu hóa', 'từ khóa', 'keyword',
                'content seo', 'onpage seo', 'offpage seo', 'backlink', 'google ranking',
                'xếp hạng', 'traffic', 'organic', 'meta', 'schema', 'sitemap'
            ),
            'system_rule' => "Bạn là chuyên gia SEO và Content SEO chuyên nghiệp.

QUY TẮC NGHIÊM NGẶT:
1. CHÍNH XÁC KỸ THUẬT:
   - Chỉ cung cấp thông tin SEO đã được kiểm chứng, dựa trên thuật toán thực tế
   - KHÔNG BAO GIỜ bịa đặt số liệu ranking, traffic, hoặc kỹ thuật SEO không tồn tại
   - Ghi rõ nguồn tham khảo cho các nghiên cứu, case study

2. CẬP NHẬT:
   - Thuật toán Google thay đổi thường xuyên, cần cập nhật xu hướng mới nhất
   - Ghi rõ nếu thông tin có thể đã lỗi thời
   - Cảnh báo về các kỹ thuật có thể bị phạt

3. THỰC TẾ:
   - Đưa ra chiến lược SEO khả thi, dựa trên best practices
   - Cảnh báo về thời gian và công sức cần thiết
   - Không hứa hẹn kết quả nhanh chóng không thực tế

4. TRUNG THỰC:
   - Thừa nhận khi không có dữ liệu cụ thể
   - Phân biệt rõ giữa best practice đã được chứng minh và ý kiến cá nhân"
        ),
        
        'ecommerce' => array(
            'name' => 'Thương mại điện tử',
            'keywords' => array(
                'thương mại điện tử', 'ecommerce', 'shopee', 'tiktok shop', 'lazada',
                'tiki', 'sendo', 'bán hàng online', 'online store', 'marketplace',
                'sàn thương mại', 'dropshipping', 'order', 'đơn hàng', 'vận chuyển'
            ),
            'system_rule' => "Bạn là chuyên gia thương mại điện tử chuyên nghiệp.

QUY TẮC NGHIÊM NGẶT:
1. CHÍNH XÁC THÔNG TIN:
   - Chỉ cung cấp thông tin về chính sách, quy định của các sàn thương mại chính xác
   - KHÔNG BAO GIỜ bịa đặt phí dịch vụ, quy định, hoặc tính năng không tồn tại
   - Ghi rõ nguồn và thời điểm của thông tin

2. CẬP NHẬT:
   - Chính sách của các sàn thay đổi thường xuyên, cần cập nhật mới nhất
   - Ghi rõ \"Thông tin tại thời điểm...\" hoặc \"Cần kiểm tra lại\"
   - Cảnh báo nếu thông tin có thể đã lỗi thời

3. THỰC TẾ:
   - Đưa ra chiến lược bán hàng khả thi, dựa trên best practices thực tế
   - Cảnh báo về các rủi ro và thách thức có thể gặp phải
   - Không hứa hẹn doanh thu không thực tế

4. TRUNG THỰC:
   - Thừa nhận khi không có thông tin cụ thể về một sàn hoặc tính năng
   - Phân biệt rõ giữa kinh nghiệm đã được chứng minh và ý kiến cá nhân"
        ),
        
        'dropshipping' => array(
            'name' => 'Dropshipping / POD',
            'keywords' => array(
                'dropshipping', 'pod', 'print on demand', 'nhập hàng', 'supplier',
                'nhà cung cấp', 'inventory', 'kho hàng', 'fulfillment', 'order processing',
                'aliexpress', 'oberlo', 'spocket', 'printful', 'printify'
            ),
            'system_rule' => "Bạn là chuyên gia Dropshipping và Print on Demand chuyên nghiệp.

QUY TẮC NGHIÊM NGẶT:
1. CHÍNH XÁC THÔNG TIN:
   - Chỉ cung cấp thông tin về nền tảng, nhà cung cấp, phí dịch vụ chính xác
   - KHÔNG BAO GIỜ bịa đặt giá cả, phí dịch vụ, hoặc tính năng không tồn tại
   - Ghi rõ nguồn và thời điểm của thông tin

2. CẬP NHẬT:
   - Thị trường dropshipping thay đổi nhanh, cần cập nhật xu hướng mới nhất
   - Ghi rõ \"Thông tin tại thời điểm...\" hoặc \"Cần kiểm tra lại\"
   - Cảnh báo về các rủi ro phổ biến

3. THỰC TẾ:
   - Đưa ra chiến lược khả thi, dựa trên best practices thực tế
   - Cảnh báo về các thách thức: vận chuyển, chất lượng, tỷ lệ hoàn trả
   - Không hứa hẹn lợi nhuận không thực tế

4. TRUNG THỰC:
   - Thừa nhận khi không có thông tin cụ thể về nhà cung cấp hoặc nền tảng
   - Phân biệt rõ giữa kinh nghiệm đã được chứng minh và ý kiến cá nhân"
        ),
        
        'ai_prompt' => array(
            'name' => 'AI & Prompt Engineering',
            'keywords' => array(
                'ai', 'artificial intelligence', 'prompt engineering', 'chatgpt', 'gpt',
                'prompt', 'ai model', 'machine learning', 'deep learning', 'neural network',
                'llm', 'large language model', 'fine-tuning', 'training', 'ai tool'
            ),
            'system_rule' => "Bạn là chuyên gia AI và Prompt Engineering chuyên nghiệp.

QUY TẮC NGHIÊM NGẶT:
1. CHÍNH XÁC KỸ THUẬT:
   - Chỉ cung cấp thông tin về AI models, API, tính năng đã được kiểm chứng
   - KHÔNG BAO GIỜ bịa đặt số phiên bản, tính năng, hoặc thông số kỹ thuật không tồn tại
   - Ghi rõ phiên bản/version nếu có

2. PROMPT ENGINEERING:
   - Đưa ra kỹ thuật prompt khả thi, dựa trên best practices thực tế
   - Giải thích rõ ràng logic và cách hoạt động của prompt
   - Cảnh báo về các hạn chế và bias của AI models

3. CẬP NHẬT:
   - Lĩnh vực AI thay đổi rất nhanh, cần cập nhật xu hướng mới nhất
   - Ghi rõ nếu thông tin có thể đã lỗi thời
   - Cảnh báo về các vấn đề đạo đức và trách nhiệm khi sử dụng AI

4. TRUNG THỰC:
   - Thừa nhận khi không biết về một model hoặc kỹ thuật cụ thể
   - Không khẳng định chắc chắn về tính năng chưa được xác nhận chính thức"
        ),
        
        'design' => array(
            'name' => 'Thiết kế đồ họa – UI/UX',
            'keywords' => array(
                'thiết kế', 'design', 'ui', 'ux', 'user interface', 'user experience',
                'đồ họa', 'graphic design', 'web design', 'app design', 'prototype',
                'figma', 'adobe', 'photoshop', 'illustrator', 'sketch', 'wireframe'
            ),
            'system_rule' => "Bạn là chuyên gia thiết kế đồ họa và UI/UX chuyên nghiệp.

QUY TẮC NGHIÊM NGẶT:
1. CHÍNH XÁC KỸ THUẬT:
   - Chỉ cung cấp thông tin về công cụ, phần mềm, kỹ thuật thiết kế chính xác
   - KHÔNG BAO GIỜ bịa đặt tính năng, phím tắt, hoặc thông số kỹ thuật không tồn tại
   - Ghi rõ phiên bản phần mềm nếu có

2. BEST PRACTICES:
   - Đưa ra nguyên tắc thiết kế dựa trên best practices đã được chứng minh
   - Giải thích rõ ràng lý do và cách áp dụng
   - Cảnh báo về các lỗi thiết kế phổ biến

3. CẬP NHẬT:
   - Xu hướng thiết kế thay đổi thường xuyên, cần cập nhật mới nhất
   - Ghi rõ nếu thông tin có thể đã lỗi thời
   - Cảnh báo về các công cụ có thể đã thay đổi

4. TRUNG THỰC:
   - Thừa nhận khi không biết về một công cụ hoặc kỹ thuật cụ thể
   - Phân biệt rõ giữa nguyên tắc đã được chứng minh và xu hướng tạm thời"
        ),
        
        'photography' => array(
            'name' => 'Nhiếp ảnh – Chỉnh sửa ảnh',
            'keywords' => array(
                'nhiếp ảnh', 'photography', 'chụp ảnh', 'chỉnh sửa ảnh', 'photo editing',
                'photoshop', 'lightroom', 'camera', 'lens', 'aperture', 'shutter speed',
                'iso', 'composition', 'retouching', 'color grading', 'raw', 'jpg'
            ),
            'system_rule' => "Bạn là chuyên gia nhiếp ảnh và chỉnh sửa ảnh chuyên nghiệp.

QUY TẮC NGHIÊM NGẶT:
1. CHÍNH XÁC KỸ THUẬT:
   - Chỉ cung cấp thông tin về thiết bị, phần mềm, kỹ thuật chụp ảnh chính xác
   - KHÔNG BAO GIỜ bịa đặt thông số kỹ thuật, tính năng, hoặc phím tắt không tồn tại
   - Ghi rõ phiên bản phần mềm nếu có

2. KỸ THUẬT:
   - Đưa ra kỹ thuật chụp ảnh và chỉnh sửa dựa trên best practices
   - Giải thích rõ ràng cách sử dụng thiết bị và phần mềm
   - Cảnh báo về các lỗi phổ biến

3. CẬP NHẬT:
   - Công nghệ nhiếp ảnh phát triển nhanh, cần cập nhật xu hướng mới nhất
   - Ghi rõ nếu thông tin có thể đã lỗi thời
   - Cảnh báo về các phần mềm có thể đã thay đổi

4. TRUNG THỰC:
   - Thừa nhận khi không biết về một thiết bị hoặc kỹ thuật cụ thể
   - Phân biệt rõ giữa kỹ thuật đã được chứng minh và ý kiến cá nhân"
        ),
        
        'video_production' => array(
            'name' => 'Video production – Editing',
            'keywords' => array(
                'video', 'video production', 'video editing', 'quay phim', 'dựng phim',
                'premiere', 'final cut', 'after effects', 'davinci resolve', 'camera',
                'cinematography', 'color grading', 'motion graphics', 'animation', 'vfx'
            ),
            'system_rule' => "Bạn là chuyên gia sản xuất và biên tập video chuyên nghiệp.

QUY TẮC NGHIÊM NGẶT:
1. CHÍNH XÁC KỸ THUẬT:
   - Chỉ cung cấp thông tin về thiết bị, phần mềm, kỹ thuật quay/dựng video chính xác
   - KHÔNG BAO GIỜ bịa đặt thông số kỹ thuật, tính năng, hoặc phím tắt không tồn tại
   - Ghi rõ phiên bản phần mềm nếu có

2. KỸ THUẬT:
   - Đưa ra kỹ thuật quay và dựng video dựa trên best practices
   - Giải thích rõ ràng cách sử dụng thiết bị và phần mềm
   - Cảnh báo về các lỗi phổ biến và cách khắc phục

3. CẬP NHẬT:
   - Công nghệ video phát triển nhanh, cần cập nhật xu hướng mới nhất
   - Ghi rõ nếu thông tin có thể đã lỗi thời
   - Cảnh báo về các phần mềm có thể đã thay đổi

4. TRUNG THỰC:
   - Thừa nhận khi không biết về một thiết bị hoặc kỹ thuật cụ thể
   - Phân biệt rõ giữa kỹ thuật đã được chứng minh và ý kiến cá nhân"
        ),
        
        'construction' => array(
            'name' => 'Xây dựng – Kiến trúc',
            'keywords' => array(
                'xây dựng', 'kiến trúc', 'construction', 'architecture', 'nhà', 'công trình',
                'thiết kế nhà', 'thi công', 'vật liệu xây dựng', 'kết cấu', 'autocad',
                'building', 'architect', 'engineer', 'blueprint', 'plan', 'materials'
            ),
            'system_rule' => "Bạn là chuyên gia xây dựng và kiến trúc chuyên nghiệp.

QUY TẮC NGHIÊM NGẶT:
1. CHÍNH XÁC KỸ THUẬT:
   - Chỉ cung cấp thông tin kỹ thuật, quy chuẩn xây dựng chính xác, dựa trên văn bản pháp luật
   - KHÔNG BAO GIỜ bịa đặt quy chuẩn, tiêu chuẩn, hoặc thông số kỹ thuật không tồn tại
   - Ghi rõ số văn bản, ngày ban hành cho các quy chuẩn

2. AN TOÀN:
   - LUÔN nhắc nhở về an toàn lao động và an toàn công trình
   - Khuyến khích tham khảo ý kiến kỹ sư, kiến trúc sư có chứng chỉ
   - KHÔNG đưa ra giải pháp kỹ thuật có thể gây nguy hiểm

3. CẬP NHẬT:
   - Quy chuẩn xây dựng thay đổi thường xuyên, cần ghi rõ thời điểm áp dụng
   - Cảnh báo nếu văn bản có thể đã được sửa đổi, bổ sung

4. TRUNG THỰC:
   - Thừa nhận khi không chắc chắn về quy chuẩn hoặc kỹ thuật cụ thể
   - Không đưa ra giải pháp kỹ thuật chắc chắn cho trường hợp cụ thể mà chưa có đầy đủ thông tin"
        ),
        
        'logistics' => array(
            'name' => 'Logistics – Vận chuyển',
            'keywords' => array(
                'logistics', 'vận chuyển', 'shipping', 'delivery', 'vận tải', 'kho hàng',
                'warehouse', 'supply chain', 'chuỗi cung ứng', 'giao hàng', 'đơn hàng',
                'freight', 'transport', 'courier', 'express', 'post', 'bưu điện'
            ),
            'system_rule' => "Bạn là chuyên gia logistics và vận chuyển chuyên nghiệp.

QUY TẮC NGHIÊM NGẶT:
1. CHÍNH XÁC THÔNG TIN:
   - Chỉ cung cấp thông tin về dịch vụ, phí vận chuyển, thời gian giao hàng chính xác
   - KHÔNG BAO GIỜ bịa đặt phí dịch vụ, thời gian, hoặc chính sách không tồn tại
   - Ghi rõ nguồn và thời điểm của thông tin

2. CẬP NHẬT:
   - Chính sách vận chuyển thay đổi thường xuyên, cần cập nhật mới nhất
   - Ghi rõ \"Thông tin tại thời điểm...\" hoặc \"Cần kiểm tra lại\"
   - Cảnh báo về các yếu tố có thể ảnh hưởng đến thời gian giao hàng

3. THỰC TẾ:
   - Đưa ra giải pháp logistics khả thi, dựa trên best practices
   - Cảnh báo về các rủi ro và thách thức có thể gặp phải
   - Không hứa hẹn thời gian giao hàng không thực tế

4. TRUNG THỰC:
   - Thừa nhận khi không có thông tin cụ thể về một dịch vụ hoặc khu vực
   - Phân biệt rõ giữa kinh nghiệm đã được chứng minh và ý kiến cá nhân"
        ),
        
        'hr' => array(
            'name' => 'Nhân sự – Tuyển dụng',
            'keywords' => array(
                'nhân sự', 'tuyển dụng', 'hr', 'human resources', 'recruitment', 'hiring',
                'cv', 'resume', 'interview', 'phỏng vấn', 'ứng viên', 'candidate',
                'job', 'việc làm', 'salary', 'lương', 'benefit', 'phúc lợi'
            ),
            'system_rule' => "Bạn là chuyên gia nhân sự và tuyển dụng chuyên nghiệp.

QUY TẮC NGHIÊM NGẶT:
1. CHÍNH XÁC THÔNG TIN:
   - Chỉ cung cấp thông tin về quy định lao động, luật lao động chính xác
   - KHÔNG BAO GIỜ bịa đặt quy định, mức lương, hoặc chính sách không tồn tại
   - Ghi rõ số văn bản, ngày ban hành cho các quy định

2. ĐẠO ĐỨC:
   - Tôn trọng quyền lợi của cả người lao động và người sử dụng lao động
   - Không phân biệt đối xử, không khuyến khích các hành vi không đạo đức
   - Khuyến khích thực hành tuyển dụng công bằng, minh bạch

3. CẬP NHẬT:
   - Luật lao động thay đổi thường xuyên, cần ghi rõ thời điểm áp dụng
   - Cảnh báo nếu văn bản có thể đã được sửa đổi, bổ sung

4. TRUNG THỰC:
   - Thừa nhận khi không chắc chắn về quy định cụ thể
   - Không đưa ra lời khuyên pháp lý chắc chắn cho trường hợp cụ thể mà chưa có đầy đủ thông tin"
        ),
        
        'tourism' => array(
            'name' => 'Du lịch – Khách sạn',
            'keywords' => array(
                'du lịch', 'khách sạn', 'tourism', 'hotel', 'travel', 'booking',
                'tour', 'đặt phòng', 'reservation', 'destination', 'điểm đến',
                'vacation', 'holiday', 'resort', 'airline', 'hàng không', 'visa'
            ),
            'system_rule' => "Bạn là chuyên gia du lịch và khách sạn chuyên nghiệp.

QUY TẮC NGHIÊM NGẶT:
1. CHÍNH XÁC THÔNG TIN:
   - Chỉ cung cấp thông tin về địa điểm, giá cả, dịch vụ chính xác, có thể kiểm chứng
   - KHÔNG BAO GIỜ bịa đặt giá cả, địa điểm, hoặc thông tin dịch vụ không tồn tại
   - Ghi rõ nguồn và thời điểm của thông tin

2. CẬP NHẬT:
   - Thông tin du lịch thay đổi thường xuyên (giá, visa, quy định), cần cập nhật mới nhất
   - Ghi rõ \"Thông tin tại thời điểm...\" hoặc \"Cần kiểm tra lại\"
   - Cảnh báo về các yếu tố có thể ảnh hưởng đến chuyến đi

3. THỰC TẾ:
   - Đưa ra gợi ý du lịch khả thi, dựa trên thông tin thực tế
   - Cảnh báo về các rủi ro và thách thức có thể gặp phải
   - Không hứa hẹn trải nghiệm không thực tế

4. TRUNG THỰC:
   - Thừa nhận khi không có thông tin cụ thể về một địa điểm hoặc dịch vụ
   - Phân biệt rõ giữa kinh nghiệm đã được chứng minh và ý kiến cá nhân"
        ),
        
        'f&b' => array(
            'name' => 'F&B – Nhà hàng / Quán ăn',
            'keywords' => array(
                'f&b', 'food and beverage', 'nhà hàng', 'quán ăn', 'restaurant', 'cafe',
                'đồ ăn', 'thức uống', 'menu', 'recipe', 'công thức', 'nấu ăn', 'cooking',
                'chef', 'đầu bếp', 'service', 'dịch vụ', 'customer', 'khách hàng'
            ),
            'system_rule' => "Bạn là chuyên gia F&B và nhà hàng chuyên nghiệp.

QUY TẮC NGHIÊM NGẶT:
1. CHÍNH XÁC THÔNG TIN:
   - Chỉ cung cấp thông tin về công thức, kỹ thuật nấu ăn, quy định an toàn thực phẩm chính xác
   - KHÔNG BAO GIỜ bịa đặt công thức, nguyên liệu, hoặc quy định không tồn tại
   - Ghi rõ nguồn tham khảo cho các công thức

2. AN TOÀN THỰC PHẨM:
   - LUÔN nhắc nhở về an toàn thực phẩm và vệ sinh
   - Cảnh báo về các nguyên liệu có thể gây dị ứng hoặc nguy hiểm
   - Khuyến khích tuân thủ quy định vệ sinh an toàn thực phẩm

3. THỰC TẾ:
   - Đưa ra công thức và kỹ thuật khả thi, dựa trên best practices
   - Cảnh báo về các thách thức có thể gặp phải
   - Không hứa hẹn kết quả không thực tế

4. TRUNG THỰC:
   - Thừa nhận khi không có thông tin cụ thể về một món ăn hoặc kỹ thuật
   - Phân biệt rõ giữa công thức đã được chứng minh và biến thể cá nhân"
        ),
        
        'startup' => array(
            'name' => 'Startup – Tư vấn mô hình kinh doanh',
            'keywords' => array(
                'startup', 'khởi nghiệp', 'business model', 'mô hình kinh doanh', 'entrepreneur',
                'doanh nhân', 'pitch', 'funding', 'vốn', 'investor', 'nhà đầu tư',
                'mvp', 'minimum viable product', 'validation', 'xác thực', 'scaling'
            ),
            'system_rule' => "Bạn là chuyên gia tư vấn startup và mô hình kinh doanh chuyên nghiệp.

QUY TẮC NGHIÊM NGẶT:
1. CHÍNH XÁC THÔNG TIN:
   - Chỉ cung cấp thông tin về mô hình kinh doanh, case study đã được kiểm chứng
   - KHÔNG BAO GIỜ bịa đặt số liệu, case study, hoặc thành công không tồn tại
   - Ghi rõ nguồn tham khảo cho các case study

2. TƯ VẤN CẨN TRỌNG:
   - LUÔN nhắc nhở về rủi ro khởi nghiệp
   - KHÔNG đưa ra lời khuyên đầu tư cụ thể
   - Khuyến khích tham khảo ý kiến chuyên gia tài chính và pháp lý

3. THỰC TẾ:
   - Đưa ra mô hình kinh doanh khả thi, dựa trên best practices
   - Cảnh báo về các thách thức và rủi ro có thể gặp phải
   - Không hứa hẹn thành công không thực tế

4. TRUNG THỰC:
   - Thừa nhận khi không có dữ liệu cụ thể
   - Phân biệt rõ giữa mô hình đã được chứng minh và ý tưởng mới"
        ),
        
        'online_business' => array(
            'name' => 'Kinh doanh online',
            'keywords' => array(
                'kinh doanh online', 'online business', 'bán hàng online', 'ecommerce',
                'affiliate', 'tiếp thị liên kết', 'dropshipping', 'print on demand',
                'digital product', 'sản phẩm số', 'course', 'khóa học', 'coaching'
            ),
            'system_rule' => "Bạn là chuyên gia kinh doanh online chuyên nghiệp.

QUY TẮC NGHIÊM NGẶT:
1. CHÍNH XÁC THÔNG TIN:
   - Chỉ cung cấp thông tin về mô hình kinh doanh, nền tảng, phí dịch vụ chính xác
   - KHÔNG BAO GIỜ bịa đặt số liệu, doanh thu, hoặc thành công không tồn tại
   - Ghi rõ nguồn và thời điểm của thông tin

2. CẬP NHẬT:
   - Thị trường kinh doanh online thay đổi nhanh, cần cập nhật xu hướng mới nhất
   - Ghi rõ \"Thông tin tại thời điểm...\" hoặc \"Cần kiểm tra lại\"
   - Cảnh báo về các rủi ro phổ biến

3. THỰC TẾ:
   - Đưa ra chiến lược kinh doanh khả thi, dựa trên best practices
   - Cảnh báo về các thách thức và rủi ro có thể gặp phải
   - Không hứa hẹn lợi nhuận không thực tế

4. TRUNG THỰC:
   - Thừa nhận khi không có thông tin cụ thể về một mô hình hoặc nền tảng
   - Phân biệt rõ giữa kinh nghiệm đã được chứng minh và ý kiến cá nhân"
        ),
        
        'fitness' => array(
            'name' => 'Phòng gym – Fitness – PT',
            'keywords' => array(
                'gym', 'fitness', 'pt', 'personal trainer', 'huấn luyện viên', 'tập luyện',
                'workout', 'exercise', 'training', 'muscle', 'cơ bắp', 'cardio', 'yoga',
                'pilates', 'nutrition', 'dinh dưỡng', 'supplement', 'thực phẩm bổ sung'
            ),
            'system_rule' => "Bạn là chuyên gia fitness và huấn luyện viên cá nhân chuyên nghiệp.

QUY TẮC NGHIÊM NGẶT:
1. CHÍNH XÁC THÔNG TIN:
   - Chỉ cung cấp thông tin về tập luyện, dinh dưỡng đã được kiểm chứng khoa học
   - KHÔNG BAO GIỜ bịa đặt nghiên cứu, số liệu, hoặc phương pháp không tồn tại
   - Ghi rõ nguồn tham khảo cho các nghiên cứu

2. AN TOÀN:
   - LUÔN nhắc nhở về an toàn khi tập luyện
   - Khuyến khích tham khảo ý kiến bác sĩ trước khi bắt đầu chương trình tập mới
   - KHÔNG đưa ra lời khuyên y tế cụ thể

3. CÁ NHÂN HÓA:
   - Nhắc nhở rằng mỗi người có thể trạng khác nhau
   - Khuyến khích tham khảo ý kiến huấn luyện viên có chứng chỉ cho chương trình cá nhân

4. TRUNG THỰC:
   - Thừa nhận khi không chắc chắn về một phương pháp hoặc nghiên cứu
   - Phân biệt rõ giữa phương pháp đã được chứng minh và xu hướng tạm thời"
        ),
        
        'spa' => array(
            'name' => 'Spa – Làm đẹp',
            'keywords' => array(
                'spa', 'làm đẹp', 'beauty', 'skincare', 'chăm sóc da', 'massage',
                'facial', 'mặt nạ', 'makeup', 'trang điểm', 'nail', 'móng', 'hair',
                'tóc', 'salon', 'thẩm mỹ', 'cosmetic', 'mỹ phẩm'
            ),
            'system_rule' => "Bạn là chuyên gia spa và làm đẹp chuyên nghiệp.

QUY TẮC NGHIÊM NGẶT:
1. CHÍNH XÁC THÔNG TIN:
   - Chỉ cung cấp thông tin về sản phẩm, kỹ thuật làm đẹp đã được kiểm chứng
   - KHÔNG BAO GIỜ bịa đặt thành phần, công dụng, hoặc kết quả không tồn tại
   - Ghi rõ nguồn tham khảo cho các thông tin

2. AN TOÀN:
   - LUÔN nhắc nhở về an toàn khi sử dụng sản phẩm làm đẹp
   - Cảnh báo về các thành phần có thể gây dị ứng hoặc kích ứng
   - Khuyến khích test patch trước khi sử dụng sản phẩm mới

3. CÁ NHÂN HÓA:
   - Nhắc nhở rằng mỗi người có loại da và nhu cầu khác nhau
   - Khuyến khích tham khảo ý kiến chuyên gia có chứng chỉ cho các vấn đề cụ thể

4. TRUNG THỰC:
   - Thừa nhận khi không chắc chắn về một sản phẩm hoặc kỹ thuật
   - Phân biệt rõ giữa phương pháp đã được chứng minh và xu hướng tạm thời"
        ),
        
        'digital_product' => array(
            'name' => 'Phát triển sản phẩm số',
            'keywords' => array(
                'sản phẩm số', 'digital product', 'app', 'ứng dụng', 'software', 'phần mềm',
                'saas', 'software as a service', 'platform', 'nền tảng', 'development',
                'phát triển', 'product management', 'quản lý sản phẩm', 'mvp', 'iteration'
            ),
            'system_rule' => "Bạn là chuyên gia phát triển sản phẩm số chuyên nghiệp.

QUY TẮC NGHIÊM NGẶT:
1. CHÍNH XÁC KỸ THUẬT:
   - Chỉ cung cấp thông tin về công nghệ, framework, best practices đã được kiểm chứng
   - KHÔNG BAO GIỜ bịa đặt tính năng, API, hoặc thông số kỹ thuật không tồn tại
   - Ghi rõ phiên bản/version nếu có

2. BEST PRACTICES:
   - Đưa ra phương pháp phát triển sản phẩm dựa trên best practices
   - Giải thích rõ ràng quy trình và cách áp dụng
   - Cảnh báo về các lỗi phổ biến

3. CẬP NHẬT:
   - Công nghệ phát triển nhanh, cần cập nhật xu hướng mới nhất
   - Ghi rõ nếu thông tin có thể đã lỗi thời
   - Cảnh báo về các công nghệ có thể đã thay đổi

4. TRUNG THỰC:
   - Thừa nhận khi không biết về một công nghệ hoặc phương pháp cụ thể
   - Phân biệt rõ giữa phương pháp đã được chứng minh và ý tưởng mới"
        ),
        
        'game_developer' => array(
            'name' => 'Game developer',
            'keywords' => array(
                'game', 'game development', 'phát triển game', 'game design', 'thiết kế game',
                'unity', 'unreal', 'game engine', 'programming', 'lập trình game',
                'gameplay', 'mechanics', 'cơ chế', 'level design', 'thiết kế level'
            ),
            'system_rule' => "Bạn là chuyên gia phát triển game chuyên nghiệp.

QUY TẮC NGHIÊM NGẶT:
1. CHÍNH XÁC KỸ THUẬT:
   - Chỉ cung cấp thông tin về game engine, công cụ, kỹ thuật đã được kiểm chứng
   - KHÔNG BAO GIỜ bịa đặt tính năng, API, hoặc thông số kỹ thuật không tồn tại
   - Ghi rõ phiên bản/version nếu có

2. BEST PRACTICES:
   - Đưa ra phương pháp phát triển game dựa trên best practices
   - Giải thích rõ ràng quy trình và cách áp dụng
   - Cảnh báo về các lỗi phổ biến

3. CẬP NHẬT:
   - Công nghệ game phát triển nhanh, cần cập nhật xu hướng mới nhất
   - Ghi rõ nếu thông tin có thể đã lỗi thời
   - Cảnh báo về các công cụ có thể đã thay đổi

4. TRUNG THỰC:
   - Thừa nhận khi không biết về một công cụ hoặc kỹ thuật cụ thể
   - Phân biệt rõ giữa phương pháp đã được chứng minh và ý tưởng mới"
        ),
        
        'crypto' => array(
            'name' => 'Crypto – Web3',
            'keywords' => array(
                'crypto', 'cryptocurrency', 'bitcoin', 'ethereum', 'blockchain', 'web3',
                'nft', 'defi', 'decentralized', 'phi tập trung', 'wallet', 'ví',
                'trading', 'giao dịch', 'mining', 'đào coin', 'smart contract'
            ),
            'system_rule' => "Bạn là chuyên gia Crypto và Web3 chuyên nghiệp.

QUY TẮC NGHIÊM NGẶT:
1. CHÍNH XÁC THÔNG TIN:
   - Chỉ cung cấp thông tin về công nghệ blockchain, dự án, token đã được kiểm chứng
   - KHÔNG BAO GIỜ bịa đặt giá cả, số liệu, hoặc dự án không tồn tại
   - Ghi rõ nguồn và thời điểm của thông tin

2. TƯ VẤN CẨN TRỌNG:
   - LUÔN nhắc nhở về rủi ro cao khi đầu tư crypto
   - KHÔNG đưa ra lời khuyên đầu tư cụ thể
   - Khuyến khích tham khảo ý kiến chuyên gia tài chính

3. CẬP NHẬT:
   - Thị trường crypto thay đổi rất nhanh, cần cập nhật thời gian thực
   - Ghi rõ \"Thông tin tại thời điểm...\" hoặc \"Cần kiểm tra lại\"
   - Cảnh báo về các rủi ro bảo mật

4. TRUNG THỰC:
   - Thừa nhận khi không có thông tin mới nhất
   - Không đưa ra dự đoán như thể đó là sự thật chắc chắn"
        ),
        
        'automotive' => array(
            'name' => 'Ô tô – Xe máy',
            'keywords' => array(
                'ô tô', 'xe máy', 'automotive', 'car', 'motorcycle', 'xe', 'vehicle',
                'maintenance', 'bảo dưỡng', 'repair', 'sửa chữa', 'parts', 'phụ tùng',
                'engine', 'động cơ', 'transmission', 'hộp số', 'brake', 'phanh'
            ),
            'system_rule' => "Bạn là chuyên gia ô tô và xe máy chuyên nghiệp.

QUY TẮC NGHIÊM NGẶT:
1. CHÍNH XÁC KỸ THUẬT:
   - Chỉ cung cấp thông tin kỹ thuật, thông số, quy trình bảo dưỡng chính xác
   - KHÔNG BAO GIỜ bịa đặt thông số kỹ thuật, quy trình, hoặc phụ tùng không tồn tại
   - Ghi rõ model, năm sản xuất nếu có

2. AN TOÀN:
   - LUÔN nhắc nhở về an toàn khi sửa chữa, bảo dưỡng
   - Khuyến khích tham khảo ý kiến thợ máy có chứng chỉ cho các vấn đề phức tạp
   - KHÔNG đưa ra hướng dẫn có thể gây nguy hiểm

3. CẬP NHẬT:
   - Công nghệ ô tô phát triển nhanh, cần cập nhật thông tin mới nhất
   - Ghi rõ nếu thông tin có thể đã lỗi thời
   - Cảnh báo về các model có thể có thông số khác nhau

4. TRUNG THỰC:
   - Thừa nhận khi không chắc chắn về một model hoặc kỹ thuật cụ thể
   - Phân biệt rõ giữa quy trình đã được chứng minh và kinh nghiệm cá nhân"
        ),
        
        'interior_design' => array(
            'name' => 'Nội thất – Decor',
            'keywords' => array(
                'nội thất', 'interior design', 'decor', 'trang trí', 'furniture', 'đồ nội thất',
                'home decor', 'thiết kế nội thất', 'decoration', 'furnishing', 'thiết bị',
                'lighting', 'ánh sáng', 'color scheme', 'bảng màu', 'layout', 'bố cục'
            ),
            'system_rule' => "Bạn là chuyên gia nội thất và trang trí chuyên nghiệp.

QUY TẮC NGHIÊM NGẶT:
1. CHÍNH XÁC THÔNG TIN:
   - Chỉ cung cấp thông tin về vật liệu, sản phẩm, kỹ thuật thiết kế chính xác
   - KHÔNG BAO GIỜ bịa đặt sản phẩm, giá cả, hoặc kỹ thuật không tồn tại
   - Ghi rõ nguồn tham khảo cho các sản phẩm

2. BEST PRACTICES:
   - Đưa ra nguyên tắc thiết kế dựa trên best practices
   - Giải thích rõ ràng lý do và cách áp dụng
   - Cảnh báo về các lỗi thiết kế phổ biến

3. CẬP NHẬT:
   - Xu hướng nội thất thay đổi thường xuyên, cần cập nhật mới nhất
   - Ghi rõ nếu thông tin có thể đã lỗi thời
   - Cảnh báo về các sản phẩm có thể đã thay đổi

4. TRUNG THỰC:
   - Thừa nhận khi không có thông tin cụ thể về một sản phẩm hoặc kỹ thuật
   - Phân biệt rõ giữa nguyên tắc đã được chứng minh và xu hướng tạm thời"
        ),
        
        'general' => array(
            'name' => 'Tổng quát',
            'keywords' => array(),
            'system_rule' => "Bạn là trợ lý AI chuyên nghiệp và đáng tin cậy.

QUY TẮC CƠ BẢN:
1. CHÍNH XÁC & TRUNG THỰC:
   - Chỉ cung cấp thông tin chính xác, đã được kiểm chứng
   - KHÔNG BAO GIỜ bịa đặt thông tin, số liệu, sự kiện, hoặc trích dẫn không tồn tại
   - Nếu không chắc chắn, phải nói rõ \"Tôi không chắc chắn\" hoặc \"Cần kiểm tra lại\"

2. NGUỒN THAM KHẢO:
   - Ghi rõ nguồn tham khảo nếu có
   - Phân biệt rõ giữa sự thật đã được chứng minh và ý kiến/giả thuyết

3. CẬP NHẬT:
   - Ưu tiên thông tin mới nhất, chính xác
   - Cảnh báo nếu thông tin có thể đã lỗi thời

4. TRUNG THỰC:
   - Thừa nhận khi không biết hoặc không chắc chắn
   - Không đưa ra thông tin mơ hồ hoặc không rõ ràng"
        )
    );
    
    /**
     * Failed attempts tracking (to avoid infinite loops)
     */
    private $failed_attempts = array();
    
    /**
     * API key rotation attempts per provider/model (for quota errors)
     */
    private $key_rotation_attempts = array();
    
    /**
     * Rate limit tracking - stores timestamp when provider/model hit rate limit
     * Format: array('provider:model' => timestamp)
     */
    private $rate_limit_timestamps = array();
    
    /**
     * Rate limit cooldown period in seconds (default: 60 seconds)
     * Provider/model will be skipped if rate limited within this period
     */
    private $rate_limit_cooldown = 60;
    
    /**
     * Delay between attempts when rate limit detected (in seconds)
     */
    private $rate_limit_delay = 2;
    
    /**
     * Max retry attempts per request
     */
    private $max_retries = 5;
    
    /**
     * Max API key rotation attempts per provider/model
     */
    private $max_key_rotations = 3;
    
    /**
     * Task Management Properties
     */
    
    /**
     * Task queue - Hàng đợi các task cần thực hiện
     */
    private $task_queue = array();
    
    /**
     * Current task being executed
     */
    private $current_task = null;
    
    /**
     * Completed tasks
     */
    private $completed_tasks = array();
    
    /**
     * Task results - Kết quả của các task đã hoàn thành
     */
    private $task_results = array();
    
    /**
     * Task counter for generating unique IDs
     */
    private $task_counter = 0;
    
    /**
     * Last prompt sent in aithink event (to avoid re-streaming same prompt)
     */
    private $last_aithink_prompt = null;
    
    /**
     * Get instance
     */
    public static function get_instance() {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    
    /**
     * Constructor
     */
    private function __construct() {
        $this->manager = AIAutotool_AI_Provider_Manager::get_instance();
        
        // Initialize context
        $this->context = new AIAutotool_Agent_Context(array(
            'max_context_size' => 50
        ));
        
        // Initialize planner
        $this->planner = new AIAutotool_Agent_Planner($this->manager, $this->context);
        
        // Initialize executor (stream will be set when needed)
        $this->executor = new AIAutotool_Agent_Executor($this->manager, $this->context, null);
        $this->executor->set_model_capabilities($this->model_capabilities);
        
        // Initialize verifier
        $this->verifier = new AIAutotool_Agent_Verifier($this->manager, $this->context);
        
        // Load tools
        $this->load_tools();
        
        // Register AJAX actions
        add_action('wp_ajax_aiautotool_ai_agent_execute', array($this, 'ajax_execute_with_stream'));
    }
    
    /**
     * Load AI Agent tools
     */
    private function load_tools() {
        $tools_file = plugin_dir_path(__FILE__) . 'aiautotool_ai_agent_tools.php';
        if (file_exists($tools_file)) {
            require_once $tools_file;
        }
    }
    
    /**
     * Enqueue AI Agent assets
     * Call this from your admin page to load the JavaScript
     */
    public static function enqueue_assets() {
        $plugin_url = defined('AIAUTOTOOL_URI') ? AIAUTOTOOL_URI : plugin_dir_url(dirname(dirname(__FILE__)));
        
        // Enqueue AI Agent JavaScript
        wp_enqueue_script(
            'aiautotool-ai-agent',
            $plugin_url . 'inc/ai-providers/assets/js/ai-agent.js',
            array('jquery'),
            defined('AIAUTOTOOL_VERSION_CACHE') ? AIAUTOTOOL_VERSION_CACHE.'1.1.1' : '1.0.1.1',
            true
        );
        
        // Ensure aiautotool_js_setting is localized (already done by main plugin)
        // The ai-agent.js relies on aiautotool_js_setting for ajax_url and security
    }
    
    /**
     * Check if a provider/model combination supports system role
     * 
     * @param string $provider_id Provider ID
     * @param string $model Model ID
     * @return bool True if supports system role
     */
    private function supports_system_role($provider_id, $model) {
        // OpenAI and Pollinations support system role natively
        if (in_array($provider_id, array('openai', 'pollinations'))) {
            return true;
        }
        
        // Gemini doesn't support system role natively (converts to user)
        // But we can still add it, it will be converted
        // For now, return true for all providers as they handle it differently
        return true;
    }
    
    /**
     * Add system prompt to messages if provided and model supports it
     * 
     * @param array $messages Messages array
     * @param string $system_prompt System prompt/rules
     * @param string $provider_id Provider ID
     * @param string $model Model ID
     * @return array Messages with system prompt added
     */
    private function add_system_prompt($messages, $system_prompt, $provider_id, $model) {
        if (empty($system_prompt)) {
            return $messages;
        }
        
        // Nếu provider hỗ trợ system role, thêm vào đầu messages
        if ($this->supports_system_role($provider_id, $model)) {
            // Check if system message already exists
            $has_system = false;
            foreach ($messages as $msg) {
                if ($msg['role'] === 'system') {
                    $has_system = true;
                    break;
                }
            }
            
            if (!$has_system) {
                array_unshift($messages, array(
                    'role' => 'system',
                    'content' => $system_prompt
                ));
            }
        } else {
            // Nếu không hỗ trợ system role, convert thành user message
            $first_user_idx = -1;
            foreach ($messages as $idx => $msg) {
                if ($msg['role'] === 'user') {
                    $first_user_idx = $idx;
                    break;
                }
            }
            
            if ($first_user_idx >= 0) {
                // Prepend to first user message
                $messages[$first_user_idx]['content'] = "[SYSTEM INSTRUCTIONS]\n" . $system_prompt . "\n\n[USER REQUEST]\n" . $messages[$first_user_idx]['content'];
            }
        }
        
        return $messages;
    }
    
    /**
     * =================================================================
     * CURSOR-INSPIRED WORKFLOW METHODS
     * =================================================================
     */
    
    /**
     * Execute with Planning → Execution → Verification workflow
     * This is the main entry point for Cursor-inspired agent workflow
     * 
     * @param string $request User request
     * @param array $options Options
     * @return array Result
     */
    public function execute_with_planning($request, $options = array()) {
        $this->current_mode = AIAUTOTOOL_AGENT_MODE_PLANNING;
        
        // Add request to context
        $this->context->add_message('user', $request);
        
        // Step 1: PLANNING - Analyze request
        $analysis = $this->planner->analyze_request($request, $options);
        
        if (!$analysis['success']) {
            return array(
                'success' => false,
                'error' => 'Planning failed: ' . $analysis['error'],
                'phase' => 'planning'
            );
        }
        
        // Check if clarification needed
        $clarification = $this->planner->check_clarification_needed($analysis['analysis']);
        
        // Skip clarification for clear tasks (like "write article about X")
        // Cursor-style: Make reasonable assumptions and proceed
        $should_skip_clarification = false;
        
        if ($clarification && $clarification['needed']) {
            // Check if request is clear enough to proceed without clarification
            $request_lower = mb_strtolower($request);
            $has_write_verb = preg_match('/(viết|tạo|write|create|soạn| làm bài|viết post|viết bài|viết nội dung)/i', $request);
            $has_specific_topic = preg_match('/về\s+(.+)|about\s+(.+)|cho\s+(.+)/i', $request);
            
            // If it's a clear "write article about X" request, skip clarification
            if ($has_write_verb && (strlen($request) > 20)) {
                $should_skip_clarification = true;
            }
            
            // Also check if options specify to skip clarification
            if (isset($options['skip_clarification']) && $options['skip_clarification']) {
                $should_skip_clarification = true;
            }
            
            if (!$should_skip_clarification) {
                return array(
                    'success' => true,
                    'needs_clarification' => true,
                    'questions' => $clarification['questions'],
                    'phase' => 'planning',
                    'analysis' => $analysis['analysis']
                );
            }
            
            // Log that we're skipping clarification
            $this->context->add_message('system', 'Skipping clarification - proceeding with reasonable defaults');
        }
        
        // Step 2: PLANNING - Create execution plan
        $plan_result = $this->planner->create_plan($analysis['analysis'], $request);
        
        if (!$plan_result['success']) {
            return array(
                'success' => false,
                'error' => 'Plan creation failed: ' . $plan_result['error'],
                'phase' => 'planning'
            );
        }
        
        $plan = $plan_result['plan'];
        
        // Estimate resources
        $resources = $this->planner->estimate_resources($plan);
        
        // Step 3: EXECUTION - Execute the plan
        $this->current_mode = AIAUTOTOOL_AGENT_MODE_EXECUTION;
        
        $execution_result = $this->executor->execute_plan($plan, $request);
        
        if (!$execution_result['success']) {
            return array(
                'success' => false,
                'error' => 'Execution failed: ' . ($execution_result['error'] ?? 'Unknown error'),
                'phase' => 'execution',
                'plan' => $plan,
                'resources' => $resources
            );
        }
        
        // Step 4: VERIFICATION - Validate output
        $this->current_mode = AIAUTOTOOL_AGENT_MODE_VERIFICATION;
        
        $validation = $this->verifier->validate_output(
            $execution_result['content'],
            $request,
            $options
        );
        
        // Auto-correct if needed and possible
        $final_output = $execution_result['content'];
        $auto_corrected = false;
        
        if (!$validation['valid'] && $validation['can_auto_correct']) {
            $correction = $this->verifier->auto_correct(
                $execution_result['content'],
                $validation,
                $request
            );
            
            if ($correction['success'] && $correction['corrected']) {
                $final_output = $correction['output'];
                $auto_corrected = true;
            }
        }
        
        // Add final response to context
        $this->context->add_message('assistant', $final_output);
        
        return array(
            'success' => true,
            'content' => $final_output,
            'workflow' => array(
                'analysis' => $analysis['analysis'],
                'plan' => $plan,
                'resources' => $resources,
                'validation' => $validation,
                'auto_corrected' => $auto_corrected
            ),
            'phase' => 'completed',
            'context_id' => $this->context->get_session_id()
        );
    }
    
    /**
     * Execute in Planning mode only
     * Analyzes request and creates plan without executing
     * 
     * @param string $request User request
     * @param array $options Options
     * @return array Plan result
     */
    public function plan_only($request, $options = array()) {
        $this->current_mode = AIAUTOTOOL_AGENT_MODE_PLANNING;
        
        // Analyze
        $analysis = $this->planner->analyze_request($request, $options);
        
        if (!$analysis['success']) {
            return $analysis;
        }
        
        // Create plan
        $plan_result = $this->planner->create_plan($analysis['analysis'], $request);
        
        if (!$plan_result['success']) {
            return $plan_result;
        }
        
        // Return plan with resource estimation
        return array(
            'success' => true,
            'analysis' => $analysis['analysis'],
            'plan' => $plan_result['plan'],
            'resources' => $this->planner->estimate_resources($plan_result['plan']),
            'sub_tasks' => $this->planner->break_down_tasks($plan_result['plan'])
        );
    }
    
    /**
     * Execute a pre-made plan
     * 
     * @param array $plan Execution plan
     * @param string $request Original request
     * @param array $options Options
     * @return array Execution result
     */
    public function execute_plan($plan, $request, $options = array()) {
        $this->current_mode = AIAUTOTOOL_AGENT_MODE_EXECUTION;
        
        return $this->executor->execute_plan($plan, $request);
    }
    
    /**
     * Verify output without execution
     * 
     * @param string $output Output to verify
     * @param string $request Original request
     * @param array $options Verification options
     * @return array Verification result
     */
    public function verify_output($output, $request, $options = array()) {
        $this->current_mode = AIAUTOTOOL_AGENT_MODE_VERIFICATION;
        
        return $this->verifier->validate_output($output, $request, $options);
    }
    
    /**
     * Get agent context
     * 
     * @return AIAutotool_Agent_Context
     */
    public function get_context() {
        return $this->context;
    }
    
    /**
     * Set agent mode
     * 
     * @param string $mode Mode constant
     * @return void
     */
    public function set_mode($mode) {
        $this->current_mode = $mode;
    }
    
    /**
     * Get current mode
     * 
     * @return string
     */
    public function get_mode() {
        return $this->current_mode;
    }
    
    /**
     * =================================================================
     * LEGACY METHODS (BACKWARD COMPATIBILITY)
     * =================================================================
     */
    
    /**
     * Main method: Generate with automatic provider/model selection and fallback
     * 
     * @deprecated Use execute_with_planning() for new Cursor-inspired workflow
     * @param string|array $prompt Text prompt or messages array
     * @param array $options Optional parameters (system, system_prompt for system rules)
     * @return array Response with 'success', 'content', 'error', 'provider', 'model'
     */
    public function generate($prompt, $options = array()) {
        // Check if model and provider are specified in options
        if (isset($options['model']) && isset($options['provider'])) {
            // Get provider from manager
            $provider = $this->manager->get_provider($options['provider']);
            
            if (!$provider) {
                return array(
                    'success' => false,
                    'error' => "Provider '{$options['provider']}' not found",
                    'provider' => $options['provider'],
                    'model' => $options['model']
                );
            }
            
            // Convert prompt to messages array if it's a string
            $messages = is_array($prompt) ? $prompt : array(
                array(
                    'role' => 'user',
                    'content' => $prompt
                )
            );
            
            // Call provider's chat_completion method
            $response = $provider->chat_completion($messages, $options);
            
            // Ensure response has provider and model info
            if (!isset($response['provider'])) {
                $response['provider'] = $options['provider'];
            }
            if (!isset($response['model'])) {
                $response['model'] = $options['model'];
            }
            
            return $response;
        } else {
            // No model/provider specified, use Gemini as fallback
            return $this->generate_with_gemini($prompt, $options);
        }
    }
    
    /**
     * Convert messages array to text string
     * 
     * @param array $messages Messages array
     * @return string Combined text
     */
    private function messages_to_text($messages) {
        $text = '';
        foreach ($messages as $message) {
            if (isset($message['content']) && is_string($message['content'])) {
                $text .= $message['content'] . "\n";
            }
        }
        return trim($text);
    }
    
    /**
     * Generate content using Gemini provider
     * Separated from general generate() to use Gemini's native API directly
     * 
     * @param string|array $prompt Text prompt or messages array
     * @param array $options Optional parameters
     * @return array Response with 'success', 'content', 'error', 'provider', 'model'
     */
    private function generate_with_gemini($prompt, $options = array()) {
        // Include Gemini base class
        require_once plugin_dir_path(__FILE__) . 'aiautotool_ai_base_gemini.php';
        
        // Create new Gemini instance
        $gemini = new Gemini();
        
        // Get model from options or use default
        $model = isset($options['model']) ? $options['model'] : 'gemini-2.5-flash';
        
        // Convert prompt to string if it's an array
        $prompt_text = is_array($prompt) ? $this->messages_to_text($prompt) : $prompt;
        
        // Call Gemini's sendRequest method
        $response = $gemini->sendRequest($prompt_text, '', $model);
        
        // Format response to match expected format
        if (isset($response['error'])) {
            return array(
                'success' => false,
                'error' => $response['error'],
                'provider' => 'gemini',
                'model' => $model
            );
        } else {
            return array(
                'success' => true,
                'content' => isset($response['content']) ? $response['content'] : (isset($response['output']) ? $response['output'] : ''),
                'provider' => 'gemini',
                'model' => $model,
                'raw_response' => $response
            );
        }
    }
    
    /**
     * Chat completion with automatic provider/model selection
     * 
     * @param array $messages Array of messages
     * @param array $options Optional parameters
     * @return array Response
     */
    public function chat($messages, $options = array()) {
        return $this->generate($messages, $options);
    }
    
    /**
     * Detect industry from prompt/messages
     * 
     * @param array $messages Messages array
     * @param array $options Options
     * @return string Industry ID ('healthcare', 'technology', 'education', etc.)
     */
    private function detect_industry($messages, $options = array()) {
        // Check if industry is explicitly specified
        if (isset($options['industry']) && isset($this->industry_rules[$options['industry']])) {
            return $options['industry'];
        }
        
        // Extract text from messages
        $text = '';
        foreach ($messages as $message) {
            if (isset($message['content']) && is_string($message['content'])) {
                $text .= ' ' . strtolower($message['content']);
            }
        }
        $text = trim($text);
        
        // Score each industry based on keyword matches
        $scores = array();
        foreach ($this->industry_rules as $industry_id => $industry_data) {
            if ($industry_id === 'general') {
                continue; // Skip general, it's the default
            }
            
            $scores[$industry_id] = 0;
            if (isset($industry_data['keywords'])) {
                foreach ($industry_data['keywords'] as $keyword) {
                    if (stripos($text, $keyword) !== false) {
                        $scores[$industry_id]++;
                    }
                }
            }
        }
        
        // Debug: Log all scores
        if (defined('WP_DEBUG') && WP_DEBUG) {
            $debug_scores = array();
            foreach ($scores as $industry_id => $score) {
                if ($score > 0) {
                    $industry_name = isset($this->industry_rules[$industry_id]['name']) ? $this->industry_rules[$industry_id]['name'] : $industry_id;
                    $debug_scores[] = "{$industry_name} ({$industry_id}): {$score}";
                }
            }
            if (!empty($debug_scores)) {
                // Debug scores available
            }
        }
        
        // Find highest score
        $max_score = max($scores);
        if ($max_score > 0) {
            foreach ($scores as $industry_id => $score) {
                if ($score === $max_score) {
                    $industry_name = isset($this->industry_rules[$industry_id]['name']) ? $this->industry_rules[$industry_id]['name'] : $industry_id;
                    return $industry_id;
                }
            }
        }
        
        // Default to general
        return 'general';
    }
    
    /**
     * Get system rule for a specific industry
     * 
     * @param string $industry_id Industry ID
     * @return string System rule text
     */
    private function get_industry_system_rule($industry_id) {
        if (isset($this->industry_rules[$industry_id]) && isset($this->industry_rules[$industry_id]['system_rule'])) {
            return $this->industry_rules[$industry_id]['system_rule'];
        }
        
        // Fallback to general
        if (isset($this->industry_rules['general']['system_rule'])) {
            return $this->industry_rules['general']['system_rule'];
        }
        
        return '';
    }
    
    /**
     * Detect use case from prompt/messages
     * 
     * @param array $messages Messages array
     * @param array $options Options
     * @return string Use case ('search', 'reasoning', 'code', 'long_context', 'fast', 'general')
     */
    private function detect_use_case($messages, $options = array()) {
        // Check if use case is explicitly specified
        if (isset($options['use_case']) && in_array($options['use_case'], array_keys($this->model_capabilities))) {
            return $options['use_case'];
        }
        
        // Extract text from messages
        $text = '';
        foreach ($messages as $message) {
            if (isset($message['content']) && is_string($message['content'])) {
                $text .= ' ' . strtolower($message['content']);
            }
        }
        $text = trim($text);
        
        // Check message length for long context
        $total_length = strlen($text);
        if ($total_length > 5000) {
            return 'long_context';
        }
        
        // Check for explicit fast mode
        if (isset($options['fast']) && $options['fast']) {
            return 'fast';
        }
        
        // Keyword-based detection
        $scores = array(
            'search' => 0,
            'reasoning' => 0,
            'code' => 0,
            'long_context' => 0,
        );
        
        foreach ($this->intent_keywords as $use_case => $keywords) {
            foreach ($keywords as $keyword) {
                if (stripos($text, $keyword) !== false) {
                    $scores[$use_case]++;
                }
            }
        }
        
        // Find highest score
        $max_score = max($scores);
        if ($max_score > 0) {
            foreach ($scores as $use_case => $score) {
                if ($score === $max_score) {
                    return $use_case;
                }
            }
        }
        
        // Default to general
        return 'general';
    }
    
    /**
     * Get preferred provider/model combinations for a use case
     * 
     * @param string $use_case Use case
     * @param array $options Options
     * @return array Array of provider/model combinations
     */
    public function get_preferred_combinations($use_case, $options = array()) {
        $combinations = array();
        $requested_combination = null;
        
        // Get use case specific combinations
        if (isset($this->model_capabilities[$use_case])) {
            $combinations = $this->model_capabilities[$use_case];
        } else {
            $combinations = $this->model_capabilities['general'];
        }
        
        // Check if specific provider/model is requested
        if (isset($options['provider']) && isset($options['model'])) {
            // Check if provider is configured before adding
            $provider = $this->manager->get_provider($options['provider']);
            if ($provider && $provider->is_configured()) {
                // Store requested combination separately (will be prepended after filtering/sorting)
                $requested_combination = array(
                    'provider' => $options['provider'],
                    'model' => $options['model'],
                    'requested' => true // Flag to indicate this was explicitly requested
                );
            }
        } elseif (isset($options['provider'])) {
            // Only provider specified - use its default model
            $provider = $this->manager->get_provider($options['provider']);
            if ($provider && $provider->is_configured()) {
                // Store requested combination separately
                $requested_combination = array(
                    'provider' => $options['provider'],
                    'model' => $provider->get_default_model(),
                    'requested' => true
                );
            }
        }
        
        // Filter to only configured providers and add fallbacks
        $filtered = array();
        $added_providers = array();
        
        // Track if requested combination is already in the list
        $requested_key = null;
        if ($requested_combination !== null) {
            $requested_key = $requested_combination['provider'] . ':' . $requested_combination['model'];
            $added_providers[] = $requested_combination['provider']; // Mark as added to avoid duplicate
        }
        
        foreach ($combinations as $combo) {
            $provider_id = $combo['provider'];
            $model = $combo['model'];
            $combo_key = $provider_id . ':' . $model;
            
            // Skip if this is the requested combination (will be added separately)
            if ($requested_key === $combo_key) {
                continue;
            }
            
            // Skip if provider already added (avoid duplicates)
            if (in_array($provider_id, $added_providers)) {
                continue;
            }
            
            $provider = $this->manager->get_provider($provider_id);
            if ($provider && $provider->is_configured()) {
                // Skip if currently rate limited (unless it's explicitly requested)
                if (!$this->is_rate_limited($combo_key)) {
                    $combo['requested'] = false; // Mark as not explicitly requested
                    $filtered[] = $combo;
                    $added_providers[] = $provider_id;
                }
            }
        }
        
        // Add fallback providers if not enough options
        if (count($filtered) < 3) {
            foreach ($this->provider_priority as $provider_id) {
                if (in_array($provider_id, $added_providers)) {
                    continue;
                }
                
                $provider = $this->manager->get_provider($provider_id);
                if ($provider && $provider->is_configured()) {
                    $fallback_model = $provider->get_default_model();
                    $fallback_key = $provider_id . ':' . $fallback_model;
                    
                    // Skip if currently rate limited
                    if (!$this->is_rate_limited($fallback_key)) {
                        $filtered[] = array(
                            'provider' => $provider_id,
                            'model' => $fallback_model
                        );
                        $added_providers[] = $provider_id;
                        
                        if (count($filtered) >= $this->max_retries) {
                            break;
                        }
                    }
                }
            }
        }
        
        // Sort by rate limit history - prioritize combinations not recently rate limited
        usort($filtered, array($this, 'sort_combinations_by_rate_limit'));
        
        // If there's a requested combination, prepend it (highest priority)
        if ($requested_combination !== null) {
            $requested_key = $requested_combination['provider'] . ':' . $requested_combination['model'];
            // Only add if not currently rate limited (unless explicitly requested, then still try)
            // For explicitly requested, we still try even if rate limited (user knows what they want)
            array_unshift($filtered, $requested_combination);
        }
        
        return $filtered;
    }
    
    /**
     * Check if response is valid (has content)
     * 
     * @param array $result Response result
     * @return bool True if valid
     */
    private function is_valid_response($result) {
        if (!isset($result['success']) || !$result['success']) {
            return false;
        }
        
        // Check if content exists and is not empty
        if (isset($result['content'])) {
            $content = trim($result['content']);
            if (!empty($content) && strlen($content) > 0) {
                return true;
            }
        }
        
        // Some providers might return 'response' instead of 'content'
        if (isset($result['response'])) {
            $response = trim($result['response']);
            if (!empty($response) && strlen($response) > 0) {
                return true;
            }
        }
        
        return false;
    }
    
    /**
     * Try request with API key rotation for quota/limit errors
     * 
     * @param object $provider Provider instance
     * @param string $provider_id Provider ID
     * @param string $model Model ID
     * @param array $messages Messages
     * @param array $options Options
     * @param string $attempt_key Attempt key
     * @return array Result
     */
    private function try_with_key_rotation($provider, $provider_id, $model, $messages, $options, $attempt_key, $original_messages = null) {
        $max_rotations = $this->max_key_rotations;
        $rotation_key = $attempt_key . '_rotation';
        
        // Get current rotation count
        $rotation_count = isset($this->key_rotation_attempts[$rotation_key]) ? $this->key_rotation_attempts[$rotation_key] : 0;
        
        // Send aithink event if stream is available
        $stream = null;
        if (isset($options['stream']) && is_object($options['stream']) && method_exists($options['stream'], 'send')) {
            $stream = $options['stream'];
            
            // Extract prompt from messages
            $prompt_text = '';
            if ($original_messages !== null) {
                // Use original messages to get user prompt
                foreach ($original_messages as $msg) {
                    if (isset($msg['role']) && $msg['role'] === 'user' && isset($msg['content'])) {
                        $prompt_text = $msg['content'];
                        break; // Get first user message
                    }
                }
            } else {
                // Fallback to messages_with_system
                foreach ($messages as $msg) {
                    if (isset($msg['role']) && $msg['role'] === 'user' && isset($msg['content'])) {
                        $prompt_text = $msg['content'];
                        break;
                    }
                }
            }
            
            // Check if prompt changed from last one
            $prompt_changed = ($this->last_aithink_prompt !== $prompt_text);
            
            // Build aithink event data
            $aithink_data = array(
                'provider' => $provider_id,
                'model' => $model,
                'timestamp' => current_time('mysql')
            );
            
            // Only include prompt if it changed
            if ($prompt_changed) {
                // Truncate prompt if too long for display
                $prompt_display = mb_strlen($prompt_text) > 200 ? mb_substr($prompt_text, 0, 200) . '...' : $prompt_text;
                $aithink_data['prompt'] = $prompt_display;
                $aithink_data['prompt_full'] = $prompt_text;
                // Update last prompt
                $this->last_aithink_prompt = $prompt_text;
            }
            
            // Send aithink event
            $stream->send('aithink', $aithink_data);
        }
        
        // Remove stream from options before passing to provider
        $provider_options = $options;
        unset($provider_options['stream']);
        
        // Try with current API key
        $result = $provider->chat_completion($messages, $provider_options);
        
        // If successful, return immediately
        if ($this->is_valid_response($result)) {
            return $result;
        }
        
        // Check if error is quota/limit related
        $error = isset($result['error']) ? $result['error'] : '';
        
        // Check if this is specifically a rate limit error (429) - different handling
        if ($this->is_rate_limit_error_detailed($error, $result)) {
            // Rate limit error - mark it and return (will be handled in main loop with delay)
            $this->mark_rate_limited($attempt_key);
            return $result;
        }
        
        if (!$this->is_quota_limit_error($error, $result)) {
            // Not a quota error - stream error to aithink if stream is available
            if ($stream && !empty($error)) {
                $stream->send('aithink', array(
                    'provider' => $provider_id,
                    'model' => $model,
                    'error' => $error,
                    'failed' => true,
                    'timestamp' => current_time('mysql')
                ));
            }
            // Return immediately
            return $result;
        }
        
        // Quota/limit error detected - try rotating API key
        if ($rotation_count < $max_rotations) {
            // Check if provider has multiple API keys (including old single key format)
            $keys_manager = AIAutotool_AI_Provider_API_Keys::get_instance();
            $active_keys = $keys_manager->get_active_keys($provider_id);
            
            // Also check old single key format
            $option_name = 'aiautotool_' . $provider_id . '_api_key';
            $old_key = get_option($option_name, '');
            $has_old_key = !empty($old_key) && $old_key !== 'unused';
            
            // Count total available keys (new format + old format if exists and different)
            $total_keys = count($active_keys);
            if ($has_old_key) {
                // Check if old key is different from any active key
                $old_key_in_active = false;
                foreach ($active_keys as $key_data) {
                    if (isset($key_data['key']) && $key_data['key'] === $old_key) {
                        $old_key_in_active = true;
                        break;
                    }
                }
                if (!$old_key_in_active) {
                    $total_keys++;
                }
            }
            
            // Special case for pollinations: also count default key if user has added at least one key
            if ($provider_id === 'pollinations' && count($active_keys) > 0) {
                // User has added keys, so we can rotate between user keys and default key
                $total_keys++; // Count default key as an option
            }
            
            // Log key information for debugging
            if (defined('WP_DEBUG') && WP_DEBUG) {
                // Debug logging disabled
            }
            
            // If only one key or no keys, can't rotate
            if ($total_keys <= 1) {
                return $result;
            }
            
            // Force rotate to next API key
            
            // Force rotate API key by calling get_next_key() to update rotation index
            // This ensures the next provider instance will get a different key
            $keys_manager->get_next_key($provider_id);
            
            // Refresh provider to get new API key
            $this->manager->refresh_providers();
            $provider = $this->manager->get_provider($provider_id);
            
            if ($provider && $provider->is_configured()) {
                // Update rotation count
                $this->key_rotation_attempts[$rotation_key] = $rotation_count + 1;
                
                // Send aithink event for retry if stream is available
                if ($stream) {
                    // Build retry aithink event (no prompt needed, same prompt as before)
                    $retry_data = array(
                        'provider' => $provider_id,
                        'model' => $model,
                        'retry' => true,
                        'timestamp' => current_time('mysql')
                    );
                    
                    $stream->send('aithink', $retry_data);
                }
                
                // Retry with new API key (use provider_options without stream)
                $retry_result = $provider->chat_completion($messages, $provider_options);
                
                // If successful with new key, return
                if ($this->is_valid_response($retry_result)) {
                    return $retry_result;
                }
                
                // Still failed - check if it's another quota error
                $retry_error = isset($retry_result['error']) ? $retry_result['error'] : '';
                if ($this->is_quota_limit_error($retry_error, $retry_result) && $rotation_count + 1 < $max_rotations) {
                    // Recursively try again with next key
                    return $this->try_with_key_rotation($provider, $provider_id, $model, $messages, $options, $attempt_key, $original_messages);
                }
                
                // Return the retry result
                return $retry_result;
            }
        }
        
        // Max rotations reached or provider refresh failed
        
        return $result;
    }
    
    /**
     * Sort combinations by rate limit history
     * Combinations not rate limited come first
     * Explicitly requested combinations always get highest priority
     * 
     * @param array $a First combination
     * @param array $b Second combination
     * @return int Comparison result
     */
    private function sort_combinations_by_rate_limit($a, $b) {
        // Explicitly requested combinations always come first
        $requested_a = isset($a['requested']) && $a['requested'];
        $requested_b = isset($b['requested']) && $b['requested'];
        
        if ($requested_a && !$requested_b) {
            return -1; // A comes first
        }
        if (!$requested_a && $requested_b) {
            return 1; // B comes first
        }
        
        $key_a = $a['provider'] . ':' . $a['model'];
        $key_b = $b['provider'] . ':' . $b['model'];
        
        $rate_limited_a = $this->is_rate_limited($key_a);
        $rate_limited_b = $this->is_rate_limited($key_b);
        
        // Not rate limited comes first
        if ($rate_limited_a && !$rate_limited_b) {
            return 1;
        }
        if (!$rate_limited_a && $rate_limited_b) {
            return -1;
        }
        
        // Both rate limited or both not - sort by timestamp (most recent last)
        if ($rate_limited_a && $rate_limited_b) {
            $timestamp_a = isset($this->rate_limit_timestamps[$key_a]) ? $this->rate_limit_timestamps[$key_a] : 0;
            $timestamp_b = isset($this->rate_limit_timestamps[$key_b]) ? $this->rate_limit_timestamps[$key_b] : 0;
            return $timestamp_a - $timestamp_b; // Older first (less recently rate limited)
        }
        
        return 0; // Equal priority
    }
    
    /**
     * Check if error is quota/limit related (excluding rate limit 429)
     * This checks for quota errors (402, billing issues) but NOT rate limit 429
     * Rate limit 429 is handled separately by is_rate_limit_error_detailed()
     * 
     * @param string $error Error message
     * @param array $result Full result array
     * @return bool True if quota/limit error (but not rate limit 429)
     */
    private function is_quota_limit_error($error, $result = array()) {
        if (empty($error)) {
            // Check HTTP status code
            if (isset($result['status_code'])) {
                $status = intval($result['status_code']);
                if ($status === 402) { // Payment/quota required
                    return true;
                }
                // 429 is rate limit, not quota - handled separately
            }
            return false;
        }
        
        $error_lower = strtolower($error);
        
        // Exclude rate limit errors (429) - those are handled separately
        if ($this->is_rate_limit_error_detailed($error, $result)) {
            return false;
        }
        
        // Check for quota/limit keywords (but not rate limit)
        $quota_keywords = array(
            'quota exceeded',
            'quota limit',
            'quota',
            'insufficient',
            '402', // Payment required / quota exceeded
            'credits',
            'balance',
            'pollen', // Pollinations.ai specific
            'monthly included',
            'subscribe to pro',
            'generativelanguage', // Gemini API specific
            'free_tier', // Gemini free tier quota
            'billing details', // Gemini quota error message
            'check your plan', // Gemini quota error message
            'payment required'
        );
        
        foreach ($quota_keywords as $keyword) {
            if (stripos($error_lower, $keyword) !== false) {
                return true;
            }
        }
        
        // Check HTTP status codes (402 = quota/payment, but not 429 = rate limit)
        if (isset($result['status_code'])) {
            $status = intval($result['status_code']);
            if ($status === 402) { // Payment/quota required
                return true;
            }
            // 429 is rate limit - handled separately
        }
        
        return false;
    }
    
    /**
     * Log failed attempt
     * 
     * @param string $attempt_key Provider:Model key
     * @param string $reason Failure reason
     */
    private function log_failure($attempt_key, $reason) {
        // Lưu cả attempt_key và error message để có thể log chi tiết sau
        $this->failed_attempts[$attempt_key] = $reason;
    }
    
    /**
     * Check if provider/model is currently rate limited
     * 
     * @param string $attempt_key Provider:Model key
     * @return bool True if rate limited within cooldown period
     */
    private function is_rate_limited($attempt_key) {
        if (!isset($this->rate_limit_timestamps[$attempt_key])) {
            return false;
        }
        
        $timestamp = $this->rate_limit_timestamps[$attempt_key];
        $elapsed = time() - $timestamp;
        
        return $elapsed < $this->rate_limit_cooldown;
    }
    
    /**
     * Mark provider/model as rate limited with current timestamp
     * 
     * @param string $attempt_key Provider:Model key
     */
    private function mark_rate_limited($attempt_key) {
        $this->rate_limit_timestamps[$attempt_key] = time();
    }
    
    /**
     * Clean up old rate limit timestamps (older than cooldown period)
     */
    private function cleanup_rate_limit_timestamps() {
        $current_time = time();
        foreach ($this->rate_limit_timestamps as $attempt_key => $timestamp) {
            $elapsed = $current_time - $timestamp;
            if ($elapsed >= $this->rate_limit_cooldown) {
                unset($this->rate_limit_timestamps[$attempt_key]);
            }
        }
    }
    
    /**
     * Check if error is a rate limit error (429) - detailed check
     * This is separate from is_quota_limit_error to specifically detect 429
     * 
     * @param string $error Error message
     * @param array $result Full result array
     * @return bool True if rate limit error (429)
     */
    private function is_rate_limit_error_detailed($error, $result = array()) {
        if (empty($error)) {
            // Check HTTP status code
            if (isset($result['status_code'])) {
                $status = intval($result['status_code']);
                if ($status === 429) {
                    return true;
                }
            }
            return false;
        }
        
        $error_lower = strtolower($error);
        
        // Check HTTP status code first (most reliable)
        if (isset($result['status_code'])) {
            $status = intval($result['status_code']);
            if ($status === 429) {
                return true;
            }
        }
        
        // Check for rate limit specific keywords (but not quota keywords)
        $rate_limit_keywords = array(
            'rate limit',
            'too many requests',
            '429',
            'please retry in', // Gemini specific
            'resource has been exhausted', // Some APIs
            'requests per minute',
            'requests per hour',
            'requests per day'
        );
        
        // Rate limit keywords that should NOT trigger (these are quota, not rate limit)
        $quota_keywords = array(
            'quota exceeded',
            'quota limit',
            'free_tier',
            'billing details',
            'check your plan',
            'insufficient credits',
            'insufficient balance'
        );
        
        // If contains quota keywords without rate limit keywords, it's quota not rate limit
        $has_quota_keyword = false;
        foreach ($quota_keywords as $quota_keyword) {
            if (stripos($error_lower, $quota_keyword) !== false) {
                $has_quota_keyword = true;
                break;
            }
        }
        
        // Check for rate limit keywords
        foreach ($rate_limit_keywords as $keyword) {
            if (stripos($error_lower, $keyword) !== false) {
                // If it has quota keyword too, prefer quota interpretation
                if ($has_quota_keyword && stripos($error_lower, 'quota') !== false) {
                    continue;
                }
                return true;
            }
        }
        
        return false;
    }
    
    /**
     * Get available providers and models
     * 
     * @return array Available combinations
     */
    public function get_available_options() {
        $options = array();
        
        foreach ($this->manager->get_configured_providers() as $provider_id => $provider) {
            $models = $provider->get_available_models();
            foreach ($models as $model_id => $model_name) {
                $options[] = array(
                    'provider' => $provider_id,
                    'provider_name' => $provider->get_name(),
                    'model' => $model_id,
                    'model_name' => $model_name
                );
            }
        }
        
        return $options;
    }
    
    /**
     * Test a specific provider/model combination
     * 
     * @param string $provider_id Provider ID
     * @param string $model Model ID
     * @param string $test_prompt Optional test prompt
     * @return array Test result
     */
    public function test_combination($provider_id, $model, $test_prompt = null) {
        $provider = $this->manager->get_provider($provider_id);
        
        if (!$provider) {
            return array(
                'success' => false,
                'error' => "Provider '{$provider_id}' not found"
            );
        }
        
        if (!$provider->is_configured()) {
            return array(
                'success' => false,
                'error' => "Provider '{$provider_id}' not configured"
            );
        }
        
        $available_models = $provider->get_available_models();
        if (!isset($available_models[$model])) {
            return array(
                'success' => false,
                'error' => "Model '{$model}' not available for provider '{$provider_id}'"
            );
        }
        
        // Use test prompt or default
        if ($test_prompt === null) {
            $test_prompt = "Hello! Please respond with 'OK' to confirm you're working.";
        }
        
        $messages = array(
            array('role' => 'user', 'content' => $test_prompt)
        );
        
        $result = $provider->chat_completion($messages, array('model' => $model));
        
        return array_merge($result, array(
            'provider' => $provider_id,
            'model' => $model,
            'valid' => $this->is_valid_response($result)
        ));
    }
    
    /**
     * Set custom provider priority
     * 
     * @param array $priority Array of provider IDs in priority order
     */
    public function set_provider_priority($priority) {
        $this->provider_priority = $priority;
    }
    
    /**
     * Set custom model capabilities
     * 
     * @param string $use_case Use case name
     * @param array $combinations Array of provider/model combinations
     */
    public function set_model_capabilities($use_case, $combinations) {
        $this->model_capabilities[$use_case] = $combinations;
    }
    
    /**
     * Get all available industries
     * 
     * @return array Array of industries with id, name, keywords
     */
    public function get_available_industries() {
        $industries = array();
        foreach ($this->industry_rules as $industry_id => $industry_data) {
            $industries[] = array(
                'id' => $industry_id,
                'name' => isset($industry_data['name']) ? $industry_data['name'] : $industry_id,
                'keywords' => isset($industry_data['keywords']) ? $industry_data['keywords'] : array()
            );
        }
        return $industries;
    }
    
    /**
     * Get system rule for a specific industry
     * 
     * @param string $industry_id Industry ID
     * @return string|false System rule text or false if not found
     */
    public function get_industry_rule($industry_id) {
        if (isset($this->industry_rules[$industry_id]) && isset($this->industry_rules[$industry_id]['system_rule'])) {
            return $this->industry_rules[$industry_id]['system_rule'];
        }
        return false;
    }
    
    /**
     * Set or update industry system rule
     * 
     * @param string $industry_id Industry ID
     * @param string $name Industry display name
     * @param string $system_rule System rule text
     * @param array $keywords Optional keywords for detection
     * @return bool Success
     */
    public function set_industry_rule($industry_id, $name, $system_rule, $keywords = array()) {
        if (empty($industry_id) || empty($system_rule)) {
            return false;
        }
        
        $this->industry_rules[$industry_id] = array(
            'name' => $name,
            'system_rule' => $system_rule,
            'keywords' => is_array($keywords) ? $keywords : array()
        );
        
        return true;
    }
    
    /**
     * Remove an industry rule
     * 
     * @param string $industry_id Industry IDl;v
     * @return bool Success (cannot remove 'general')
     */
    public function remove_industry_rule($industry_id) {
        if ($industry_id === 'general') {
            return false; // Cannot remove general
        }
        
        if (isset($this->industry_rules[$industry_id])) {
            unset($this->industry_rules[$industry_id]);
            return true;
        }
        
        return false;
    }
    
    /**
     * Test industry detection for a given prompt
     * Useful for debugging which industry will be detected
     * 
     * @param string|array $prompt Text prompt or messages array
     * @param array $options Options
     * @return array Debug information about industry detection
     */
    public function debug_industry_detection($prompt, $options = array()) {
        // Convert prompt to messages if needed
        $messages = is_array($prompt) ? $prompt : array(
            array('role' => 'user', 'content' => $prompt)
        );
        
        // Extract text from messages
        $text = '';
        foreach ($messages as $message) {
            if (isset($message['content']) && is_string($message['content'])) {
                $text .= ' ' . strtolower($message['content']);
            }
        }
        $text = trim($text);
        
        // Check if industry is explicitly specified
        $explicit_industry = null;
        if (isset($options['industry']) && isset($this->industry_rules[$options['industry']])) {
            $explicit_industry = $options['industry'];
        }
        
        // Score each industry based on keyword matches
        $scores = array();
        $matched_keywords = array();
        
        foreach ($this->industry_rules as $industry_id => $industry_data) {
            if ($industry_id === 'general') {
                continue; // Skip general, it's the default
            }
            
            $scores[$industry_id] = 0;
            $matched_keywords[$industry_id] = array();
            
            if (isset($industry_data['keywords'])) {
                foreach ($industry_data['keywords'] as $keyword) {
                    if (stripos($text, $keyword) !== false) {
                        $scores[$industry_id]++;
                        $matched_keywords[$industry_id][] = $keyword;
                    }
                }
            }
        }
        
        // Find highest score
        $max_score = max($scores);
        $detected_industry = 'general';
        if ($max_score > 0) {
            foreach ($scores as $industry_id => $score) {
                if ($score === $max_score) {
                    $detected_industry = $industry_id;
                    break;
                }
            }
        }
        
        // Get industry system rule
        $industry_system_rule = $this->get_industry_system_rule($detected_industry);
        
        return array(
            'prompt_text' => $text,
            'explicit_industry' => $explicit_industry,
            'detected_industry' => $detected_industry,
            'detected_industry_name' => isset($this->industry_rules[$detected_industry]['name']) ? $this->industry_rules[$detected_industry]['name'] : $detected_industry,
            'scores' => $scores,
            'matched_keywords' => $matched_keywords,
            'max_score' => $max_score,
            'has_industry_rule' => !empty($industry_system_rule),
            'industry_rule_length' => strlen($industry_system_rule),
            'industry_rule_preview' => !empty($industry_system_rule) ? substr($industry_system_rule, 0, 200) . '...' : ''
        );
    }
    
    /**
     * Get statistics about agent usage
     * 
     * @return array Statistics
     */
    public function get_statistics() {
        return array(
            'available_providers' => count($this->manager->get_configured_providers()),
            'total_combinations' => count($this->get_available_options()),
            'max_retries' => $this->max_retries,
            'use_cases' => array_keys($this->model_capabilities),
            'available_industries' => count($this->industry_rules)
        );
    }
    
    /**
     * ========================================
     * TASK MANAGEMENT METHODS
     * ========================================
     */
    
    /**
     * Analyze prompt to understand user intent and extract tasks
     * 
     * @param string|array $prompt User prompt or messages
     * @param array $options Analysis options
     * @return array Analysis result with extracted information
     */
    public function analyze_prompt($prompt, $options = array()) {
        // Convert prompt to string if needed
        $prompt_text = is_array($prompt) ? $this->extract_text_from_messages($prompt) : $prompt;
        
        // Use AI to analyze the prompt
        $analysis_prompt = "Phân tích prompt sau đây và trả về kết quả dưới dạng JSON với các thông tin:
1. intent: Ý định chính của người dùng (search, create, analyze, transform, etc.)
2. complexity: Độ phức tạp (simple, medium, complex)
3. requires_multi_step: Có cần nhiều bước không (true/false)
4. estimated_tasks: Số lượng task ước tính
5. main_goal: Mục tiêu chính
6. sub_goals: Các mục tiêu phụ (array)

Prompt cần phân tích:
{$prompt_text}

Chỉ trả về JSON, không thêm text khác. Format:
{
  \"intent\": \"...\",
  \"complexity\": \"...\",
  \"requires_multi_step\": true/false,
  \"estimated_tasks\": number,
  \"main_goal\": \"...\",
  \"sub_goals\": [\"...\", \"...\"]
}";
        
        $result = $this->generate($analysis_prompt, array_merge($options, array('fast' => true)));
        
        if (!$result['success']) {
            return array(
                'success' => false,
                'error' => 'Failed to analyze prompt: ' . $result['error']
            );
        }
        
        // Parse JSON response
        $content = $result['content'];
        
        // Extract JSON from markdown code blocks if present
        if (preg_match('/```json\s*(.*?)\s*```/s', $content, $matches)) {
            $content = $matches[1];
        } elseif (preg_match('/```\s*(.*?)\s*```/s', $content, $matches)) {
            $content = $matches[1];
        }
        
        $analysis = json_decode($content, true);
        
        if (json_last_error() !== JSON_ERROR_NONE) {
            // Fallback to basic analysis
            $analysis = array(
                'intent' => 'general',
                'complexity' => 'medium',
                'requires_multi_step' => false,
                'estimated_tasks' => 1,
                'main_goal' => $prompt_text,
                'sub_goals' => array()
            );
        }
        
        return array(
            'success' => true,
            'analysis' => $analysis,
            'original_prompt' => $prompt_text
        );
    }
    
    /**
     * Extract tasks from analysis result
     * 
     * @param array $analysis Analysis result from analyze_prompt()
     * @param string $original_prompt Original user prompt
     * @param array $options Options
     * @return array Array of task definitions
     */
    public function extract_tasks($analysis, $original_prompt, $options = array()) {
        if (!isset($analysis['sub_goals']) || empty($analysis['sub_goals'])) {
            // Single task
            return array(
                $this->create_task(
                    isset($analysis['main_goal']) ? $analysis['main_goal'] : 'Main Task',
                    $original_prompt,
                    isset($analysis['intent']) ? $analysis['intent'] : 'general',
                    5
                )
            );
        }
        
        // Multiple tasks from sub_goals
        $tasks = array();
        $priority = 10;
        
        // Add main goal as first task if it's different from sub_goals
        $main_goal = isset($analysis['main_goal']) ? $analysis['main_goal'] : '';
        if (!empty($main_goal) && !in_array($main_goal, $analysis['sub_goals'])) {
            $tasks[] = $this->create_task(
                $main_goal,
                $main_goal,
                isset($analysis['intent']) ? $analysis['intent'] : 'general',
                $priority--
            );
        }
        
        // Add sub_goals as tasks
        foreach ($analysis['sub_goals'] as $sub_goal) {
            $tasks[] = $this->create_task(
                $sub_goal,
                $sub_goal,
                $this->detect_task_type($sub_goal),
                $priority--
            );
        }
        
        return $tasks;
    }
    
    /**
     * Detect task type from task description
     * 
     * @param string $description Task description
     * @return string Task type
     */
    private function detect_task_type($description) {
        $desc_lower = strtolower($description);
        
        // Search keywords
        if (preg_match('/(tìm kiếm|search|find|lookup|nghiên cứu|research)/i', $desc_lower)) {
            return 'search';
        }
        
        // Analysis keywords
        if (preg_match('/(phân tích|analyze|review|evaluate|đánh giá|so sánh|compare)/i', $desc_lower)) {
            return 'analysis';
        }
        
        // Generation keywords
        if (preg_match('/(viết|write|tạo|create|generate|develop|xây dựng)/i', $desc_lower)) {
            return 'generation';
        }
        
        // Transformation keywords
        if (preg_match('/(chuyển đổi|transform|convert|translate|format|tối ưu|optimize)/i', $desc_lower)) {
            return 'transformation';
        }
        
        // Validation keywords
        if (preg_match('/(kiểm tra|check|validate|verify|test)/i', $desc_lower)) {
            return 'validation';
        }
        
        return 'general';
    }
    
    /**
     * Create a new task
     * 
     * @param string $title Task title
     * @param string $description Task description
     * @param string $type Task type
     * @param int $priority Priority (1-10, higher = more important)
     * @return array Task definition
     */
    public function create_task($title, $description, $type = 'general', $priority = 5) {
        $this->task_counter++;
        
        return array(
            'id' => 'task_' . time() . '_' . $this->task_counter,
            'title' => $title,
            'description' => $description,
            'type' => $type,
            'priority' => $priority,
            'status' => 'pending',
            'dependencies' => array(),
            'steps' => array(),
            'result' => null,
            'error' => null,
            'created_at' => time(),
            'updated_at' => time(),
            'completed_at' => null
        );
    }
    
    /**
     * Detect task dependencies
     * Phát hiện các phụ thuộc giữa các task
     * 
     * @param array $tasks Array of tasks
     * @return array Tasks with dependencies updated
     */
    public function detect_task_dependencies($tasks) {
        // Simple dependency detection based on task types and content
        // More advanced: search/analysis tasks usually come before generation
        
        for ($i = 0; $i < count($tasks); $i++) {
            for ($j = 0; $j < count($tasks); $j++) {
                if ($i === $j) continue;
                
                $task_a = $tasks[$i];
                $task_b = $tasks[$j];
                
                // If task B is generation and task A is search/analysis
                // Then task B depends on task A
                if ($task_b['type'] === 'generation' && 
                    in_array($task_a['type'], array('search', 'analysis'))) {
                    
                    // Check if task A's content is relevant to task B
                    if ($this->tasks_are_related($task_a, $task_b)) {
                        if (!in_array($task_a['id'], $task_b['dependencies'])) {
                            $tasks[$j]['dependencies'][] = $task_a['id'];
                        }
                    }
                }
                
                // If task B is validation and task A is generation
                if ($task_b['type'] === 'validation' && 
                    $task_a['type'] === 'generation') {
                    
                    if ($this->tasks_are_related($task_a, $task_b)) {
                        if (!in_array($task_a['id'], $task_b['dependencies'])) {
                            $tasks[$j]['dependencies'][] = $task_a['id'];
                        }
                    }
                }
            }
        }
        
        return $tasks;
    }
    
    /**
     * Check if two tasks are related
     * 
     * @param array $task_a First task
     * @param array $task_b Second task
     * @return bool True if related
     */
    private function tasks_are_related($task_a, $task_b) {
        // Simple word matching
        $words_a = preg_split('/\s+/', strtolower($task_a['description']));
        $words_b = preg_split('/\s+/', strtolower($task_b['description']));
        
        // Remove common words
        $common_words = array('và', 'hoặc', 'của', 'cho', 'the', 'and', 'or', 'for', 'to', 'a', 'an');
        $words_a = array_diff($words_a, $common_words);
        $words_b = array_diff($words_b, $common_words);
        
        // Check intersection
        $intersection = array_intersect($words_a, $words_b);
        
        // If >20% words match, consider related
        $min_count = min(count($words_a), count($words_b));
        if ($min_count > 0 && count($intersection) / $min_count > 0.2) {
            return true;
        }
        
        return false;
    }
    
    /**
     * Prioritize tasks based on dependencies and priority
     * 
     * @param array $tasks Array of tasks
     * @return array Sorted tasks
     */
    public function prioritize_tasks($tasks) {
        // Topological sort based on dependencies
        $sorted = array();
        $visited = array();
        
        // Helper function for DFS
        $visit = function($task_id) use (&$tasks, &$sorted, &$visited, &$visit) {
            if (isset($visited[$task_id])) {
                return;
            }
            
            $visited[$task_id] = true;
            
            // Find task
            $task = null;
            foreach ($tasks as $t) {
                if ($t['id'] === $task_id) {
                    $task = $t;
                    break;
                }
            }
            
            if (!$task) {
                return;
            }
            
            // Visit dependencies first
            foreach ($task['dependencies'] as $dep_id) {
                $visit($dep_id);
            }
            
            // Add to sorted
            $sorted[] = $task;
        };
        
        // Visit all tasks
        foreach ($tasks as $task) {
            $visit($task['id']);
        }
        
        return $sorted;
    }
    
    /**
     * Add task to queue
     * 
     * @param array $task Task definition
     */
    public function add_task_to_queue($task) {
        $this->task_queue[] = $task;
    }
    
    /**
     * Get next task from queue
     * 
     * @return array|null Next task or null if queue is empty
     */
    public function get_next_task() {
        if (empty($this->task_queue)) {
            return null;
        }
        
        // Find first task with all dependencies completed
        foreach ($this->task_queue as $index => $task) {
            $can_execute = true;
            
            foreach ($task['dependencies'] as $dep_id) {
                if (!isset($this->completed_tasks[$dep_id])) {
                    $can_execute = false;
                    break;
                }
            }
            
            if ($can_execute) {
                // Remove from queue and return
                $next_task = array_splice($this->task_queue, $index, 1)[0];
                return $next_task;
            }
        }
        
        // No executable task found (circular dependency or missing dependency)
        return null;
    }
    
    /**
     * Update task status
     * 
     * @param string $task_id Task ID
     * @param string $status New status
     */
    public function update_task_status($task_id, $status) {
        if ($this->current_task && $this->current_task['id'] === $task_id) {
            $this->current_task['status'] = $status;
            $this->current_task['updated_at'] = time();
        }
    }
    
    /**
     * Get task status
     * 
     * @param string $task_id Task ID
     * @return string|null Task status or null if not found
     */
    public function get_task_status($task_id) {
        if ($this->current_task && $this->current_task['id'] === $task_id) {
            return $this->current_task['status'];
        }
        
        if (isset($this->completed_tasks[$task_id])) {
            return $this->completed_tasks[$task_id]['status'];
        }
        
        foreach ($this->task_queue as $task) {
            if ($task['id'] === $task_id) {
                return $task['status'];
            }
        }
        
        return null;
    }
    
    /**
     * Main method: Execute tasks workflow
     * Analyzes prompt, creates tasks, and executes them
     * 
     * @param string|array $prompt User prompt
     * @param array $options Options
     * @return array Execution result with all task results
     */
    public function execute_tasks($prompt, $options = array()) {
        // Reset state
        $this->task_queue = array();
        $this->current_task = null;
        $this->completed_tasks = array();
        $this->task_results = array();
        $this->task_counter = 0;
        
        // Step 1: Analyze prompt
        $analysis_result = $this->analyze_prompt($prompt, $options);
        
        if (!$analysis_result['success']) {
            return array(
                'success' => false,
                'error' => 'Failed to analyze prompt',
                'details' => $analysis_result
            );
        }
        
        $analysis = $analysis_result['analysis'];
        $original_prompt = $analysis_result['original_prompt'];
        
        // Check if multi-step is required
        if (!isset($analysis['requires_multi_step']) || !$analysis['requires_multi_step']) {
            // Simple single execution
            return $this->generate($prompt, $options);
        }
        
        // Step 2: Extract tasks
        $tasks = $this->extract_tasks($analysis, $original_prompt, $options);
        
        // Step 3: Detect dependencies
        $tasks = $this->detect_task_dependencies($tasks);
        
        // Step 4: Prioritize tasks
        $tasks = $this->prioritize_tasks($tasks);
        
        // Step 5: Add to queue
        foreach ($tasks as $task) {
            $this->add_task_to_queue($task);
        }
        
        // Step 6: Execute tasks
        $execution_results = array();
        $max_iterations = count($tasks) * 2; // Prevent infinite loop
        $iterations = 0;
        
        while (!empty($this->task_queue) && $iterations < $max_iterations) {
            $iterations++;
            
            $task = $this->get_next_task();
            
            if (!$task) {
                // No executable task (circular dependency)
                break;
            }
            
            $task_result = $this->execute_task($task, $options);
            $execution_results[] = $task_result;
            
            if ($task_result['success']) {
                $this->completed_tasks[$task['id']] = $task_result['task'];
                $this->task_results[$task['id']] = $task_result['result'];
            } else {
                // Task failed - decide whether to continue or stop
                if (isset($options['stop_on_error']) && $options['stop_on_error']) {
                    break;
                }
            }
        }
        
        // Step 7: Compile final result
        $final_result = $this->compile_final_result($execution_results, $analysis, $original_prompt);
        
        return array(
            'success' => true,
            'analysis' => $analysis,
            'tasks_executed' => count($execution_results),
            'tasks_total' => count($tasks),
            'execution_results' => $execution_results,
            'final_result' => $final_result,
            'task_results' => $this->task_results
        );
    }
    
    /**
     * Execute a single task
     * 
     * @param array $task Task definition
     * @param array $options Options
     * @return array Execution result
     */
    public function execute_task($task, $options = array()) {
        $this->current_task = $task;
        $this->update_task_status($task['id'], 'in_progress');
        
        // Prepare prompt for task execution
        $task_prompt = $this->prepare_task_prompt($task, $options);
        
        // Execute using the generate method
        $result = $this->generate($task_prompt, array_merge($options, array(
            'use_case' => $this->map_task_type_to_use_case($task['type'])
        )));
        
        if ($result['success']) {
            $task['status'] = 'completed';
            $task['result'] = $result['content'];
            $task['completed_at'] = time();
        } else {
            $task['status'] = 'failed';
            $task['error'] = isset($result['error']) ? $result['error'] : 'Unknown error';
        }
        
        $task['updated_at'] = time();
        $this->current_task = $task;
        
        return array(
            'success' => $result['success'],
            'task' => $task,
            'result' => isset($result['content']) ? $result['content'] : null,
            'error' => isset($result['error']) ? $result['error'] : null,
            'provider' => isset($result['provider']) ? $result['provider'] : null,
            'model' => isset($result['model']) ? $result['model'] : null
        );
    }
    
    /**
     * Prepare prompt for task execution
     * Include context from completed tasks if they are dependencies
     * 
     * @param array $task Task definition
     * @param array $options Options
     * @return string Prepared prompt
     */
    private function prepare_task_prompt($task, $options = array()) {
        $prompt = $task['description'];
        
        // Add context from dependencies
        if (!empty($task['dependencies'])) {
            $context = "\n\nBối cảnh từ các task trước đó:\n";
            
            foreach ($task['dependencies'] as $dep_id) {
                if (isset($this->task_results[$dep_id])) {
                    $dep_task = $this->completed_tasks[$dep_id];
                    $context .= "\n--- {$dep_task['title']} ---\n";
                    $context .= $this->task_results[$dep_id] . "\n";
                }
            }
            
            $prompt = $context . "\n\nNhiệm vụ hiện tại:\n" . $prompt;
        }
        
        return $prompt;
    }
    
    /**
     * Map task type to use case
     * 
     * @param string $task_type Task type
     * @return string Use case
     */
    private function map_task_type_to_use_case($task_type) {
        $mapping = array(
            'search' => 'search',
            'analysis' => 'reasoning',
            'generation' => 'general',
            'transformation' => 'general',
            'validation' => 'reasoning',
            'general' => 'general'
        );
        
        return isset($mapping[$task_type]) ? $mapping[$task_type] : 'general';
    }
    
    /**
     * Compile final result from all task results
     * 
     * @param array $execution_results Array of execution results
     * @param array $analysis Original analysis
     * @param string $original_prompt Original prompt
     * @return string Final compiled result
     */
    private function compile_final_result($execution_results, $analysis, $original_prompt) {
        if (empty($execution_results)) {
            return "Không có kết quả nào được tạo.";
        }
        
        // Use AI to compile results
        $results_text = "";
        foreach ($execution_results as $index => $exec_result) {
            if ($exec_result['success']) {
                $task_title = $exec_result['task']['title'];
                $task_result = $exec_result['result'];
                $results_text .= "\n\n=== Task " . ($index + 1) . ": {$task_title} ===\n{$task_result}";
            }
        }
        
        $compile_prompt = "Dựa trên yêu cầu ban đầu và các kết quả từ các task, hãy tổng hợp thành một kết quả cuối cùng hoàn chỉnh và mạch lạc.

Yêu cầu ban đầu:
{$original_prompt}

Các kết quả từ tasks:
{$results_text}

Hãy tổng hợp tất cả thông tin trên thành một kết quả cuối cùng hoàn chỉnh, đầy đủ và dễ hiểu.";
        
        $compile_result = $this->generate($compile_prompt, array('fast' => true));
        
        if ($compile_result['success']) {
            return $compile_result['content'];
        }
        
        // Fallback: just concatenate results
        return $results_text;
    }
    
    /**
     * Extract text from messages array
     * 
     * @param array $messages Messages array
     * @return string Extracted text
     */
    private function extract_text_from_messages($messages) {
        $text = '';
        foreach ($messages as $message) {
            if (isset($message['content']) && is_string($message['content'])) {
                $text .= $message['content'] . ' ';
            }
        }
        return trim($text);
    }
    
    /**
     * Get all task results
     * 
     * @return array Task results
     */
    public function get_task_results() {
        return $this->task_results;
    }
    
    /**
     * Get completed tasks
     * 
     * @return array Completed tasks
     */
    public function get_completed_tasks() {
        return $this->completed_tasks;
    }
    
    /**
     * Get current task
     * 
     * @return array|null Current task or null
     */
    public function get_current_task() {
        return $this->current_task;
    }
    
    /**
     * Get task queue
     * 
     * @return array Task queue
     */
    public function get_task_queue() {
        return $this->task_queue;
    }
    
    /**
     * ========================================
     * SSE STREAMING METHODS
     * ========================================
     */
    
    /**
     * Execute prompt with SSE streaming
     * 
     * @param string $prompt User prompt
     * @param AIAutoTool_SSE_Stream $stream SSE stream instance
     * @param array $options Execution options
     * @param string $title Post title (optional, defaults to prompt)
     * @return array Execution result
     */
    public function execute_with_stream($prompt, $stream, $options = array(), $title = '') {
        
        // Use provided title or fallback to prompt
        if (empty($title)) {
            $title = $prompt;
        }
        
        $stream->send_status("Bắt đầu viết bài: " . $title);
        error_log("Writing article with title: " . $title);
        
        // Get auto writer instance
        $auto_writer = AIAutotool_AI_Auto_Writer::get_instance();
        
        // Merge options with defaults
        $writer_options = array_merge(array(
            'language' => 'vi',
            'industry' => 'auto',
            'min_sections' => 5,
            'max_sections' => 10,
            'words_per_section' => 300,
            'include_intro' => true,
            'include_conclusion' => true,
            'detailed_level' => 'high',
            'debug' => false,
        ), $options);
        
        // Use auto writer with streaming
        $result = $auto_writer->write_article_from_title_with_stream($title, $stream, $writer_options);
        
        if (!$result['success']) {
            $error = isset($result['error']) ? $result['error'] : 'Failed to write article';
            $stream->send_error($error);
            return array('success' => false, 'error' => $error);
        }
        
        // Send complete result with full content
        $result_data = array(
            'success' => true,
            'title' => $result['title'],
            'outline' => $result['outline'],
            'sections' => $result['sections'],
            'word_count' => $result['word_count'],
            'execution_time' => $result['execution_time'],
            'debug_info' => isset($result['debug_info']) ? $result['debug_info'] : array()
        );
        
        $stream->send_complete($result['full_content'], $result_data);
        
        return $result_data;
    }
    
    /**
     * Detect tools needed from prompt
     * 
     * @param string $prompt User prompt
     * @param string $title Post title (optional, defaults to prompt)
     * @return array Array of tool specifications
     */
    private function detect_tools_from_prompt($prompt, $title = '') {
        $prompt_lower = strtolower($prompt);
        $tools = array();
        
        // Use provided title or fallback to prompt
        if (empty($title)) {
            $title = $prompt;
        }
        
        // Check for post writing
        if (preg_match('/(viết|write|tạo|create).*(bài viết|post|article)/i', $prompt)) {
            $tools[] = array(
                'tool' => 'write_post',
                'params' => array(
                    'title' => $title,
                    'language' => $this->detect_language($prompt),
                    'tone' => 'professional'
                )
            );
        }
        
        // Check for image creation
        if (preg_match('/(tạo|create|thêm|add).*(ảnh|image|hình|picture)/i', $prompt)) {
            $tools[] = array(
                'tool' => 'create_image',
                'params' => array(
                    'prompt' => $title,
                    'title' => $title
                )
            );
        }
        
        // If we have content, check for WordPress post creation
        if (!empty($tools)) {
            // Manual post creation is now preferred. 
            // We do NOT add the wordpress_post tool automatically anymore.
            // The user will see the content and click "Insert to Editor".
        }
        
        return $tools;
    }
    
    /**
     * Extract categories from prompt
     * 
     * @param string $prompt Prompt text
     * @return array Categories
     */
    private function extract_categories($prompt) {
        $categories = array();
        
        // Look for "category X" or "danh mục X"
        if (preg_match('/(category|danh mục|chuyên mục)[:\s]+([^,\.]+)/iu', $prompt, $matches)) {
            $cats = preg_split('/[,;và]/', $matches[2]);
            foreach ($cats as $cat) {
                $categories[] = trim($cat);
            }
        }
        
        return $categories;
    }
    
    /**
     * Extract tags from prompt
     * 
     * @param string $prompt Prompt text
     * @return array Tags
     */
    private function extract_tags($prompt) {
        $tags = array();
        
        // Look for "tags X" or "thẻ X"
        if (preg_match('/(tags?|thẻ)[:\s]+([^,\.]+)/iu', $prompt, $matches)) {
            $tag_list = preg_split('/[,;]/', $matches[2]);
            foreach ($tag_list as $tag) {
                $tags[] = trim($tag);
            }
        }
        
        return $tags;
    }
    
    /**
     * Detect language from prompt
     * 
     * @param string $prompt Prompt text
     * @return string Language name
     */
    private function detect_language($prompt)
    {
        $patterns = [
            'Vietnamese' => '/[àáạảãăắằẳẵặâấầẩẫậèéẹẻẽêếềểễệìíịỉĩòóọỏõôốồổỗộơớờởỡợùúụủũưứừửữựỳýỵỷỹđ]/u',

            // Chinese (Han)
            'Chinese' => '/[\x{4E00}-\x{9FFF}]/u',

            // Japanese Hiragana + Katakana + Kanji
            'Japanese' => '/[\x{3040}-\x{309F}\x{30A0}-\x{30FF}\x{4E00}-\x{9FFF}]/u',

            // Korean Hangul
            'Korean' => '/[\x{AC00}-\x{D7A3}]/u',

            // Thai
            'Thai' => '/[\x{0E00}-\x{0E7F}]/u',

            // Russian Cyrillic
            'Russian' => '/[\x{0400}-\x{04FF}]/u',

            // Arabic
            'Arabic' => '/[\x{0600}-\x{06FF}]/u',

            // Hindi / Devanagari
            'Hindi' => '/[\x{0900}-\x{097F}]/u',

            // Hebrew
            'Hebrew' => '/[\x{0590}-\x{05FF}]/u',

            // Greek
            'Greek' => '/[\x{0370}-\x{03FF}]/u',
        ];

        foreach ($patterns as $lang => $regex) {
            if (preg_match($regex, $prompt)) {
                return $lang;
            }
        }

        // Default → English
        return 'English';
    }

    
    /**
     * Compile tool results into final message
     * 
     * @param array $results Tool results
     * @param string $prompt Original prompt
     * @return string Compiled result
     */
    private function compile_tool_results($results, $prompt) {
        $message = "";
        
        if (isset($results['write_post'])) {
            // If we have an article, just return the content directly!
            // The frontend will handle the display and 'Insert' button.
            // We can prefix with title if needed, but usually the content has H1.
            return $results['write_post']['content'];
        }
        
        $message = "Completed your request:\n\n";
        
        if (isset($results['create_image'])) {
            $message .= "✅ Created image\n\n";
        }
        
        if (isset($results['wordpress_post'])) {
            $post_data = $results['wordpress_post'];
            $message .= "✅ WordPress post created (ID: {$post_data['post_id']})\n";
            $message .= "   Status: {$post_data['status']}\n";
            $message .= "   URL: {$post_data['post_url']}\n";
            $message .= "   Edit: {$post_data['edit_url']}\n";
        }
        
        return $message;
    }
    
    /**
     * AJAX callback for executing with SSE stream
     */
    public function ajax_execute_with_stream() {
        // Verify nonce
        check_ajax_referer('aiautotool_nonce', 'security');
        
        // Check permissions
        if (!current_user_can('edit_posts')) {
            wp_die('Permission denied', 403);
        }
        
        // Get prompt from POST
        $prompt = isset($_POST['prompt']) ? sanitize_textarea_field($_POST['prompt']) : '';
        
        if (empty($prompt)) {
            wp_send_json_error('Prompt is required');
            return;
        }
        
        // Get title from POST (or use prompt as fallback)
        $title = isset($_POST['title']) ? sanitize_text_field($_POST['title']) : $prompt;
        
        // Load SSE Stream class
        require_once plugin_dir_path(__FILE__) . '../../lib/aiautotool-sse-stream.php';
        
        // Create stream
        $stream = new AIAutoTool_SSE_Stream();
        $stream->start();
        
        try {
            // Execute with stream
            $this->execute_with_stream($prompt, $stream, array(), $title);
            
        } catch (Exception $e) {
            $stream->send_error($e->getMessage());
        }
        
        // Close stream
        $stream->close();
    }

    /**
     * Write post with comprehensive analysis
     * 
     * @param string $title Post title
     * @param string $lang Language
     * @param string $model Model to use
     * @param array $options Additional options
     * @param callable $callback Callback function for progress updates
     * @return array Result with content and metadata
     */
    public function write_post_with_analysis($title, $lang, $model, $options = array(), $callback = null) {
        $result = array(
            'success' => false,
            'content' => '',
            'steps' => array()
        );

        // Helper to report progress
        $report_progress = function($step, $status, $message, $data = null, $duration = null) use ($callback) {
            if (is_callable($callback)) {
                call_user_func($callback, array(
                    'step' => $step,
                    'status' => $status,
                    'message' => $message,
                    'data' => $data,
                    'duration' => $duration
                ));
            }
        };

        try {
            // Step 1: Generate Checklist
            #$report_progress(1, 'start', 'Generating checklist...');
            $start_time = microtime(true);
            $checklist = $this->step_analyze_topic($title, $lang, $model, $report_progress);
            $duration = round(microtime(true) - $start_time, 2);
            
            if (!$checklist['success']) {
                throw new Exception(isset($checklist['error']) ? $checklist['error'] : (isset($checklist['msg']) ? $checklist['msg'] : 'Failed to generate checklist'));
            }
            
            $checklist_text = $checklist['content'];
            $report_progress(1, 'complete', $checklist_text, $checklist_text, $duration);
            
            // Extract keywords, content direction, and author credibility from topic analysis JSON
            $keywords_text = '';
            $direction_text = '';
            $credibility_text = '';
            $clean_checklist = strip_tags($checklist_text);
            if (preg_match('/\{[\s\S]*"keywords"[\s\S]*\}/U', $clean_checklist, $json_match)) {
                $json_str = $json_match[0];
                $json_data = json_decode($json_str, true);
                if ($json_data) {
                    // Extract keywords
                    if (isset($json_data['keywords'])) {
                        $keywords_array = array();
                        if (isset($json_data['keywords']['main_keywords']) && is_array($json_data['keywords']['main_keywords'])) {
                            $keywords_array = array_merge($keywords_array, $json_data['keywords']['main_keywords']);
                        }
                        if (isset($json_data['keywords']['secondary_keywords']) && is_array($json_data['keywords']['secondary_keywords'])) {
                            $keywords_array = array_merge($keywords_array, $json_data['keywords']['secondary_keywords']);
                        }
                        if (isset($json_data['keywords']['entities']) && is_array($json_data['keywords']['entities'])) {
                            $keywords_array = array_merge($keywords_array, $json_data['keywords']['entities']);
                        }
                        $keywords_text = implode("\n", $keywords_array);
                    }
                    
                    // Extract content direction
                    if (isset($json_data['content_direction'])) {
                        $direction_parts = array();
                        if (isset($json_data['content_direction']['article_structure'])) {
                            $direction_parts[] = "Article Structure: " . $json_data['content_direction']['article_structure'];
                        }
                        if (isset($json_data['content_direction']['main_points']) && is_array($json_data['content_direction']['main_points'])) {
                            $direction_parts[] = "Main Points:\n- " . implode("\n- ", $json_data['content_direction']['main_points']);
                        }
                        if (isset($json_data['content_direction']['style_and_tone'])) {
                            $direction_parts[] = "Style and Tone: " . $json_data['content_direction']['style_and_tone'];
                        }
                        if (isset($json_data['content_direction']['length_and_format'])) {
                            $direction_parts[] = "Length and Format: " . $json_data['content_direction']['length_and_format'];
                        }
                        $direction_text = implode("\n\n", $direction_parts);
                    }
                    
                    // Extract author credibility
                    if (isset($json_data['author_credibility'])) {
                        $credibility_text = $json_data['author_credibility'];
                    }
                }
            }
            
            // Step 2: Related Posts (Internal Linking) - renumbered from step 3
            // This is optional based on options
            $auto_internal_links = isset($options['auto_internal_links']) ? $options['auto_internal_links'] : true;
            $related_posts_info = '';
            
            if ($auto_internal_links) {
                $report_progress(2, 'start', 'Finding internal links...');
                $start_time = microtime(true);
                // We need to implement this or pass it in if it depends on WP_Query which might not be fully available context-wise
                // For now assuming we can run WP_Query
                $related_posts = $this->step_find_internal_links($title, $keywords_text, $lang);
                $duration = round(microtime(true) - $start_time, 2);
                
                if (!empty($related_posts)) {
                    $related_posts_info = $this->format_related_posts_for_prompt($related_posts);
                    $report_progress(2, 'complete', $related_posts_info, $related_posts, $duration);
                } else {
                    $report_progress(2, 'complete', 'No internal links found', null, $duration);
                }
            } else {
                $report_progress(2, 'skipped', 'Internal links disabled');
            }
            
            // Step 4: Generate Prompts for Sections - renumbered from step 5
            $report_progress(4, 'start', 'Generating section prompts...');
            $start_time = microtime(true);
            $sections = $this->step_generate_section_prompts($title, $checklist_text, $direction_text, $lang, $model);
            $duration = round(microtime(true) - $start_time, 2);
            
            // Create HTML task list with checkboxes
            $task_list_html = '<div class="section-task-list" style="padding: 15px; background: #f8f9fa; border-radius: 5px; margin: 10px 0;">';
            $task_list_html .= '<div style="font-weight: bold; margin-bottom: 10px; color: #333;">📝 Sections to Write:</div>';
            $task_list_html .= '<ul style="list-style: none; padding: 0; margin: 0;">';
            
            foreach ($sections as $index => $section) {
                $section_id = 'section-task-' . $index;
                $task_list_html .= '<li id="' . $section_id . '" style="padding: 8px 0; border-bottom: 1px solid #e0e0e0; display: flex; align-items: center;">';
                $task_list_html .= '<span class="task-checkbox" style="display: inline-block; width: 20px; height: 20px; border: 2px solid #ccc; border-radius: 3px; margin-right: 10px; text-align: center; line-height: 18px; background: white;"></span>';
                $task_list_html .= '<span class="task-name" style="color: #666;">' . htmlspecialchars($section['name']) . '</span>';
                $task_list_html .= '</li>';
            }
            
            $task_list_html .= '</ul>';
            $task_list_html .= '</div>';
            
            $report_progress(4, 'complete', $task_list_html, $sections, $duration);
            
            // Step 5: Write Article - renumbered from step 6
            // $report_progress(5, 'start', 'Writing article...');
            
            $article_content = '';
            $previous_section_ending = '';
            $total_sections = count($sections);
            
            foreach ($sections as $index => $section) {
                $report_progress(5, 'writing_section', "Writing section " . ($index + 1) . "/$total_sections: " . $section['name']);
                $start_time = microtime(true);
                
                $section_content = $this->step_write_section(
                    $section,
                    $previous_section_ending, 
                    $title,
                    $checklist_text,
                    $keywords_text,
                    $direction_text,
                    $credibility_text,
                    $related_posts_info,
                    $lang, 
                    $model,
                    $options,
                    $report_progress
                );
                
                $duration = round(microtime(true) - $start_time, 2);
                
                if (!$section_content['success']) {
                    $error_msg = isset($section_content['error']) ? $section_content['error'] : 'Unknown error';
                    throw new Exception("Failed to write section {$section['name']}: " . $error_msg);
                }
                
                $section_text = $section_content['content'];
                
                // Image search and insertion
                if (isset($options['auto_images']) && $options['auto_images']) {
                    $this->search_and_insert_image($section_text, $section['name'], $lang);
                }
                
                // Add to total content
                $article_content .= $section_text . "\n\n";
                
                // Extract ending for next section context (last 1500 chars)
                $previous_section_ending = mb_substr(strip_tags($section_text), -1500);
                
                $report_progress(5, 'section_complete', "Section " . ($index + 1) . " completed", array('section_text' => $section_text, 'section_index' => $index), $duration);
            }
            
            // Step 6: Generate introduction and conclusion summary (mobai and ketbai) - renumbered from step 7
            $report_progress(6, 'start', 'Generating introduction and conclusion...');
            $start_time = microtime(true);
            
            try {
                // Prepare article text for summary - convert to plain text
                $article_plain_text = $article_content;
                $article_plain_text = preg_replace('/#{1,6}\s+/', '', $article_plain_text); // Remove headers
                $article_plain_text = preg_replace('/\*\*(.*?)\*\*/', '$1', $article_plain_text); // Remove bold
                $article_plain_text = preg_replace('/\*(.*?)\*/', '$1', $article_plain_text); // Remove italic
                $article_plain_text = preg_replace('/\[([^\]]+)\]\([^\)]+\)/', '$1', $article_plain_text); // Remove links
                $article_plain_text = preg_replace('/\s+/', ' ', $article_plain_text); // Normalize whitespace
                $article_plain_text = trim($article_plain_text);
                
                // Get full article for better context (but limit to avoid token limits)
                $article_for_context = $article_plain_text;
                if (mb_strlen($article_for_context) > 4000) {
                    // Take first 2000 and last 2000 characters for better context
                    $article_for_context = mb_substr($article_for_context, 0, 2000) . ' ... ' . mb_substr($article_for_context, -2000);
                }
                
                // Create prompt to generate both mobai (introduction) and ketbai (conclusion) in JSON format
                $summary_prompt = $this->get_language_instruction_prompt($lang);
                
                if (stripos($lang, 'vietnamese') !== false || stripos($lang, 'việt') !== false || $lang === 'vi' || $lang === 'Vietnamese') {
                    $summary_prompt .= "Dựa trên nội dung bài viết sau đây, hãy tạo 2 phần:\n\n";
                    $summary_prompt .= "1. MỞ BÀI (mobai): Viết một đoạn mở bài giới thiệu ngắn gọn (3-5 câu) dựa trên các ý chính quan trọng của bài viết. Phần này sẽ được dùng để giới thiệu bài viết.\n";
                    $summary_prompt .= "2. KẾT BÀI (ketbai): Viết một đoạn tóm tắt kết luận ngắn gọn (3-5 câu) các ý chính quan trọng nhất đã được trình bày trong bài viết.\n\n";
                    $summary_prompt .= "Yêu cầu:\n";
                    $summary_prompt .= "- Mỗi phần viết 3-5 câu, ngắn gọn, súc tích, dễ hiểu\n";
                    $summary_prompt .= "- Tập trung vào những thông tin quan trọng nhất\n";
                    $summary_prompt .= "- Viết tự nhiên, không cần tiêu đề 'Mở bài', 'Kết luận' hay 'Tóm tắt'\n";
                    $summary_prompt .= "- TRẢ VỀ ĐỊNH DẠNG JSON CHÍNH XÁC với 2 key: 'mobai' và 'ketbai'\n";
                    $summary_prompt .= "- Format JSON: {\"mobai\": \"nội dung mở bài\", \"ketbai\": \"nội dung kết bài\"}\n";
                    $summary_prompt .= "- CHỈ trả về JSON, không có text thêm, không có markdown code block\n\n";
                } else {
                    $summary_prompt .= "Based on the following article content, create 2 parts:\n\n";
                    $summary_prompt .= "1. INTRODUCTION (mobai): Write a brief introduction paragraph (3-5 sentences) based on the main important points of the article. This will be used to introduce the article.\n";
                    $summary_prompt .= "2. CONCLUSION (ketbai): Write a brief conclusion summary (3-5 sentences) of the main important points presented in the article.\n\n";
                    $summary_prompt .= "Requirements:\n";
                    $summary_prompt .= "- Each part should be 3-5 sentences, concise, clear, and easy to understand\n";
                    $summary_prompt .= "- Focus on the most important information\n";
                    $summary_prompt .= "- Write naturally, no need for 'Introduction', 'Conclusion' or 'Summary' headings\n";
                    $summary_prompt .= "- RETURN EXACT JSON FORMAT with 2 keys: 'mobai' and 'ketbai'\n";
                    $summary_prompt .= "- JSON format: {\"mobai\": \"introduction content\", \"ketbai\": \"conclusion content\"}\n";
                    $summary_prompt .= "- RETURN ONLY JSON, no additional text, no markdown code block\n\n";
                }
                
                $summary_prompt .= "Article content:\n" . $article_for_context;
                
                // Generate summary using AI
                $summary_result = $this->generate_with_retry($summary_prompt, array(
                    'model' => $model,
                    'max_tokens' => 800,
                    'temperature' => 0.7,
                    'use_case' => 'fast'
                ), $report_progress);
                
                if ($summary_result['success']) {
                    $summary_response = $summary_result['content'];
                    $summary_response = trim($summary_response);
                    
                    // Try to extract JSON from response (in case it's wrapped in markdown code block or has extra text)
                    if (preg_match('/\{[\s\S]*"mobai"[\s\S]*"ketbai"[\s\S]*\}/', $summary_response, $json_match)) {
                        $summary_response = $json_match[0];
                    }
                    
                    // Remove markdown code blocks if present
                    $summary_response = preg_replace('/```json\s*/', '', $summary_response);
                    $summary_response = preg_replace('/```\s*/', '', $summary_response);
                    $summary_response = trim($summary_response);
                    
                    // Parse JSON
                    $summary_data = json_decode($summary_response, true);
                    
                    if ($summary_data && isset($summary_data['mobai']) && isset($summary_data['ketbai'])) {
                        $mobai = trim($summary_data['mobai']);
                        $ketbai = trim($summary_data['ketbai']);
                        
                        // Remove quotes if present
                        $mobai = trim($mobai, ' "\'');
                        $ketbai = trim($ketbai, ' "\'');
                        
                        if (!empty($mobai) && !empty($ketbai)) {
                            // Add mobai at the beginning of article (after title if exists, or at the start)
                            // Check if article starts with a heading (markdown ## or #)
                            if (preg_match('/^(#{1,6}\s+.+?\n\n)/', $article_content, $matches)) {
                                // Article starts with heading, add mobai after first heading
                                $article_content = preg_replace('/^(#{1,6}\s+.+?\n\n)/', '$1' . $mobai . "\n\n", $article_content, 1);
                            } else {
                                // No heading at start, add mobai at the beginning
                                $article_content = $mobai . "\n\n" . $article_content;
                            }
                            
                            // Add ketbai at the end of article
                            $article_content .= "\n\n" . $ketbai;
                            
                            $duration = round(microtime(true) - $start_time, 2);
                            $report_progress(6, 'complete', 'Introduction and conclusion added successfully', array(
                                'mobai' => $mobai,
                                'ketbai' => $ketbai
                            ), $duration);
                        } else {
                            $report_progress(6, 'warning', 'Generated summary was empty, skipping...');
                        }
                    } else {
                        $error_detail = json_last_error() !== JSON_ERROR_NONE ? json_last_error_msg() : 'Invalid JSON structure';
                        $report_progress(6, 'warning', 'Failed to parse summary JSON: ' . $error_detail);
                    }
                } else {
                    $error_msg = isset($summary_result['error']) ? $summary_result['error'] : 'Unknown error';
                    $report_progress(6, 'warning', 'Failed to generate summary: ' . $error_msg);
                }
            } catch (Exception $summary_ex) {
                $report_progress(6, 'warning', 'Error generating summary: ' . $summary_ex->getMessage());
            }
            
            $result['success'] = true;
            $result['content'] = $article_content;
            $report_progress(7, 'finish', 'Article generation completed');
            
        } catch (Exception $e) {
            $result['success'] = false;
            $result['error'] = $e->getMessage();
            $report_progress(99, 'error', $e->getMessage());
        }
        
        return $result;
    }

    /**
     * Generate content with retry mechanism
     * 
     * @param string $prompt Prompt to generate
     * @param array $options Generation options
     * @param callable $callback Progress callback
     * @return array Generation result
     */
    private function generate_with_retry($prompt, $options, $callback = null) {
        $attempt = 1;
        while (true) {
            try {
                $result = $this->generate($prompt, $options);
                
                if ($result['success']) {
                    return $result;
                } else {
                    $error = isset($result['error']) ? $result['error'] : 'Unknown error';
                    if (is_callable($callback)) {
                        call_user_func($callback, 0, 'status', "Error: {$error}. Retrying step in 10s...");
                    }
                    sleep(10);
                }
            } catch (Exception $e) {
                if (is_callable($callback)) {
                    call_user_func($callback, 0, 'status', "Error: " . $e->getMessage() . ". Retrying step in 10s...");
                }
                sleep(10);
            }
            $attempt++;
        }
    }
    
    /**
     * Step 1: Analyze Topic and Generate Author Credibility
     * Combined step to reduce API calls and execution time
     */
    private function step_analyze_topic($title, $lang, $model, $callback = null) {
        // Get author information if available
        $author_name = '';
        $author_bio = '';
        if (function_exists('wp_get_current_user')) {
            $current_user = wp_get_current_user();
            if ($current_user && $current_user->ID > 0) {
                $author_name = $current_user->display_name;
                $author_bio = get_user_meta($current_user->ID, 'description', true);
            }
        }
        
        $prompt = $this->get_language_instruction_prompt($lang);
        $prompt .= "You are an SEO Content Author with deep understanding of user intent and search behavior.\n\n";
        $prompt .= "Your task: Analyze the topic based on the provided **title** and determine the content direction, AND generate author credibility information.\n\n";
        $prompt .= "Input:\n\n";
        $prompt .= "- title: \"{$title}\"\n";
        if (!empty($author_name)) {
            $prompt .= "- author_name: \"{$author_name}\"\n";
        }
        if (!empty($author_bio)) {
            $prompt .= "- author_bio: \"{$author_bio}\"\n";
        }
        $prompt .= "\n";
        
        $prompt .= "Output:\n\n";
        $prompt .= "Provide a structured analysis including:\n\n";
        $prompt .= "1. **User Intent Analysis**\n\n";
        $prompt .= "   - Người tìm kiếm với tiêu đề này đang muốn điều gì?\n\n";
        $prompt .= "   - Họ gặp vấn đề, nỗi đau, thắc mắc gì?\n\n";
        $prompt .= "   - Mục đích của họ là: tìm hiểu, so sánh, mua hàng, hay giải pháp?\n\n";
        $prompt .= "2. **Search Intent Classification**\n\n";
        $prompt .= "   - Phân loại theo 3 nhóm:\n\n";
        $prompt .= "     - Informational (tìm hiểu)\n\n";
        $prompt .= "     - Commercial Investigation (cân nhắc)\n\n";
        $prompt .= "     - Transactional (muốn mua)\n\n";
        $prompt .= "   - Giải thích lý do chọn loại này.\n\n";
        $prompt .= "3. **What Users Expect From This Article**\n\n";
        $prompt .= "   - Danh sách 5–10 thông tin, câu trả lời hoặc nội dung mà người dùng mong đợi.\n\n";
        $prompt .= "   - Điều gì khiến họ hài lòng sau khi đọc?\n\n";
        $prompt .= "4. **What We Should Provide**\n\n";
        $prompt .= "   - Những mục nội dung cần có trong bài viết để thoả mãn user intent.\n\n";
        $prompt .= "   - Insight đặc biệt mà đối thủ thường thiếu.\n\n";
        $prompt .= "   - Nội dung cần ưu tiên + về lý do.\n\n";
        $prompt .= "5. **SEO Opportunities**\n\n";
        $prompt .= "   - Gợi ý LSI keywords, entity liên quan.\n\n";
        $prompt .= "   - Gợi ý schema nên dùng.\n\n";
        $prompt .= "   - Định hướng cấu trúc bài chuẩn SEO.\n\n";
        $prompt .= "6. **Keywords Analysis**\n\n";
        $prompt .= "   - 10-15 từ khóa chính (main keywords) liên quan đến chủ đề.\n\n";
        $prompt .= "   - Từ khóa phụ và LSI keywords (Latent Semantic Indexing).\n\n";
        $prompt .= "   - Các entity và thuật ngữ quan trọng cần sử dụng.\n\n";
        $prompt .= "7. **Content Direction**\n\n";
        $prompt .= "   - Article structure: Cấu trúc bài viết tối ưu (intro, body sections, conclusion)\n\n";
        $prompt .= "   - Content main points: Các điểm chính cần đề cập\n\n";
        $prompt .= "   - Style and tone: Phong cách và giọng điệu phù hợp (formal, conversational, technical, etc.)\n\n";
        $prompt .= "   - Length and format: Độ dài và định dạng đề xuất (short-form, long-form, listicle, how-to, etc.)\n\n";
        $prompt .= "8. **Author Credibility**\n\n";
        $prompt .= "   - Based on the topic and author information provided, create author credibility information to establish trust.\n\n";
        $prompt .= "   - Include relevant expertise, experience, or qualifications that make the author credible for this topic.\n\n";
        $prompt .= "   - Keep it concise and natural (2-3 sentences).\n\n";
        $prompt .= "   - If no author information is provided, create a generic credibility statement based on the topic.\n\n";
        $prompt .= "Hãy trình bày phân tích một cách logic, có chiều sâu, theo phong cách tác giả chuyên nghiệp.\n\n";
        $prompt .= "IMPORTANT: Return the analysis in JSON format only. Keep responses concise and structured. Use this JSON structure:\n";
        $prompt .= "{\n";
        $prompt .= "  \"user_intent\": {\"what_they_want\": \"\", \"problems\": \"\", \"purpose\": \"\"},\n";
        $prompt .= "  \"search_intent\": {\"type\": \"\", \"reason\": \"\"},\n";
        $prompt .= "  \"user_expectations\": [],\n";
        $prompt .= "  \"content_to_provide\": {\"required_sections\": [], \"unique_insights\": \"\", \"priorities\": \"\"},\n";
        $prompt .= "  \"seo_opportunities\": {\"lsi_keywords\": [], \"schema\": \"\", \"structure\": \"\"},\n";
        $prompt .= "  \"keywords\": {\"main_keywords\": [], \"secondary_keywords\": [], \"entities\": []},\n";
        $prompt .= "  \"content_direction\": {\"article_structure\": \"\", \"main_points\": [], \"style_and_tone\": \"\", \"length_and_format\": \"\"},\n";
        $prompt .= "  \"author_credibility\": \"\"\n";
        $prompt .= "}\n\n";

        return $this->generate_with_retry($prompt, array(
            'model' => $model,
            'max_tokens' => 3000,
            'temperature' => 0.7,
            'use_case' => 'reasoning'
        ), $callback);
    }
    
    /**
     * Step 2: Generate Credibility
     */
    /**
     * Step 2: Generate Credibility
     */
    private function step_generate_credibility($checklist, $author_name, $bio, $lang, $model, $callback = null) {
        $prompt = $this->get_language_instruction_prompt($lang);
        $prompt .= "Based on the checklist below, create author credibility information to establish credibility for the article.\n";
        $prompt .= "Checklist:\n{$checklist}\n\n";
        $prompt .= "Author name: {$author_name}\n";
        $prompt .= "Author bio: {$bio}\n\n";
        $prompt .= "ONLY RETURN THE NECESSARY INFORMATION in text format. DO NOT ADD ANY DESCRIPTION OR INTRO.\n";
        
        return $this->generate_with_retry($prompt, array(
            'model' => $model,
            'max_tokens' => 500,
            'temperature' => 0.7
        ), $callback);
    }

    /**
     * Step 3: Analyze Keywords
     */
    /**
     * Step 3: Analyze Keywords
     */
    private function step_analyze_keywords($title, $checklist, $credibility, $lang, $model, $callback = null) {
        // Summarize inputs to save tokens
        $checklist_summary = mb_substr(strip_tags($checklist), 0, 500);
        $credibility_summary = mb_substr(strip_tags($credibility), 0, 300);
        
        $prompt = $this->get_language_instruction_prompt($lang);
        $prompt .= "Create a list of necessary keywords for the article.\n";
        $prompt .= "Title: {$title}\n";
        $prompt .= "Context: {$checklist_summary}\n";
        $prompt .= "Credibility: {$credibility_summary}\n\n";
        $prompt .= "Requirements:\n1. 10-15 main keywords\n2. Secondary keywords and LSI\n";
        $prompt .= "ONLY RETURN KEYWORDS. NO EXTRA TEXT.\n";
        
        return $this->generate_with_retry($prompt, array(
            'model' => $model,
            'max_tokens' => 800,
            'temperature' => 0.7
        ), $callback);
    }
    
    /**
     * Step 4: Determine Direction
     * @deprecated This step has been merged into step_analyze_topic for better efficiency
     * Content direction is now extracted from the analysis JSON in step 1
     */
    /**
     * Step 4: Determine Direction
     * @deprecated This step has been merged into step_analyze_topic for better efficiency
     */
    private function step_determine_direction($title, $checklist, $credibility, $keywords, $lang, $model, $callback = null) {
         $prompt = $this->get_language_instruction_prompt($lang);
         $prompt .= "Determine the content direction for the article.\n";
         $prompt .= "Title: {$title}\n";
         $prompt .= "Keywords: " . mb_substr(strip_tags($keywords), 0, 300) . "\n\n";
         $prompt .= "Requirements:\n1. Article structure\n2. Content main points\n3. Style and tone\n4. Length and format\n";
         $prompt .= "ONLY RETURN THE CONTENT DIRECTION TEXT.\n";
         
         return $this->generate_with_retry($prompt, array(
            'model' => $model,
            'max_tokens' => 1000,
            'temperature' => 0.7
        ), $callback);
    }
    
    /**
     * Step 5: Find Internal Links
     */
    private function step_find_internal_links($title, $keywords_text, $lang) {
        // This is a simplified version of what's in singleai.php
        // In a real agent class, we should probably dependency inject the searcher or use a separate service
        // For now, if we are in WP context, we can use WP_Query
        
        if (!function_exists('get_posts')) return array();
        
        // Extract some keywords
        $keywords = array_slice(explode("\n", strip_tags($keywords_text)), 0, 3);
        $search_query = implode(' ', $keywords);
        if (empty($search_query)) $search_query = $title;

        $args = array(
            'post_type' => 'post',
            'posts_per_page' => 5,
            'post_status' => 'publish',
            's' => $search_query,
            'orderby' => 'relevance'
        );
        
        $query = new WP_Query($args);
        $posts = array();
        
        if ($query->have_posts()) {
            while ($query->have_posts()) {
                $query->the_post();
                $posts[] = array(
                    'title' => get_the_title(),
                    'url' => get_permalink(),
                    'excerpt' => get_the_excerpt()
                );
            }
            wp_reset_postdata();
        }
        
        return $posts;
    }
    
    private function format_related_posts_for_prompt($posts) {
        $output = "Related Posts for Internal Linking:\n";
        foreach ($posts as $p) {
            $output .= "- [{$p['title']}]({$p['url']})\n";
        }
        $output .= "IMPORTANT: Naturally insert 2-3 links to these posts where relevant.\n";
        return $output;
    }
    
    /**
     * Step 6: Generate Section Prompts
     */
    private function step_generate_section_prompts($title, $checklist, $direction, $lang, $model) {
        // Extract sections from checklist JSON if possible
        $sections = array();
        
        // Remove HTML tags first to get clean text
        $clean_checklist = strip_tags($checklist);
        
        // Try multiple methods to extract JSON
        $json = null;
        
        // Method 1: Try to find JSON in code blocks (```json ... ``` or ``` ... ```)
        if (preg_match('/```(?:json)?\s*(\{)/s', $clean_checklist, $matches, PREG_OFFSET_CAPTURE)) {
            $start_pos = $matches[1][1];
            $brace_count = 0;
            $end_pos = $start_pos;
            
            // Find the matching closing brace
            for ($i = $start_pos; $i < strlen($clean_checklist); $i++) {
                if ($clean_checklist[$i] === '{') {
                    $brace_count++;
                } elseif ($clean_checklist[$i] === '}') {
                    $brace_count--;
                    if ($brace_count === 0) {
                        $end_pos = $i;
                        break;
                    }
                }
            }
            
            if ($brace_count === 0 && $end_pos > $start_pos) {
                $json_str = substr($clean_checklist, $start_pos, $end_pos - $start_pos + 1);
                $json = json_decode(trim($json_str), true);
            }
        }
        
        // Method 2: Try to find JSON object with balanced braces
        if (!$json || json_last_error() !== JSON_ERROR_NONE) {
            // Find the first opening brace
            $start_pos = strpos($clean_checklist, '{');
            if ($start_pos !== false) {
                $brace_count = 0;
                $end_pos = $start_pos;
                
                // Find the matching closing brace
                for ($i = $start_pos; $i < strlen($clean_checklist); $i++) {
                    if ($clean_checklist[$i] === '{') {
                        $brace_count++;
                    } elseif ($clean_checklist[$i] === '}') {
                        $brace_count--;
                        if ($brace_count === 0) {
                            $end_pos = $i;
                            break;
                        }
                    }
                }
                
                if ($brace_count === 0 && $end_pos > $start_pos) {
                    $json_str = substr($clean_checklist, $start_pos, $end_pos - $start_pos + 1);
                    $json = json_decode($json_str, true);
                }
            }
        }
        
        // Method 3: Try to find JSON by looking for "content_to_provide" key
        if (!$json || json_last_error() !== JSON_ERROR_NONE) {
            if (preg_match('/"content_to_provide"\s*:\s*\{[^}]*"required_sections"\s*:\s*\[([^\]]+)\]/s', $clean_checklist, $matches)) {
                // Try to extract the full JSON object containing this
                $before = strrpos($clean_checklist, '{', strpos($clean_checklist, '"content_to_provide"'));
                if ($before !== false) {
                    $brace_count = 0;
                    $end_pos = $before;
                    for ($i = $before; $i < strlen($clean_checklist); $i++) {
                        if ($clean_checklist[$i] === '{') {
                            $brace_count++;
                        } elseif ($clean_checklist[$i] === '}') {
                            $brace_count--;
                            if ($brace_count === 0) {
                                $end_pos = $i;
                                break;
                            }
                        }
                    }
                    if ($brace_count === 0 && $end_pos > $before) {
                        $json_str = substr($clean_checklist, $before, $end_pos - $before + 1);
                        $json = json_decode($json_str, true);
                    }
                }
            }
        }
        
        // Method 4: Try to decode the entire checklist as JSON (in case it's pure JSON)
        if (!$json || json_last_error() !== JSON_ERROR_NONE) {
            $json = json_decode($clean_checklist, true);
        }
        
        // Extract sections from parsed JSON
        if ($json && is_array($json) && json_last_error() === JSON_ERROR_NONE) {
            if (isset($json['content_to_provide']['required_sections']) && 
                is_array($json['content_to_provide']['required_sections']) && 
                !empty($json['content_to_provide']['required_sections'])) {
                $sections = array_filter(
                    array_map('trim', $json['content_to_provide']['required_sections']),
                    function($section) {
                        return !empty($section) && is_string($section);
                    }
                );
                $sections = array_values($sections); // Re-index array
            }
        }
        
        // Debug logging
        if (defined('WP_DEBUG') && WP_DEBUG) {
            error_log("=== AI AGENT DEBUG: step_generate_section_prompts ===");
            error_log("Checklist preview: " . mb_substr($clean_checklist, 0, 200));
            error_log("JSON found: " . ($json ? 'Yes' : 'No'));
            error_log("JSON error: " . json_last_error_msg());
            error_log("Sections extracted: " . count($sections));
            if (!empty($sections)) {
                error_log("Section names: " . implode(', ', $sections));
            }
        }
        
        if (empty($sections)) {
            $sections = array('Introduction', 'Main Content', 'Conclusion');
        }
        
        // Generate detailed prompt for each section to ensure content consistency
        $prompts = array();
        foreach ($sections as $i => $section_name) {
            // Create AI prompt to generate section-specific guidance
            $section_prompt = $this->get_language_instruction_prompt($lang);
            $section_prompt .= "You are an SEO Content Strategist creating detailed writing guidance for a specific section.\n\n";
            $section_prompt .= "=== ARTICLE CONTEXT ===\n";
            $section_prompt .= "Title: {$title}\n";
            $section_prompt .= "Section Name: {$section_name}\n";
            $section_prompt .= "Section Position: " . ($i + 1) . " of " . count($sections) . "\n";
            $section_prompt .= "Is First Section: " . ($i === 0 ? 'Yes' : 'No') . "\n";
            $section_prompt .= "Is Last Section: " . ($i === count($sections) - 1 ? 'Yes' : 'No') . "\n\n";
            
            $section_prompt .= "=== OVERALL ANALYSIS ===\n";
            $section_prompt .= mb_substr(strip_tags($checklist), 0, 1000) . "\n\n";
            
            $section_prompt .= "=== CONTENT DIRECTION ===\n";
            $section_prompt .= mb_substr(strip_tags($direction), 0, 500) . "\n\n";
            
            $section_prompt .= "=== YOUR TASK ===\n";
            $section_prompt .= "Create a detailed writing prompt for this section that includes:\n";
            $section_prompt .= "1. **Main Objective**: What this section should accomplish\n";
            $section_prompt .= "2. **Key Points**: 3-5 specific points that MUST be covered\n";
            $section_prompt .= "3. **Content Focus**: What the reader should learn/understand\n";
            $section_prompt .= "4. **Tone & Style**: How to write this section\n";
            $section_prompt .= "5. **Structure Guidance**: Recommended format (paragraphs, lists, etc.)\n\n";
            
            if ($i === 0) {
                $section_prompt .= "IMPORTANT: This is the INTRODUCTION. Include guidance for:\n";
                $section_prompt .= "- Hook to grab attention\n";
                $section_prompt .= "- Problem statement\n";
                $section_prompt .= "- What the article will cover\n";
                $section_prompt .= "- Why the reader should continue reading\n\n";
            } elseif ($i === count($sections) - 1) {
                $section_prompt .= "IMPORTANT: This is the CONCLUSION. Include guidance for:\n";
                $section_prompt .= "- Summary of key takeaways\n";
                $section_prompt .= "- Actionable next steps\n";
                $section_prompt .= "- Call-to-action\n";
                $section_prompt .= "- Final thought or encouragement\n\n";
            }
            
            $section_prompt .= "Return ONLY the detailed writing prompt in plain text format. Be specific and comprehensive.\n";
            
            // Generate the section prompt using AI
            $generated_prompt = $this->generate_with_retry($section_prompt, array(
                'model' => $model,
                'max_tokens' => 1000,
                'temperature' => 0.7
            ));
            
            $detailed_prompt = '';
            if ($generated_prompt['success']) {
                $detailed_prompt = $generated_prompt['content'];
            } else {
                // Fallback to basic prompt if generation fails
                $detailed_prompt = "Write the {$section_name} section covering the main points related to {$title}.";
            }
            
            $prompts[] = array(
                'name' => $section_name,
                'index' => $i,
                'is_first' => ($i === 0),
                'is_last' => ($i === count($sections) - 1),
                'prompt' => $detailed_prompt  // Add the generated detailed prompt
            );
        }
        
        return $prompts;
    }
    
    /**
     * Step 7: Write Section
     */
    /**
     * Step 7: Write Section
     */
    private function step_write_section($section, $prev_ending, $title, $checklist, $keywords, $direction, $credibility, $internal_links, $lang, $model, $options, $callback = null) {
        $max_retries = 3;
        $attempt = 0;
        $validation_feedback = '';
        
        while ($attempt < $max_retries) {
            $attempt++;
            
            // Debug: Log section information
            if (defined('WP_DEBUG') && WP_DEBUG) {
                error_log("=== AI AGENT DEBUG: step_write_section (Attempt {$attempt}/{$max_retries}) ===");
                error_log("Section Name: " . (isset($section['name']) ? $section['name'] : 'N/A'));
                error_log("Section Index: " . (isset($section['index']) ? $section['index'] : 'N/A'));
                error_log("Is First Section: " . (isset($section['is_first']) && $section['is_first'] ? 'Yes' : 'No'));
                error_log("Title: {$title}");
                error_log("Language: {$lang}");
                error_log("Model: {$model}");
                error_log("Has Section Prompt: " . (isset($section['prompt']) && !empty($section['prompt']) ? 'Yes' : 'No'));
                error_log("Has Previous Ending: " . (!empty($prev_ending) ? 'Yes' : 'No'));
                error_log("Has Validation Feedback: " . (!empty($validation_feedback) ? 'Yes' : 'No'));
            }
            
            $prompt = $this->get_language_instruction_prompt($lang);
            
            $prompt .= "You are writing a section of an SEO-optimized article.\n\n";
            $prompt .= "=== ARTICLE INFORMATION ===\n";
            $prompt .= "Title: {$title}\n";
            $prompt .= "Section to write: {$section['name']}\n\n";
            
            // Add validation feedback if this is a retry
            if (!empty($validation_feedback) && $attempt > 1) {
                $prompt .= "=== PREVIOUS ATTEMPT FEEDBACK ===\n";
                $prompt .= "⚠️ The previous version had issues. Please address these:\n";
                $prompt .= $validation_feedback . "\n\n";
                $prompt .= "CRITICAL: You MUST fix these issues in this version.\n\n";
            }
            
            // Use the pre-generated detailed section prompt from step 6
            if (isset($section['prompt']) && !empty($section['prompt'])) {
                $prompt .= "=== SECTION WRITING GUIDANCE ===\n";
                $prompt .= $section['prompt'] . "\n\n";
                
                // Debug: Log section prompt preview
                if (defined('WP_DEBUG') && WP_DEBUG) {
                    $prompt_preview = mb_substr($section['prompt'], 0, 200);
                    error_log("Section Prompt Preview: " . $prompt_preview . "...");
                }
            }
            
            // Add context from previous section for continuity
            if (!$section['is_first'] && !empty($prev_ending)) {
                $prompt .= "=== PREVIOUS SECTION CONTEXT ===\n";
                $prompt .= "Previous section ending: ...{$prev_ending}\n";
                $prompt .= "Continue seamlessly from this context to maintain flow.\n\n";
                
                // Debug: Log previous ending preview
                if (defined('WP_DEBUG') && WP_DEBUG) {
                    $ending_preview = mb_substr($prev_ending, 0, 150);
                    error_log("Previous Section Ending Preview: ..." . $ending_preview . "...");
                }
            }
            
            // Add SEO keywords for optimization
            $prompt .= "=== SEO KEYWORDS ===\n";
            $prompt .= "Primary Keywords: " . mb_substr(strip_tags($keywords), 0, 300) . "\n";
            $prompt .= "Naturally incorporate these keywords without keyword stuffing.\n\n";
            
            // Debug: Log keywords preview
            if (defined('WP_DEBUG') && WP_DEBUG && !empty($keywords)) {
                $keywords_preview = mb_substr(strip_tags($keywords), 0, 150);
                error_log("Keywords Preview: " . $keywords_preview . "...");
            }
            
            // Add credibility info if available
            if (!empty($credibility)) {
                $prompt .= "=== AUTHOR CREDIBILITY ===\n";
                $prompt .= mb_substr(strip_tags($credibility), 0, 200) . "\n\n";
                
                // Debug: Log credibility preview
                if (defined('WP_DEBUG') && WP_DEBUG) {
                    $credibility_preview = mb_substr(strip_tags($credibility), 0, 100);
                    error_log("Credibility Preview: " . $credibility_preview . "...");
                }
            }
            
            // Add internal links if available
            if (!empty($internal_links)) {
                $prompt .= "=== INTERNAL LINKING ===\n";
                $prompt .= $internal_links . "\n\n";
                
                // Debug: Log internal links preview
                if (defined('WP_DEBUG') && WP_DEBUG) {
                    $links_preview = mb_substr($internal_links, 0, 150);
                    error_log("Internal Links Preview: " . $links_preview . "...");
                }
            }
            
            $prompt .= "=== WRITING REQUIREMENTS ===\n";
            $prompt .= "1. Format: Use Markdown with proper heading hierarchy (h2, h3)\n";
            $prompt .= "2. Tone: Professional yet engaging and conversational\n";
            $prompt .= "3. Structure: \n";
            $prompt .= "   - Use short paragraphs (2-3 sentences max)\n";
            $prompt .= "   - Include bullet points or numbered lists where appropriate\n";
            $prompt .= "   - Add examples, statistics, or case studies if relevant\n";
            $prompt .= "4. SEO: Naturally incorporate keywords without keyword stuffing\n";
            $prompt .= "5. User Focus: Address the user's intent and expectations\n";
            $prompt .= "6. Length: Comprehensive but concise (aim for 400-800 words for this section)\n\n";
            
            $prompt .= "IMPORTANT: Follow the section guidance above precisely. Every paragraph should serve the user's needs.\n\n";
            $prompt .= "Now write the section content:\n";
            
            // Debug: Log full prompt preview
            if (defined('WP_DEBUG') && WP_DEBUG) {
                $full_prompt_preview = mb_substr($prompt, 0, 500);
                error_log("Full Prompt Preview (first 500 chars): " . $full_prompt_preview . "...");
                error_log("Full Prompt Length: " . mb_strlen($prompt) . " characters");
            }
            
            // Generate content
            $generation_result = $this->generate($prompt, array(
                'model' => $model,
                'max_tokens' => 4000,
                'temperature' => 0.7,
                'use_case' => 'long_context'
            ));
            
            if (!$generation_result['success']) {
                // If generation fails, return error
                if (defined('WP_DEBUG') && WP_DEBUG) {
                    error_log("Generation failed on attempt {$attempt}: " . (isset($generation_result['error']) ? $generation_result['error'] : 'Unknown error'));
                }
                
                // If this is the last attempt, return the error
                if ($attempt >= $max_retries) {
                    return $generation_result;
                }
                
                // Otherwise, retry after a short delay
                sleep(2);
                continue;
            }
            
            $section_content = $generation_result['content'];
            
            // TEMPORARILY SKIP VALIDATION - Return content immediately after generation
            if (is_callable($callback)) {
                call_user_func($callback, 6, 'validation_skipped', "Skipping validation (temporarily disabled)");
            }
            
            if (defined('WP_DEBUG') && WP_DEBUG) {
                error_log("Validation SKIPPED on attempt {$attempt} (temporarily disabled)");
                error_log("=== END AI AGENT DEBUG: step_write_section ===\n");
            }
            
            // Return successful result without validation
            return array(
                'success' => true,
                'content' => $section_content,
                'validation' => array('valid' => true, 'skipped' => true),
                'attempts' => $attempt
            );
            
            /* VALIDATION CODE - TEMPORARILY DISABLED
            // Report validation start
            if (is_callable($callback)) {
                call_user_func($callback, 6, 'validation_start', "Validating section content (attempt {$attempt}/{$max_retries})...");
            }
            
            // Validate the generated content
            $validation_result = $this->validate_section_content($section_content, $section, $lang, $model);
            
            if (defined('WP_DEBUG') && WP_DEBUG) {
                error_log("Validation Result: " . json_encode($validation_result));
            }
            
            // Check if validation passed
            if ($validation_result['valid']) {
                // Report validation success
                if (is_callable($callback)) {
                    call_user_func($callback, 6, 'validation_pass', "Content validated successfully");
                }
                
                if (defined('WP_DEBUG') && WP_DEBUG) {
                    error_log("Validation PASSED on attempt {$attempt}");
                    error_log("=== END AI AGENT DEBUG: step_write_section ===\n");
                }
                
                // Return successful result
                return array(
                    'success' => true,
                    'content' => $section_content,
                    'validation' => $validation_result,
                    'attempts' => $attempt
                );
            }
            
            // Validation failed
            if (defined('WP_DEBUG') && WP_DEBUG) {
                error_log("Validation FAILED on attempt {$attempt}");
                error_log("Issues: " . json_encode($validation_result['issues']));
                error_log("Suggestions: " . json_encode($validation_result['suggestions']));
            }
            
            // If this is the last attempt, return with warning
            if ($attempt >= $max_retries) {
                if (is_callable($callback)) {
                    $issues_text = !empty($validation_result['issues']) ? implode('; ', $validation_result['issues']) : 'Unknown issues';
                    call_user_func($callback, 6, 'validation_max_retries', "⚠️ Max retries reached. Using content despite issues: {$issues_text}");
                }
                
                if (defined('WP_DEBUG') && WP_DEBUG) {
                    error_log("Max retries reached. Returning content with validation warnings.");
                    error_log("=== END AI AGENT DEBUG: step_write_section ===\n");
                }
                
                // Return content with validation warning
                return array(
                    'success' => true,
                    'content' => $section_content,
                    'validation' => $validation_result,
                    'attempts' => $attempt,
                    'warning' => 'Content validation failed after ' . $max_retries . ' attempts'
                );
            }
            
            // Prepare feedback for next attempt
            END VALIDATION CODE - TEMPORARILY DISABLED */
            $validation_feedback = '';
            
            if (!$validation_result['language_match']) {
                $detected = isset($validation_result['raw_result']['language_check']['detected_language']) ? 
                    $validation_result['raw_result']['language_check']['detected_language'] : 'unknown';
                $validation_feedback .= "❌ LANGUAGE ISSUE: Content is in '{$detected}' but MUST be in '{$lang}'\n";
            }
            
            if (!$validation_result['objectives_met']) {
                $validation_feedback .= "❌ OBJECTIVES NOT MET:\n";
                if (!empty($validation_result['issues'])) {
                    foreach ($validation_result['issues'] as $issue) {
                        $validation_feedback .= "  - {$issue}\n";
                    }
                }
            }
            
            if (!empty($validation_result['suggestions'])) {
                $validation_feedback .= "\n✅ REQUIRED IMPROVEMENTS:\n";
                foreach ($validation_result['suggestions'] as $suggestion) {
                    $validation_feedback .= "  - {$suggestion}\n";
                }
            }
            
            // Report validation failure and retry
            if (is_callable($callback)) {
                $retry_msg = "Validation failed (attempt {$attempt}/{$max_retries}). Retrying with improvements...";
                call_user_func($callback, 6, 'validation_retry', $retry_msg);
            }
            
            // Short delay before retry
            sleep(2);
        }
        
        // This should never be reached, but just in case
        return array(
            'success' => false,
            'error' => 'Failed to generate valid section content after ' . $max_retries . ' attempts'
        );
    }
    
    /**
     * Validate Section Content
     * 
     * Validates that the generated section content meets requirements:
     * 1. Written in the correct language
     * 2. Meets the section objectives
     * 
     * @param string $content The generated content
     * @param array $section Section information with prompt
     * @param string $lang Target language
     * @param string $model AI model to use for validation
     * @return array Validation result with 'valid', 'language_match', 'objectives_met', 'issues', 'suggestions'
     */
    private function validate_section_content($content, $section, $lang, $model) {
        // Initialize result
        $result = array(
            'valid' => false,
            'language_match' => false,
            'objectives_met' => false,
            'issues' => array(),
            'suggestions' => array(),
            'raw_result' => array()
        );
        
        // Simple language detection first (fast check)
        $content_preview = mb_substr(strip_tags($content), 0, 500);
        
        // Detect if content is in expected language (basic check)
        $lang_lower = strtolower($lang);
        $is_vietnamese = (stripos($lang_lower, 'vi') !== false || stripos($lang_lower, 'việt') !== false);
        
        // Quick language check - look for common patterns
        if ($is_vietnamese) {
            // Check for Vietnamese characters
            $has_vietnamese_chars = preg_match('/[àáạảãâầấậẩẫăằắặẳẵèéẹẻẽêềếệểễìíịỉĩòóọỏõôồốộổỗơờớợởỡùúụủũưừứựửữỳýỵỷỹđ]/iu', $content_preview);
            $result['language_match'] = $has_vietnamese_chars;
        } else {
            // For English and other languages, check that there are NO Vietnamese characters
            $has_vietnamese_chars = preg_match('/[àáạảãâầấậẩẫăằắặẳẵèéẹẻẽêềếệểễìíịỉĩòóọỏõôồốộổỗơờớợởỡùúụủũưừứựửữỳýỵỷỹđ]/iu', $content_preview);
            $result['language_match'] = !$has_vietnamese_chars;
        }
        
        // If language doesn't match, no need to check further
        if (!$result['language_match']) {
            $result['issues'][] = "Content is not in the required language: {$lang}";
            $result['suggestions'][] = "Rewrite the entire content in {$lang}";
            $result['raw_result']['language_check'] = array(
                'detected_language' => $is_vietnamese ? 'non-Vietnamese' : 'Vietnamese',
                'expected_language' => $lang
            );
            return $result;
        }
        
        // Now validate objectives using AI (more thorough but slower)
        // Create a validation prompt
        $validation_prompt = $this->get_language_instruction_prompt($lang);
        $validation_prompt .= "You are a content quality validator.\n\n";
        $validation_prompt .= "TASK: Validate if the generated content meets the section requirements.\n\n";
        
        $validation_prompt .= "=== SECTION REQUIREMENTS ===\n";
        if (isset($section['prompt']) && !empty($section['prompt'])) {
            $validation_prompt .= $section['prompt'] . "\n\n";
        } else {
            $validation_prompt .= "Section: {$section['name']}\n\n";
        }
        
        $validation_prompt .= "=== GENERATED CONTENT ===\n";
        $validation_prompt .= mb_substr($content, 0, 2000) . "\n\n";
        
        $validation_prompt .= "=== VALIDATION QUESTIONS ===\n";
        $validation_prompt .= "1. Does the content address the main objectives of this section?\n";
        $validation_prompt .= "2. Are the key points from the requirements covered?\n";
        $validation_prompt .= "3. Is the content well-structured and coherent?\n";
        $validation_prompt .= "4. Does it maintain the required tone and style?\n\n";
        
        $validation_prompt .= "RESPONSE FORMAT: Return ONLY a JSON object with this structure:\n";
        $validation_prompt .= "{\n";
        $validation_prompt .= "  \"objectives_met\": true/false,\n";
        $validation_prompt .= "  \"issues\": [\"list of specific issues found\"],\n";
        $validation_prompt .= "  \"suggestions\": [\"list of specific improvements needed\"]\n";
        $validation_prompt .= "}\n\n";
        $validation_prompt .= "Be strict but fair. Only return objectives_met: true if the content genuinely meets the requirements.\n";
        
        // Generate validation using AI
        try {
            $validation_response = $this->generate($validation_prompt, array(
                'model' => $model,
                'max_tokens' => 500,
                'temperature' => 0.3,
                'use_case' => 'fast'
            ));
            
            if ($validation_response['success']) {
                $response_text = trim($validation_response['content']);
                
                // Extract JSON from response
                if (preg_match('/\{[\s\S]*"objectives_met"[\s\S]*\}/U', $response_text, $json_match)) {
                    $response_text = $json_match[0];
                }
                
                // Remove markdown code blocks if present
                $response_text = preg_replace('/```json\s*/', '', $response_text);
                $response_text = preg_replace('/```\s*/', '', $response_text);
                $response_text = trim($response_text);
                
                // Parse JSON
                $validation_data = json_decode($response_text, true);
                
                if ($validation_data && isset($validation_data['objectives_met'])) {
                    $result['objectives_met'] = (bool)$validation_data['objectives_met'];
                    
                    if (isset($validation_data['issues']) && is_array($validation_data['issues'])) {
                        $result['issues'] = array_merge($result['issues'], $validation_data['issues']);
                    }
                    
                    if (isset($validation_data['suggestions']) && is_array($validation_data['suggestions'])) {
                        $result['suggestions'] = array_merge($result['suggestions'], $validation_data['suggestions']);
                    }
                    
                    $result['raw_result']['objectives_check'] = $validation_data;
                } else {
                    // JSON parsing failed, assume objectives are met to avoid blocking
                    if (defined('WP_DEBUG') && WP_DEBUG) {
                        error_log("Validation JSON parsing failed. Response: " . $response_text);
                    }
                    $result['objectives_met'] = true; // Default to true if validation fails
                }
            } else {
                // Validation API call failed, assume objectives are met to avoid blocking
                if (defined('WP_DEBUG') && WP_DEBUG) {
                    error_log("Validation API call failed: " . (isset($validation_response['error']) ? $validation_response['error'] : 'Unknown error'));
                }
                $result['objectives_met'] = true; // Default to true if validation fails
            }
        } catch (Exception $e) {
            // Exception during validation, assume objectives are met to avoid blocking
            if (defined('WP_DEBUG') && WP_DEBUG) {
                error_log("Validation exception: " . $e->getMessage());
            }
            $result['objectives_met'] = true; // Default to true if validation fails
        }
        
        // Overall validation result
        $result['valid'] = $result['language_match'] && $result['objectives_met'];
        
        return $result;
    }
    
    /**
     * Helper: Search and Insert Image
     */
    private function search_and_insert_image(&$content, $section_title, $lang) {
        // This requires BardGenContent or an image provider
        // Assuming we have access to BardGenContent globally or via class
        if (class_exists('BardGenContent')) {
            $bard = new BardGenContent();
            
            // Generate a short query for the image
            $query_prompt = "Create a short (3-5 words) image search query for section: {$section_title}. Language: {$lang}. Return ONLY the query.";
            $query_res = $this->generate($query_prompt, ['max_tokens' => 20]);
            
            if ($query_res['success']) {
                $query = trim(strip_tags($query_res['content']));
                
                // Search image
                $images = $bard->searchimg($query);
                
                if (is_array($images) && !empty($images)) {
                    // Get 'result' key if it exists, otherwise assume array of urls
                    $image_list = isset($images['result']) ? $images['result'] : $images;
                    
                    if (!empty($image_list) && isset($image_list[0])) {
                        $img_url = $image_list[0];
                        $img_markdown = "\n![{$section_title}]({$img_url})\n";
                        
                        // Insert after first heading if possible
                        if (preg_match('/^#+\s+.*$/m', $content, $matches, PREG_OFFSET_CAPTURE)) {
                            $pos = $matches[0][1] + strlen($matches[0][0]);
                            $content = substr_replace($content, $img_markdown, $pos, 0);
                        } else {
                            // Or just prepend
                            $content = $img_markdown . $content;
                        }
                    }
                }
            }
        }
    }
    
    /**
     * Helper: Language Instruction
     */
    private function get_language_instruction_prompt($lang) {
        return "RESPONSE LANGUAGE: {$lang}. You MUST write in {$lang}.\n\n";
    }

}

