<?php
namespace boru\ai\Tests\Provider\OpenAI;

use boru\ai\Provider\OpenAI\OpenAIMapper;
use boru\ai\Provider\OpenAI\OpenAIProvider;
use boru\ai\Embedding\EmbeddingRequest;
use boru\ai\Schema\Request;
use boru\ai\Schema\Response;
use boru\ai\Schema\ToolResult;
use boru\ai\Tests\Fakes\FakeOpenAIClient;
use PHPUnit\Framework\TestCase;

class OpenAIProviderTest extends TestCase
{
    public function testExecutePostsMappedRequestAndReturnsNormalizedResponse()
    {
        $client = new FakeOpenAIClient(array(
            array(
                'id' => 'resp_1',
                'model' => 'gpt-5.1',
                'status' => 'completed',
                'output' => array(
                    array(
                        'type' => 'message',
                        'content' => array(
                            array(
                                'type' => 'output_text',
                                'text' => 'Hello from OpenAI',
                            ),
                        ),
                    ),
                ),
            ),
        ));

        $provider = new OpenAIProvider($client, new OpenAIMapper());
        $request = new Request();
        $request->model('gpt-5.1')->addMessage('Hello');

        $response = $provider->execute($request);

        $this->assertInstanceOf(Response::class, $response);
        $this->assertSame('responses', $client->requests[0]['path']);
        $this->assertSame('gpt-5.1', $client->requests[0]['payload']['model']);
        $this->assertSame('Hello from OpenAI', $response->text());
    }

    public function testContinueResponseAddsToolResultsAndPreviousResponseId()
    {
        $client = new FakeOpenAIClient(array(
            array(
                'id' => 'resp_2',
                'model' => 'gpt-5.1',
                'status' => 'completed',
                'output' => array(
                    array(
                        'type' => 'message',
                        'content' => array(
                            array(
                                'type' => 'output_text',
                                'text' => 'The temperature is 69°F.',
                            ),
                        ),
                    ),
                ),
            ),
        ));

        $provider = new OpenAIProvider($client, new OpenAIMapper());
        $request = new Request();
        $request->model('gpt-5.1')->addMessage('Weather?');

        $previousResponse = new Response();
        $previousResponse->id('resp_previous');

        $toolResult = new ToolResult();
        $toolResult->toolCallId('call_123');
        $toolResult->name('get_current_temperature');
        $toolResult->output('{"temperature":69}');

        $response = $provider->continueResponse($request, $previousResponse, array($toolResult));

        $this->assertSame('resp_previous', $client->requests[0]['payload']['previous_response_id']);
        $this->assertSame('function_call_output', $client->requests[0]['payload']['input'][1]['type']);
        $this->assertSame('call_123', $client->requests[0]['payload']['input'][1]['call_id']);
        $this->assertSame('The temperature is 69°F.', $response->text());
    }

    public function testEmbedPostsEmbeddingPayloadAndReturnsNormalizedVectors()
    {
        $client = new FakeOpenAIClient(array(
            array(
                'model' => 'text-embedding-3-small',
                'data' => array(
                    array(
                        'index' => 0,
                        'embedding' => array(0.1, 0.2, 0.3),
                    ),
                ),
                'usage' => array(
                    'prompt_tokens' => 3,
                    'total_tokens' => 3,
                ),
            ),
        ));

        $provider = new OpenAIProvider($client, new OpenAIMapper());
        $request = new EmbeddingRequest();
        $request->model('text-embedding-3-small');
        $request->input('hello');
        $request->option('dimensions', 3);

        $result = $provider->embed($request);

        $this->assertSame('embeddings', $client->requests[0]['path']);
        $this->assertSame('hello', $client->requests[0]['payload']['input']);
        $this->assertSame(3, $client->requests[0]['payload']['dimensions']);
        $this->assertSame(array(0.1, 0.2, 0.3), $result->vector());
        $this->assertSame(3, $result->usage()['total_tokens']);
    }
}
