<?php

namespace AIPT\Api\BulkGenerator\Common;

use AIPT\Api\OpenAI\OpenAIClient;
use AIPT\Api\Gemini\GeminiClient;
use AIPT\Api\OpenRouter\OpenRouterClient;
use AIPT\Api\Claude\ClaudeClient;
use AIPT\Utils\ApiKeyManager;

class AIClientFactory {
    public static function create($api_provider, $options = []) {
        $client = null;

        try {
            if ($api_provider === 'gemini') {
                $api_key = ApiKeyManager::get_gemini_key();
                if (empty($api_key)) {
                    throw new \Exception('Gemini API key is not set');
                }
                $client = new GeminiClient($api_key);
            } elseif ($api_provider === 'openrouter') {
                $api_key = ApiKeyManager::get_openrouter_key();
                if (empty($api_key)) {
                    throw new \Exception('OpenRouter API key is not set');
                }
                $client = new OpenRouterClient($api_key);
            } elseif ($api_provider === 'claude') {
                $api_key = ApiKeyManager::get_claude_key();
                if (empty($api_key)) {
                    throw new \Exception('Claude API key is not set');
                }
                $client = new ClaudeClient($api_key);
            } else {
                $api_key = ApiKeyManager::get_openai_key();
                if (empty($api_key)) {
                    throw new \Exception('OpenAI API key is not set');
                }
                $client = new OpenAIClient($api_key);
            }

            self::applyParameterOptimization($client, $api_provider, $options);

            return $client;
            
        } catch (\Exception $e) {

            throw new \Exception('API key configuration error. Please check your API key settings.');
        }
    }

    /**
     * AI istemcisine optimum parametreleri uygular
     *
     * @param object $client AI istemcisi (OpenAIClient veya GeminiClient)
     * @param string $provider API sağlayıcı (openai, gemini)
     * @param array $options İstemci oluşturma seçenekleri
     * @return void
     */
    private static function applyParameterOptimization($client, $provider, $options = []) {
        try {

            $generationType = $options['generation_type'] ?? 'full';
            $model = $options['model'] ?? null;

            $parameterService = new \AIPT\Core\CreditSystem\ParameterService();
            $optimizedParams = $parameterService->getForType($generationType, $provider, $model);

            if (empty($optimizedParams) || !is_array($optimizedParams)) {
                return; 
            }

            if (isset($optimizedParams['max_tokens'])) {
                unset($optimizedParams['max_tokens']);
            }

            $validParams = [];

            if ($provider === 'openai' || $provider === 'openrouter') {

                if (isset($optimizedParams['temperature']) && is_numeric($optimizedParams['temperature'])) {
                    $temp = floatval($optimizedParams['temperature']);
                    if ($temp >= 0.0 && $temp <= 2.0) {
                        $validParams['temperature'] = $temp;
                    }
                }

                if (isset($optimizedParams['top_p']) && is_numeric($optimizedParams['top_p'])) {
                    $topP = floatval($optimizedParams['top_p']);
                    if ($topP >= 0.0 && $topP <= 1.0) {
                        $validParams['top_p'] = $topP;
                    }
                }

                if (isset($optimizedParams['frequency_penalty']) && is_numeric($optimizedParams['frequency_penalty'])) {
                    $freq = floatval($optimizedParams['frequency_penalty']);
                    if ($freq >= -2.0 && $freq <= 2.0) {
                        $validParams['frequency_penalty'] = $freq;
                    }
                }

                if (isset($optimizedParams['presence_penalty']) && is_numeric($optimizedParams['presence_penalty'])) {
                    $pres = floatval($optimizedParams['presence_penalty']);
                    if ($pres >= -2.0 && $pres <= 2.0) {
                        $validParams['presence_penalty'] = $pres;
                    }
                }
            }

            else if ($provider === 'gemini') {

                if (isset($optimizedParams['temperature']) && is_numeric($optimizedParams['temperature'])) {
                    $temp = floatval($optimizedParams['temperature']);
                    if ($temp >= 0.0 && $temp <= 1.0) {
                        $validParams['temperature'] = $temp;
                    }
                }

                if (isset($optimizedParams['top_p']) && is_numeric($optimizedParams['top_p'])) {
                    $topP = floatval($optimizedParams['top_p']);
                    if ($topP >= 0.0 && $topP <= 1.0) {
                        $validParams['top_p'] = $topP;
                    }
                }

                if (isset($optimizedParams['top_k']) && is_numeric($optimizedParams['top_k'])) {
                    $topK = intval($optimizedParams['top_k']);
                    if ($topK >= 1 && $topK <= 40) {
                        $validParams['top_k'] = $topK;
                    }
                }
            }

            else if ($provider === 'claude') {

                if (isset($optimizedParams['temperature']) && is_numeric($optimizedParams['temperature'])) {
                    $temp = floatval($optimizedParams['temperature']);
                    if ($temp >= 0.0 && $temp <= 1.0) {
                        $validParams['temperature'] = $temp;
                    }
                }

                if (isset($optimizedParams['top_p']) && is_numeric($optimizedParams['top_p'])) {
                    $topP = floatval($optimizedParams['top_p']);
                    if ($topP >= 0.0 && $topP <= 1.0) {
                        $validParams['top_p'] = $topP;
                    }
                }
            }

            if (!empty($validParams) && method_exists($client, 'setParameters')) {

                $client->setParameters($validParams);
            } else {

            }
        } catch (\Exception $e) {

        } catch (\Error $e) {

        }
    }

}