<?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\Credentials\CredentialResolver;

/**
 * AI client factory with parameter optimization layer.
 *
 * Wraps RestAPIClientFactory with provider-specific parameter tuning
 * (temperature, top_p, max_tokens, etc.) for bulk generation operations.
 *
 * Since 2.6.0: API key resolution via CredentialResolver. Parameter optimization
 * and provider-selection logic unchanged.
 */
class AIClientFactory {
    public static function create($api_provider, $options = []) {

        $ai_gate = \AIPT\Core\Services\AiSupportGate::guard();
        if ( $ai_gate instanceof \WP_Error ) {
            $data        = $ai_gate->get_error_data();
            $status_code = ( is_array( $data ) && isset( $data['status'] ) ) ? (int) $data['status'] : 503;

            throw new \Exception(
                '[' . $ai_gate->get_error_code() . '] ' . $ai_gate->get_error_message(),
                $status_code
            );

        }
        $resolver = CredentialResolver::instance();
        $api_key  = $resolver->getKey($api_provider);

        if (empty($api_key)) {
            $source_label = $resolver->getSourceLabel($api_provider);

            throw new \Exception(
                sprintf(
                    /* translators: 1: provider id, 2: source label. */
                    __('%1$s API key is not configured (resolved source: %2$s).', 'ai-product-tools'),
                    $api_provider,
                    $source_label
                )
            );

        }

        if ($api_provider === 'gemini') {
            $client = new GeminiClient($api_key);
        } elseif ($api_provider === 'openrouter') {
            $client = new OpenRouterClient($api_key);
        } elseif ($api_provider === 'claude') {
            $client = new ClaudeClient($api_key);
        } else {
            $client = new OpenAIClient($api_key);
        }

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

        return $client;
    }

    /**
     * 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) {

        }
    }

}