<?php
/**
 * AI Agent Verifier
 * Handles verification phase: validates outputs, detects errors, auto-corrects
 * 
 * @package AI_Auto_Tool
 */

if (!defined('ABSPATH')) {
    exit;
}

/**
 * Agent Verifier Class
 * Validates execution results and auto-corrects errors
 */
class AIAutotool_Agent_Verifier {
    
    /**
     * AI Provider Manager
     * @var object
     */
    private $manager;
    
    /**
     * Agent context
     * @var AIAutotool_Agent_Context
     */
    private $context;
    
    /**
     * Verification models (prefer reasoning models)
     * @var array
     */
    private $verification_models = array(
        array('provider' => 'openai', 'model' => 'gpt-4o'),
        array('provider' => 'gemini', 'model' => 'gemini-2.5-pro'),
    );
    
    /**
     * Constructor
     * 
     * @param object $manager Provider manager
     * @param AIAutotool_Agent_Context $context Agent context
     */
    public function __construct($manager, $context) {
        $this->manager = $manager;
        $this->context = $context;
    }
    
    /**
     * Validate output against requirements
     * 
     * @param string $output Generated output
     * @param string $original_request Original request
     * @param array $options Validation options
     * @return array Validation result
     */
    public function validate_output($output, $original_request, $options = array()) {
        $this->context->add_task('validate_output', 'verifying');
        
        $checks = array(
            'language' => $this->check_language($output, $options),
            'completeness' => $this->check_completeness($output, $original_request),
            'quality' => $this->check_quality($output),
            'format' => $this->check_format($output, $options)
        );
        
        $is_valid = true;
        $issues = array();
        
        foreach ($checks as $check_name => $check_result) {
            if (!$check_result['valid']) {
                $is_valid = false;
                $issues[] = array(
                    'check' => $check_name,
                    'issue' => $check_result['issue'],
                    'severity' => $check_result['severity'] ?? 'medium'
                );
            }
        }
        
        $this->context->update_task_status('completed', array(
            'valid' => $is_valid,
            'issues' => $issues
        ));
        
        return array(
            'valid' => $is_valid,
            'checks' => $checks,
            'issues' => $issues,
            'can_auto_correct' => $this->can_auto_correct($issues)
        );
    }
    
    /**
     * Check language correctness
     * 
     * @param string $output Output
     * @param array $options Options
     * @return array Check result
     */
    private function check_language($output, $options) {
        $expected_lang = $options['language'] ?? null;
        
        if (!$expected_lang) {
            // No language requirement
            return array('valid' => true);
        }
        
        // Detect language
        $detected_lang = $this->detect_language($output);
        
        if ($detected_lang !== $expected_lang) {
            return array(
                'valid' => false,
                'issue' => "Expected {$expected_lang} but got {$detected_lang}",
                'severity' => 'high',
                'detected' => $detected_lang,
                'expected' => $expected_lang
            );
        }
        
        return array('valid' => true, 'language' => $detected_lang);
    }
    
    /**
     * Detect language of text
     * 
     * @param string $text Text
     * @return string Language code
     */
    private function detect_language($text) {
        // Simple detection based on character patterns
        $vietnamese_chars = preg_match_all('/[àáạảãâầấậẩẫăằắặẳẵèéẹẻẽêềếệểễìíịỉĩòóọỏõôồốộổỗơờớợởỡùúụủũưừứựửữỳýỵỷỹđ]/iu', $text);
        $total_chars = mb_strlen(preg_replace('/\s/', '', $text));
        
        if ($total_chars > 0 && ($vietnamese_chars / $total_chars) > 0.1) {
            return 'vi';
        }
        
        return 'en';
    }
    
    /**
     * Check completeness
     * 
     * @param string $output Output
     * @param string $request Original request
     * @return array Check result
     */
    private function check_completeness($output, $request) {
        // Use AI to check if output fulfills request
        $prompt = "Kiểm tra xem output sau có đáp ứng đầy đủ yêu cầu không?

YÊU CẦU: {$request}

OUTPUT: {$output}

Trả về JSON (chỉ JSON, không text khác):
{
    \"complete\": true/false,
    \"missing\": [\"list of missing parts if incomplete\"],
    \"explanation\": \"brief explanation\"
}";
        
        $result = $this->execute_with_verification_model($prompt);
        
        if (!$result['success']) {
            // Fallback: simple check
            return array(
                'valid' => strlen($output) > 50,
                'issue' => 'Could not verify completeness'
            );
        }
        
        $check = $this->parse_json($result['content']);
        
        if (!$check || !isset($check['complete'])) {
            return array('valid' => true); // Assume valid if can't parse
        }
        
        if (!$check['complete']) {
            return array(
                'valid' => false,
                'issue' => 'Output incomplete: ' . implode(', ', $check['missing'] ?? array()),
                'severity' => 'high',
                'missing' => $check['missing'] ?? array()
            );
        }
        
        return array('valid' => true);
    }
    
    /**
     * Check quality
     * 
     * @param string $output Output
     * @return array Check result
     */
    private function check_quality($output) {
        $issues = array();
        
        // Check for garbled text
        if ($this->is_garbled($output)) {
            $issues[] = 'Garbled or malformed text detected';
        }
        
        // Check for very short output
        if (strlen($output) < 20) {
            $issues[] = 'Output too short';
        }
        
        // Check for repetitive content
        if ($this->is_repetitive($output)) {
            $issues[] = 'Repetitive content detected';
        }
        
        if (!empty($issues)) {
            return array(
                'valid' => false,
                'issue' => implode('; ', $issues),
                'severity' => 'medium'
            );
        }
        
        return array('valid' => true);
    }
    
    /**
     * Check if text is garbled
     * 
     * @param string $text Text
     * @return bool
     */
    private function is_garbled($text) {
        // Check for excessive special characters or encoding issues
        $special_char_ratio = strlen(preg_replace('/[a-zA-Z0-9\s]/u', '', $text)) / max(strlen($text), 1);
        
        return $special_char_ratio > 0.5;
    }
    
    /**
     * Check if text is repetitive
     * 
     * @param string $text Text
     * @return bool
     */
    private function is_repetitive($text) {
        // Simple check: find repeated patterns
        $words = preg_split('/\s+/', $text);
        if (count($words) < 10) {
            return false;
        }
        
        $word_counts = array_count_values($words);
        foreach ($word_counts as $count) {
            if ($count > count($words) * 0.3) {
                return true;
            }
        }
        
        return false;
    }
    
    /**
     * Check format
     * 
     * @param string $output Output
     * @param array $options Options
     * @return array Check result
     */
    private function check_format($output, $options) {
        $expected_format = $options['format'] ?? null;
        
        if (!$expected_format) {
            return array('valid' => true);
        }
        
        switch ($expected_format) {
            case 'json':
                $decoded = json_decode($output, true);
                if (!$decoded) {
                    return array(
                        'valid' => false,
                        'issue' => 'Invalid JSON format',
                        'severity' => 'high'
                    );
                }
                break;
                
            case 'html':
                // Basic HTML check
                if (strip_tags($output) === $output) {
                    return array(
                        'valid' => false,
                        'issue' => 'Output is not HTML',
                        'severity' => 'medium'
                    );
                }
                break;
        }
        
        return array('valid' => true);
    }
    
    /**
     * Detect errors in output
     * 
     * @param string $output Output
     * @return array Detected errors
     */
    public function detect_errors($output) {
        $errors = array();
        
        // Check for error patterns
        $error_patterns = array(
            '/error:/i' => 'Error message in output',
            '/exception:/i' => 'Exception in output',
            '/failed/i' => 'Failure indicator',
            '/\[object Object\]/i' => 'Unformatted object',
        );
        
        foreach ($error_patterns as $pattern => $description) {
            if (preg_match($pattern, $output)) {
                $errors[] = array(
                    'type' => 'pattern_match',
                    'description' => $description,
                    'pattern' => $pattern
                );
            }
        }
        
        return $errors;
    }
    
    /**
     * Auto-correct errors
     * 
     * @param string $output Original output
     * @param array $validation Validation result
     * @param string $original_request Original request
     * @return array Corrected result
     */
    public function auto_correct($output, $validation, $original_request) {
        $this->context->add_task('auto_correct', 'executing');
        
        if ($validation['valid']) {
            return array(
                'success' => true,
                'corrected' => false,
                'output' => $output
            );
        }
        
        // Build correction prompt
        $prompt = $this->build_correction_prompt($output, $validation, $original_request);
        
        $result = $this->execute_with_verification_model($prompt);
        
        if (!$result['success']) {
            return array(
                'success' => false,
                'error' => 'Auto-correction failed'
            );
        }
        
        $this->context->update_task_status('completed');
        
        return array(
            'success' => true,
            'corrected' => true,
            'output' => $result['content'],
            'original_output' => $output
        );
    }
    
    /**
     * Build correction prompt
     * 
     * @param string $output Original output
     * @param array $validation Validation result
     * @param string $request Original request
     * @return string
     */
    private function build_correction_prompt($output, $validation, $request) {
        $issues_text = '';
        foreach ($validation['issues'] as $issue) {
            $issues_text .= "- {$issue['check']}: {$issue['issue']}\n";
        }
        
        return "Hãy sửa lại output sau để khắc phục các vấn đề:

YÊU CẦU GỐC: {$request}

OUTPUT HIỆN TẠI: 
{$output}

VẤN ĐỀ CẦN SỬA:
{$issues_text}

Trả về output đã được sửa lại, giữ nguyên format và style nhưng khắc phục các vấn đề trên.";
    }
    
    /**
     * Check if issues can be auto-corrected
     * 
     * @param array $issues Issues
     * @return bool
     */
    private function can_auto_correct($issues) {
        foreach ($issues as $issue) {
            // Can't auto-correct critical issues
            if ($issue['severity'] === 'critical') {
                return false;
            }
        }
        
        return !empty($issues);
    }
    
    /**
     * Suggest improvements
     * 
     * @param string $output Output
     * @param string $request Original request
     * @return array Suggestions
     */
    public function suggest_improvements($output, $request) {
        $prompt = "Đề xuất cải thiện cho output sau:

YÊU CẦU: {$request}

OUTPUT: {$output}

Trả về JSON với các đề xuất cải thiện:
{
    \"suggestions\": [
        {\"aspect\": \"clarity|detail|structure|etc\", \"suggestion\": \"specific suggestion\"}
    ]
}";
        
        $result = $this->execute_with_verification_model($prompt);
        
        if (!$result['success']) {
            return array();
        }
        
        $parsed = $this->parse_json($result['content']);
        
        return $parsed['suggestions'] ?? array();
    }
    
    /**
     * Execute with verification model
     * 
     * @param string $prompt Prompt
     * @return array Result
     */
    private function execute_with_verification_model($prompt) {
        foreach ($this->verification_models as $model_combo) {
            $provider = $this->manager->get_provider($model_combo['provider']);
            
            if (!$provider) {
                continue;
            }
            
            $messages = array(
                array('role' => 'user', 'content' => $prompt)
            );
            
            $result = $provider->chat_completion($messages, array(
                'model' => $model_combo['model'],
                'temperature' => 0.2,
                'max_tokens' => 2000
            ));
            
            if ($result['success'] && !empty($result['content'])) {
                return $result;
            }
        }
        
        return array(
            'success' => false,
            'error' => 'All verification models failed'
        );
    }
    
    /**
     * Parse JSON from response
     * 
     * @param string $content Response content
     * @return array|null
     */
    private function parse_json($content) {
        // Remove markdown code blocks
        $content = preg_replace('/```json\s*|\s*```/', '', $content);
        $content = trim($content);
        
        return json_decode($content, true);
    }
}
