<?php

namespace ZenoChatbot\Services\LLMService\AIClient\Providers\Adapters;

use ZenoChatbot\Services\HttpClient;
use ZenoChatbot\Services\LLMService\AIClient\Config\AiConfig;
use ZenoChatbot\Services\LLMService\AIClient\Providers\OpenAI;
use ZenoChatbot\Services\LLMService\AIClient\Results\Candidate;
use ZenoChatbot\Services\LLMService\AIClient\Results\GenerativeAiResult;
use ZenoChatbot\Services\LLMService\AIClient\Results\TokenUsage;
use ZenoChatbot\Services\LLMService\AIClient\Support\ResponseParser;

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

class OpenAITextModel implements AdapterInterface
{
    public function generate(array $input, AiConfig $config): GenerativeAiResult
    {
        // Build payload using dedicated provider prompt builder
        $payload = \ZenoChatbot\Services\LLMService\AIClient\Providers\PromptBuilders\OpenAIPromptBuilder::buildPayload($config, $input);

        $headers = [
            'Authorization' => 'Bearer ' . $config->getApiKey(),
        ];

        $client = new HttpClient();
        // Switch to Responses API (non-chat)
        $url = OpenAI::API_V1 . '/responses';
        $resp = $client->post($url, $payload, $headers);
        $body = $resp['body'] ?? [];

        $candidates = [];
        $finishReason = null;
        // Prefer Responses API convenience field
        if (isset($body['output_text']) && is_string($body['output_text'])) {
            $txt = trim((string)$body['output_text']);
            if ($txt !== '') { $candidates[] = new Candidate($txt, $finishReason); }
        } elseif (!empty($body['output']) && is_array($body['output'])) {
            // Aggregate any output_text parts from message content
            $buf = '';
            foreach ($body['output'] as $out) {
                if (!is_array($out)) { continue; }
                $content = $out['content'] ?? null;
                if (is_array($content)) {
                    foreach ($content as $part) {
                        if (is_array($part)) {
                            $ptype = $part['type'] ?? '';
                            if ($ptype === 'output_text' || $ptype === 'text') {
                                $buf .= (string)($part['text'] ?? '');
                            }
                        }
                    }
                }
            }
            if (trim($buf) !== '') { $candidates[] = new Candidate(trim($buf), $finishReason); }
        } elseif (!empty($body['choices']) && is_array($body['choices'])) {
            // Backward compatibility if model still proxies chat-like structure
            foreach ($body['choices'] as $ch) {
                $txt = $ch['message']['content'] ?? ($ch['text'] ?? '');
                $candidates[] = new Candidate((string)$txt, $ch['finish_reason'] ?? null);
                $finishReason = $finishReason ?? ($ch['finish_reason'] ?? null);
            }
        }

        // Fallback behavior (strict mode): if no candidates, emit fallback text when provided
        if (empty($candidates) && !empty($input['fallback'])) {
            $candidates[] = new Candidate((string)$input['fallback'], 'stop');
        }

        $usage = $body['usage'] ?? $body['x_gpt_output_usage'] ?? [];
        $tokenUsage = new TokenUsage(
            (int)($usage['prompt_tokens'] ?? $usage['input_tokens'] ?? 0),
            (int)($usage['completion_tokens'] ?? $usage['output_tokens'] ?? 0),
            (int)($usage['total_tokens'] ?? (($usage['input_tokens'] ?? 0) + ($usage['output_tokens'] ?? 0)))
        );

        $citations = ResponseParser::extractCitations($candidates);

        // Prepare raw request (sanitize API key)
        $rawRequest = ResponseParser::sanitizeRequest($input, [
            'model' => $payload['model'] ?? null,
            'input_count' => is_array($payload['input'] ?? null) ? count($payload['input']) : 0,
            'has_instructions' => isset($payload['instructions']),
        ]);

        // Prepare raw response
        $rawResponse = $body;

        return GenerativeAiResult::create([
            'candidates'    => $candidates,
            'token_usage'   => $tokenUsage,
            'finish_reason' => $finishReason,
            'citations'     => $citations,
            'provider'      => 'openai',
            'model'         => $config->getModel(),
            'raw_response'  => $rawResponse,
            'raw_request'   => $rawRequest,
        ]);
    }

}

