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

use boru\ai\Provider\Gemini\GeminiMapper;
use boru\ai\Provider\Gemini\GeminiProvider;
use boru\ai\Schema\Request;
use boru\ai\Schema\Response;
use boru\ai\Schema\ToolResult;
use boru\ai\Tests\Fakes\FakeGeminiClient;
use PHPUnit\Framework\TestCase;

class GeminiProviderTest extends TestCase
{
    public function testExecutePostsMappedRequestAndReturnsNormalizedResponse()
    {
        $client = new FakeGeminiClient(array(
            array(
                'responseId' => 'gem_resp_1',
                'modelVersion' => 'gemini-2.5-pro',
                'candidates' => array(
                    array(
                        'content' => array(
                            'parts' => array(
                                array(
                                    'text' => 'Hello from Gemini',
                                ),
                            ),
                        ),
                    ),
                ),
            ),
        ));

        $provider = new GeminiProvider($client, new GeminiMapper());
        $request = new Request();
        $request->model('gemini-2.5-pro')->addMessage('Hello');

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

        $this->assertInstanceOf(Response::class, $response);
        $this->assertSame('generateContent', $client->requests[0]['method']);
        $this->assertSame('gemini-2.5-pro', $client->requests[0]['model']);
        $this->assertSame('Hello from Gemini', $response->text());
    }

    public function testContinueResponseAddsPriorModelContentAndToolResultsAndReturnsNormalizedResponse()
    {
        $client = new FakeGeminiClient(array(
            array(
                'responseId' => 'gem_resp_2',
                'modelVersion' => 'gemini-2.5-pro',
                'candidates' => array(
                    array(
                        'content' => array(
                            'parts' => array(
                                array(
                                    'text' => 'The temperature is 69°F.',
                                ),
                            ),
                        ),
                    ),
                ),
            ),
        ));

        $provider = new GeminiProvider($client, new GeminiMapper());
        $request = new Request();
        $request->model('gemini-2.5-pro')->addMessage('Weather?');

        $previousResponse = new Response();
        $previousResponse->id('gem_prev_resp');
        $previousResponse->raw(array(
            'candidates' => array(
                array(
                    'content' => array(
                        'role' => 'model',
                        'parts' => array(
                            array(
                                'functionCall' => array(
                                    'id' => 'call_123',
                                    'name' => 'get_current_temperature',
                                    'args' => array(
                                        'location' => 'Atlanta, GA',
                                        'unit' => 'Fahrenheit',
                                    ),
                                ),
                            ),
                        ),
                    ),
                ),
            ),
        ));

        $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('model', $client->requests[0]['payload']['contents'][1]['role']);
        $this->assertSame('get_current_temperature', $client->requests[0]['payload']['contents'][1]['parts'][0]['functionCall']['name']);
        $this->assertSame('user', $client->requests[0]['payload']['contents'][2]['role']);
        $this->assertSame('get_current_temperature', $client->requests[0]['payload']['contents'][2]['parts'][0]['functionResponse']['name']);
        $this->assertSame('call_123', $client->requests[0]['payload']['contents'][2]['parts'][0]['functionResponse']['id']);
        $this->assertSame(69, $client->requests[0]['payload']['contents'][2]['parts'][0]['functionResponse']['response']['temperature']);
        $this->assertSame('The temperature is 69°F.', $response->text());
    }
}
