<?php

namespace AIPT\Api\OpenAI;

use AIPT\Api\AIClientInterface;
use AIPT\Utils\PromptFormatter;
use AIPT\Core\ErrorHandler;

class OpenAIClient implements AIClientInterface {
    private $api_key;
    private $api_url = 'https://api.openai.com/v1/chat/completions';
    private $models = [];

    public function __construct($api_key) {
        $this->api_key = $api_key;
        $this->initializeModels();
    }
    
    /**
     * Initialize model configurations using shared base configurations
     * This eliminates code duplication and makes maintenance easier
     */
    private function initializeModels(): void {

        $gpt5Config = [
            'max_completion_tokens' => 128000,
            'use_legacy_params' => false,
            'has_temperature' => false,
            'supports_system_message' => true
        ];
        

        $gpt41Config = [
            'max_completion_tokens' => 32768,
            'temperature' => 0.7,
            'use_legacy_params' => false,
            'has_temperature' => true,
            'supports_system_message' => true
        ];
        

        $reasoningConfig = [
            'max_completion_tokens' => 100000,
            'temperature' => 0.7,
            'use_legacy_params' => false,
            'has_temperature' => false,
            'supports_system_message' => false
        ];
        

        $legacyConfig = [
            'max_tokens' => 4096,
            'temperature' => 0.7,
            'use_legacy_params' => true,
            'has_temperature' => true,
            'supports_system_message' => true
        ];
        
        $this->models = [

            'gpt-5.4' => ['name' => 'gpt-5.4'] + $gpt5Config,
            'gpt-5.4-mini' => ['name' => 'gpt-5.4-mini'] + $gpt5Config,
            'gpt-5.4-nano' => ['name' => 'gpt-5.4-nano'] + $gpt5Config,
            

            'gpt-5.2' => ['name' => 'gpt-5.2'] + $gpt5Config,
            'gpt-5.2-pro' => ['name' => 'gpt-5.2-pro'] + $gpt5Config,
            

            'gpt-5-mini' => ['name' => 'gpt-5-mini'] + $gpt5Config,
            'gpt-5-nano' => ['name' => 'gpt-5-nano'] + $gpt5Config,
            

            'gpt-4.1' => ['name' => 'gpt-4.1'] + $gpt41Config,
            'gpt-4.1-mini' => ['name' => 'gpt-4.1-mini'] + $gpt41Config,
            'gpt-4.1-nano' => ['name' => 'gpt-4.1-nano'] + $gpt41Config,
            

            'o4-mini' => ['name' => 'o4-mini'] + $reasoningConfig,
            'o3-pro' => ['name' => 'o3-pro'] + $reasoningConfig,
            'o3' => ['name' => 'o3'] + $reasoningConfig,
        ];
    }

    public function generate_description(string $system_prompt, string $user_prompt, string $model = 'gpt-4.1-mini', ?int $maximum_length = null): string {
        if (!isset($this->models[$model])) {
            throw new \Exception('Invalid model selected: ' . esc_html($model));
        }

        $model_config = $this->models[$model];
        $messages = [];

        $system_prompt = $this->sanitize_prompt_content($system_prompt);
        $user_prompt = $this->sanitize_prompt_content($user_prompt);

        if ($model_config['supports_system_message']) {
            $messages[] = [
                'role' => 'system',
                'content' => $system_prompt
            ];
            $messages[] = [
                'role' => 'user',
                'content' => $user_prompt
            ];
        } else {
            $messages[] = [
                'role' => 'user',
                'content' => $system_prompt . "\n\n" . $user_prompt
            ];
        }

        $request_body = [
            'model' => $model_config['name'],
            'messages' => $messages
        ];

        if ($model_config['has_temperature']) {
            $request_body['temperature'] = $model_config['temperature'];
        }
        

        $timeout = 30; 
        if (strpos($model, 'gpt-5') === 0) {
            $timeout = 120; 
        }
        
        $json_body = wp_json_encode($request_body, JSON_UNESCAPED_UNICODE);

        if ( false === $json_body ) {

            throw new \Exception(
                __( 'Failed to encode request body as JSON. The product data may contain invalid characters.', 'ai-product-tools' )
            );

        }

        $response = wp_remote_post($this->api_url, [
            'headers' => [
                'Authorization' => 'Bearer ' . $this->api_key,
                'Content-Type' => 'application/json',
            ],
            'body' => $json_body,
            'timeout' => $timeout,
        ]);

        if ($response instanceof \WP_Error) {
            $error_message = $response->get_error_message();
            throw new \Exception(
                sprintf(
                    /* translators: %s: WP Error message */
                    esc_html__('WP Error: %s', 'ai-product-tools'),
                    esc_html($error_message)
                )
            );
        }

        $response_code = wp_remote_retrieve_response_code($response);
        $content_type = (string) wp_remote_retrieve_header($response, 'content-type');
        $body_str = (string) wp_remote_retrieve_body($response);

        if (strpos($content_type, 'application/json') === false && !empty($body_str) && $body_str[0] === '<') {

            throw new \Exception(__('The API response was not valid JSON. This is often caused by a server firewall or security plugin blocking outbound requests. Please contact your hosting provider or check your security plugin settings.', 'ai-product-tools'));
        }

        $body = json_decode($body_str, true);
        if (json_last_error() !== JSON_ERROR_NONE) {

            throw new \Exception(
                sprintf(
                    /* translators: %s: JSON error message */
                    __('Invalid JSON response from the API: %s', 'ai-product-tools'),
                    json_last_error_msg()
                )
            );

        }

        if (isset($body['error'])) {
            $error_data = $body['error'];

            $detailed_error = ErrorHandler::format_api_response_error($error_data, 'OpenAI', $response_code);

            throw new \Exception($detailed_error);
        }

        if (!isset($body['choices'][0]['message']['content'])) {
            throw new \Exception('Invalid response from OpenAI API: Response structure is not as expected');
        }

        return trim($body['choices'][0]['message']['content']);
    }

    public function generate_faq_content(string $system_prompt, string $user_prompt, ?string $model = null): string {
        $resolved_model = $model ?: 'gpt-4.1-mini';

        return $this->generate_description($system_prompt, $user_prompt, $resolved_model);
    }

    /**
     * Prompt içeriğini temizler ve API için hazırlar
     * 
     * @param string $content Temizlenecek prompt içeriği 
     * @return string Temizlenmiş içerik
     */
    private function sanitize_prompt_content(string $content): string {
        return PromptFormatter::cleanContent($content);
    }

    public static function validate_api_key(string $api_key): bool {
        $validation_timeout = 20;

        try {

            $response = wp_remote_get('https://api.openai.com/v1/models', [
                'headers' => [
                    'Authorization' => 'Bearer ' . $api_key,
                ],
                'timeout' => $validation_timeout
            ]);

            if (is_wp_error($response)) {
                /** @var \WP_Error $response */
                throw new \Exception(
                    sprintf(
                        /* translators: %s: Error message from API request */
                        __( 'OpenAI API request failed: %s', 'ai-product-tools' ),
                        $response->get_error_message()
                    )
                );
            }

            $response_code = wp_remote_retrieve_response_code($response);
            $body_str = (string) wp_remote_retrieve_body($response);
            $body = json_decode($body_str, true);

            if (json_last_error() !== JSON_ERROR_NONE || !is_array($body)) {
                throw new \Exception(
                    sprintf(
                        /* translators: %s: JSON error message */
                        __('Invalid response from OpenAI API: %s', 'ai-product-tools'),
                        json_last_error_msg()
                    )
                );
            }

            if ($response_code === 200 && !empty($body['data'])) {
                return true;
            }

            if (isset($body['error']['message'])) {
                throw new \Exception($body['error']['message']);
            }

            throw new \Exception(__('Invalid OpenAI API key', 'ai-product-tools'));

        } catch (\Exception $e) {
            throw $e;
        }
    }

    public function get_available_models(): array {
        return $this->models;
    }
    
    /**
     * API istekleri için parametre ayarlarını yapar
     * 
     * @param array $parameters Ayarlanacak parametreler
     * @return void
     */
    public function setParameters(array $parameters): void {
        if (empty($parameters)) {
            return;
        }
        
        try {

            foreach ($this->models as $model_id => &$model_config) {

                if (isset($parameters['temperature']) && is_numeric($parameters['temperature'])) {
                    $temperature = floatval($parameters['temperature']);

                    if ($temperature >= 0.0 && $temperature <= 2.0) {
                        if (!isset($model_config['has_temperature']) || $model_config['has_temperature'] === true) {
                            $model_config['temperature'] = $temperature;
                        }
                    } else {
                    }
                }
                

                if (isset($parameters['top_p']) && is_numeric($parameters['top_p'])) {
                    $topP = floatval($parameters['top_p']);

                    if ($topP >= 0.0 && $topP <= 1.0) {
                        $model_config['top_p'] = $topP;
                    } else {
                    }
                }
                

                if (isset($model_config['use_legacy_params']) && $model_config['use_legacy_params']) {
                    if (isset($parameters['frequency_penalty']) && is_numeric($parameters['frequency_penalty'])) {
                        $freqPenalty = floatval($parameters['frequency_penalty']);

                        if ($freqPenalty >= -2.0 && $freqPenalty <= 2.0) {
                            $model_config['frequency_penalty'] = $freqPenalty;
                        } else {
                        }
                    }
                    
                    if (isset($parameters['presence_penalty']) && is_numeric($parameters['presence_penalty'])) {
                        $presPenalty = floatval($parameters['presence_penalty']);

                        if ($presPenalty >= -2.0 && $presPenalty <= 2.0) {
                            $model_config['presence_penalty'] = $presPenalty;
                        } else {
                        }
                    }
                }
                

            }
        } catch (\Exception $e) {

        }
    }
} 
