<?php

declare(strict_types=1);

namespace ContextPaging\Tests;

use ContextPaging\ToolFormatter;
use ContextPaging\ToolCallMode;
use PHPUnit\Framework\TestCase;

class ToolFormatterTest extends TestCase
{
    /**
     * Test native format produces tools array.
     */
    public function testFormatNative(): void
    {
        $formatter = new ToolFormatter(ToolCallMode::NATIVE);

        $tools = [
            [
                'name' => 'fetch_message',
                'description' => 'Retrieve a message',
                'parameters' => [
                    'type' => 'object',
                    'properties' => [
                        'md5' => ['type' => 'string'],
                    ],
                    'required' => ['md5'],
                ],
            ],
        ];

        $result = $formatter->formatForRequest($tools);

        $this->assertArrayHasKey('tools', $result);
        $this->assertArrayHasKey('tool_choice', $result);
        $this->assertEquals('auto', $result['tool_choice']);
        $this->assertCount(1, $result['tools']);
        $this->assertEquals('function', $result['tools'][0]['type']);
        $this->assertEquals('fetch_message', $result['tools'][0]['function']['name']);
    }

    /**
     * Test raw format returns empty array (tools go in system prompt).
     */
    public function testFormatRaw(): void
    {
        $formatter = new ToolFormatter(ToolCallMode::RAW);

        $tools = [
            [
                'name' => 'test_tool',
                'description' => 'A test tool',
                'parameters' => [
                    'type' => 'object',
                    'properties' => [
                        'query' => ['type' => 'string', 'description' => 'Search query'],
                    ],
                    'required' => ['query'],
                ],
            ],
        ];

        $result = $formatter->formatForRequest($tools);

        // Raw format returns empty array - tools are injected via buildPayload
        $this->assertEmpty($result);

        // Verify tools get injected into system prompt via buildPayload
        $messages = [
            ['role' => 'system', 'content' => 'You are a helpful assistant.'],
        ];
        $modifiedMessages = $formatter->injectToolsIntoMessages($messages, $tools);

        $this->assertStringContainsString('## Tools', $modifiedMessages[0]['content']);
        $this->assertStringContainsString('test_tool', $modifiedMessages[0]['content']);
    }

    /**
     * Test buildPayload with native mode.
     */
    public function testBuildPayloadNative(): void
    {
        $formatter = new ToolFormatter(ToolCallMode::NATIVE);

        $messages = [
            ['role' => 'user', 'content' => 'Hello'],
        ];

        $options = ['model' => 'gpt-4'];

        $tools = [ToolFormatter::FETCH_MESSAGE_TOOL];

        $payload = $formatter->buildPayload($messages, $options, $tools);

        $this->assertEquals($messages, $payload['messages']);
        $this->assertEquals('gpt-4', $payload['model']);
        $this->assertArrayHasKey('tools', $payload);
        $this->assertEquals('fetch_message', $payload['tools'][0]['function']['name']);
    }

    /**
     * Test buildPayload with raw mode injects into system prompt.
     */
    public function testBuildPayloadRaw(): void
    {
        $formatter = new ToolFormatter(ToolCallMode::RAW);

        $messages = [
            ['role' => 'system', 'content' => 'You are helpful.'],
            ['role' => 'user', 'content' => 'Hello'],
        ];

        $options = ['model' => 'test-model'];

        $tools = [ToolFormatter::FETCH_MESSAGE_TOOL];

        $payload = $formatter->buildPayload($messages, $options, $tools);

        // Raw mode does NOT add tools key
        $this->assertArrayNotHasKey('tools', $payload);
        // Instead, tools are injected into the system message
        $this->assertStringContainsString('fetch_message', $payload['messages'][0]['content']);
        $this->assertStringContainsString('You are helpful.', $payload['messages'][0]['content']);
    }

    /**
     * Test FETCH_MESSAGE_TOOL constant.
     */
    public function testFetchMessageToolDefinition(): void
    {
        $tool = ToolFormatter::FETCH_MESSAGE_TOOL;

        $this->assertEquals('fetch_message', $tool['name']);
        $this->assertArrayHasKey('md5', $tool['parameters']['properties']);
        $this->assertEquals(['md5'], $tool['parameters']['required']);
    }
}
