<?php
/**
 * OpenAI Provider
 */

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

class AIAutotool_AI_Provider_OpenAI extends AIAutotool_AI_Provider_Base {
    
    protected $name = 'OpenAI';
    protected $id = 'openai';
    protected $base_url = 'https://api.openai.com/v1';
    protected $default_model = 'gpt-4o-mini';
    protected $capabilities = array('text_generation', 'image_generation');
    
    protected $available_models = array(
        'gpt-4o' => 'GPT-4o (Most Capable)',
        'gpt-4o-mini' => 'GPT-4o Mini (Fast & Affordable)',
        'gpt-4-turbo' => 'GPT-4 Turbo',
        'gpt-4' => 'GPT-4',
        'gpt-3.5-turbo' => 'GPT-3.5 Turbo',
        'gpt-3.5-turbo-16k' => 'GPT-3.5 Turbo 16K',
    );

    public function get_image_models() {
        return array(
            'dall-e-3' => 'DALL-E 3',
            'dall-e-2' => 'DALL-E 2',
            'gpt-image-1' => 'GPT Image 1',
        );
    }

    public function generate_image($prompt, $options = array()) {
        if (!$this->is_configured()) {
            return array('success' => false, 'error' => 'OpenAI API key not configured');
        }

        $prompt = trim((string) $prompt);
        if ($prompt === '') {
            return array('success' => false, 'error' => 'Image prompt is required');
        }

        $models = $this->get_image_models();
        $model = isset($options['model']) ? sanitize_text_field($options['model']) : 'dall-e-3';
        if (!isset($models[$model])) {
            $model = 'dall-e-3';
        }

        $width = isset($options['width']) ? (int) $options['width'] : 1024;
        $height = isset($options['height']) ? (int) $options['height'] : 1024;
        $size = $this->normalize_image_size($width, $height, $model);

        $api_key_to_use = !empty($this->api_key) ? $this->api_key : $this->get_rotated_key();
        if (empty($api_key_to_use)) {
            return array('success' => false, 'error' => 'OpenAI API key not configured');
        }

        $body = array(
            'model' => $model,
            'prompt' => $prompt,
            'n' => 1,
            'size' => $size,
        );

        if ($model !== 'gpt-image-1') {
            $body['response_format'] = 'url';
        }

        $response = $this->make_request(
            $this->base_url . '/images/generations',
            $body,
            'POST',
            array(
                'Authorization' => 'Bearer ' . $api_key_to_use,
                'Content-Type' => 'application/json',
            ),
            array('timeout' => isset($options['timeout']) ? (int) $options['timeout'] : 90)
        );

        if (!$response['success']) {
            return $response;
        }

        $data = isset($response['data']['data'][0]) ? $response['data']['data'][0] : array();
        if (!empty($data['url'])) {
            return array(
                'success' => true,
                'url' => esc_url_raw($data['url']),
                'model' => $model,
                'provider' => $this->id,
                'size' => $size,
            );
        }

        if (!empty($data['b64_json'])) {
            return array(
                'success' => true,
                'data_url' => 'data:image/png;base64,' . $data['b64_json'],
                'model' => $model,
                'provider' => $this->id,
                'size' => $size,
            );
        }

        return array('success' => false, 'error' => 'OpenAI image response missing image data');
    }

    private function normalize_image_size($width, $height, $model) {
        if ($model === 'dall-e-2') {
            return '1024x1024';
        }

        if ($width > $height) {
            return '1792x1024';
        }

        if ($height > $width) {
            return '1024x1792';
        }

        return '1024x1024';
    }
    
    public function __construct($api_key = '') {
        parent::__construct($api_key);
        
        if (empty($this->api_key)) {
            $this->api_key = $this->get_rotated_key();
        }
    }
    
    /**
     * Check if this is an Azure OpenAI endpoint
     * 
     * @return bool
     */
    private function is_azure_openai() {
        $base_url_lower = strtolower($this->base_url);
        return strpos($base_url_lower, 'azure') !== false || 
               strpos($base_url_lower, 'openai.azure.com') !== false;
    }
    
    /**
     * Chat completion
     */
    public function chat_completion($messages, $options = array()) {
        if (!$this->is_configured()) {
            return array(
                'success' => false,
                'error' => 'OpenAI API key not configured'
            );
        }
        
        $options = $this->parse_options($options);
        
        // Get rotated key if needed
        $api_key_to_use = $this->api_key;
        if (empty($api_key_to_use)) {
            $api_key_to_use = $this->get_rotated_key();
            if (!empty($api_key_to_use)) {
                $this->api_key = $api_key_to_use; // Update instance key
            }
        }
        
        if (empty($api_key_to_use)) {
            return array(
                'success' => false,
                'error' => 'OpenAI API key not configured'
            );
        }
        
        $url = $this->base_url . '/chat/completions';
        
        $body = array(
            'model' => $options['model'],
            'messages' => $messages,
            'max_tokens' => intval($options['max_tokens']),
            'top_p' => floatval($options['top_p'])
        );
        
        // Azure OpenAI only supports default temperature (1), so we conditionally include it
        // Only send temperature if:
        // 1. Not using Azure OpenAI, OR
        // 2. Using Azure OpenAI and temperature is 1 (default)
        $is_azure = $this->is_azure_openai();
        $temperature = floatval($options['temperature']);
        
        if (!$is_azure || $temperature == 1.0) {
            // For non-Azure or Azure with default temperature, include it
            $body['temperature'] = $temperature;
        } else {
            // For Azure OpenAI with non-default temperature, omit it to use default
            // This prevents the "Unsupported value" error
        }
        
        $headers = array(
            'Authorization' => 'Bearer ' . $api_key_to_use,
            'Content-Type' => 'application/json'
        );
        
        $this->log('Chat completion request', array('model' => $options['model']));
        
        $response = $this->make_request($url, $body, 'POST', $headers, array(
            'timeout' => isset($options['timeout']) ? (int) $options['timeout'] : 60,
            'connect_timeout' => isset($options['connect_timeout']) ? (int) $options['connect_timeout'] : 10,
            'low_speed_time' => isset($options['low_speed_time']) ? (int) $options['low_speed_time'] : 30,
        ));
        
        if (!$response['success']) {
            // Ensure error is always set
            if (!isset($response['error'])) {
                $response['error'] = 'API request failed';
            }
            return $response;
        }
        
        $data = $response['data'];
        
        // Validate response structure
        if (!isset($data['choices']) || !is_array($data['choices']) || empty($data['choices'])) {
            return array(
                'success' => false,
                'error' => 'Invalid response structure: missing choices array'
            );
        }
        
        if (!isset($data['choices'][0]['message']['content'])) {
            return array(
                'success' => false,
                'error' => 'Invalid response structure: missing message content'
            );
        }
        
        return array(
            'success' => true,
            'content' => $data['choices'][0]['message']['content'],
            'usage' => isset($data['usage']) ? $data['usage'] : null,
            'model' => isset($data['model']) ? $data['model'] : $options['model'],
            'finish_reason' => isset($data['choices'][0]['finish_reason']) ? $data['choices'][0]['finish_reason'] : null
        );
    }
    
    /**
     * Test connection
     */
    public function test_connection() {
        if (!$this->is_configured()) {
            return array(
                'success' => false,
                'message' => 'OpenAI API key not configured'
            );
        }
        
        // Get available models for display
        $available_models = $this->get_available_models();
        $test_model = $this->default_model;
        $model_name = isset($available_models[$test_model]) ? $available_models[$test_model] : $test_model;
        
        // Test with prompt asking model to introduce itself
        $test_prompt = sprintf(
            __('Hãy giới thiệu về bạn (model AI) cùng tên model (%s) và ngày cuối cùng cập nhật dữ liệu của bạn. Trả lời bằng tiếng Việt.', 'ai-auto-tool'),
            $model_name
        );
        
        $test_messages = array(
            array(
                'role' => 'user',
                'content' => $test_prompt
            )
        );
        
        $test_result = $this->chat_completion($test_messages, array('model' => $test_model));
        
        if ($test_result['success']) {
            // Get the actual model used in response
            $response_model = isset($test_result['model']) ? $test_result['model'] : $test_model;
            $response_model_name = isset($available_models[$response_model]) ? $available_models[$response_model] : $response_model;
            
            // Get response content
            $response_content = '';
            if (isset($test_result['content'])) {
                $response_content = is_string($test_result['content']) ? trim($test_result['content']) : '';
            } elseif (isset($test_result['response'])) {
                $response_content = is_string($test_result['response']) ? trim($test_result['response']) : '';
            }
            
            return array(
                'success' => true,
                'message' => 'OpenAI API connection successful!',
                'response' => $response_content,
                'model' => $response_model,
                'model_name' => $response_model_name,
                'usage' => isset($test_result['usage']) ? $test_result['usage'] : null
            );
        } else {
            return array(
                'success' => false,
                'message' => 'OpenAI API Error: ' . (isset($test_result['error']) ? $test_result['error'] : 'Unknown error'),
                'model' => $test_model,
                'model_name' => $model_name
            );
        }
    }
    
    /**
     * Get models list
     */
    public function get_models() {
        if (!$this->is_configured()) {
            return array(
                'success' => false,
                'error' => 'OpenAI API key not configured'
            );
        }
        
        // Get rotated key if needed
        $api_key_to_use = $this->api_key;
        if (empty($api_key_to_use)) {
            $api_key_to_use = $this->get_rotated_key();
            if (!empty($api_key_to_use)) {
                $this->api_key = $api_key_to_use; // Update instance key
            }
        }
        
        if (empty($api_key_to_use)) {
            return array(
                'success' => false,
                'error' => 'OpenAI API key not configured'
            );
        }
        
        $url = $this->base_url . '/models';
        
        $headers = array(
            'Authorization' => 'Bearer ' . $api_key_to_use,
            'Content-Type' => 'application/json'
        );
        
        $response = $this->make_request($url, null, 'GET', $headers);
        
        if ($response['success']) {
            $models = array();
            foreach ($response['data']['data'] as $model) {
                if (!empty($model['id'])) {
                    $models[] = $model['id'];
                }
            }
            
            return array(
                'success' => true,
                'models' => $models
            );
        }
        
        return $response;
    }
}
