<?php

declare(strict_types=1);

namespace ContextPaging\Tests;

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

class ToolCallParserTest extends TestCase
{
    /**
     * Test extracting native OpenAI-style tool calls.
     */
    public function testExtractNativeToolCalls(): void
    {
        $parser = new ToolCallParser(ToolCallMode::NATIVE);

        $response = [
            "choices" => [
                [
                    "message" => [
                        "role" => "assistant",
                        "content" => null,
                        "tool_calls" => [
                            [
                                "id" => "call_123",
                                "function" => [
                                    "name" => "fetch_message",
                                    "arguments" => "{\"md5\":\"abc123\"}",
                                ],
                            ],
                        ],
                    ],
                ],
            ],
        ];

        $toolCalls = $parser->extract($response);

        $this->assertNotNull($toolCalls);
        $this->assertCount(1, $toolCalls);
        $this->assertEquals("fetch_message", $toolCalls[0]["name"]);
        $this->assertEquals(["md5" => "abc123"], $toolCalls[0]["arguments"]);
    }

    /**
     * Test extracting raw tool calls from content.
     */
    public function testExtractRawToolCalls(): void
    {
        $parser = new ToolCallParser(ToolCallMode::RAW);

        // The actual content from SmolLM3 response
        $rawContent = chr(0xD9) . chr(0xA7) . "{\"name\": \"web_search\", \"arguments\": {\"query\": \"nvidia stock\"}}" . chr(0xD9) . chr(0xA7);
        
        $response = [
            "choices" => [
                [
                    "message" => [
                        "role" => "assistant",
                        "content" => $rawContent,
                        "tool_calls" => [],
                    ],
                ],
            ],
        ];

        $toolCalls = $parser->extract($response);

        $this->assertNotNull($toolCalls);
        $this->assertGreaterThanOrEqual(1, count($toolCalls));
        $this->assertEquals("web_search", $toolCalls[0]["name"]);
    }

    /**
     * Test auto-detect mode picks native tool calls.
     */
    public function testAutoDetectNative(): void
    {
        $parser = new ToolCallParser(ToolCallMode::AUTO);

        $response = [
            "choices" => [
                [
                    "message" => [
                        "role" => "assistant",
                        "content" => null,
                        "tool_calls" => [
                            [
                                "id" => "call_456",
                                "function" => [
                                    "name" => "fetch_message",
                                    "arguments" => "{\"md5\":\"def456\"}",
                                ],
                            ],
                        ],
                    ],
                ],
            ],
        ];

        $detectedMode = $parser->detectMode($response);
        $this->assertEquals(ToolCallMode::NATIVE, $detectedMode);

        $toolCalls = $parser->extract($response);
        $this->assertNotNull($toolCalls);
    }

    /**
     * Test no tool calls returns null.
     */
    public function testNoToolCalls(): void
    {
        $parser = new ToolCallParser(ToolCallMode::AUTO);

        $response = [
            "choices" => [
                [
                    "message" => [
                        "role" => "assistant",
                        "content" => "Hello! How can I help you?",
                    ],
                ],
            ],
        ];

        $toolCalls = $parser->extract($response);
        $this->assertNull($toolCalls);
    }

    /**
     * Test hasToolCalls helper.
     */
    public function testHasToolCalls(): void
    {
        $parser = new ToolCallParser(ToolCallMode::NATIVE);

        $withTools = [
            "choices" => [
                ["message" => ["tool_calls" => [["function" => ["name" => "test"]]]]],
            ],
        ];

        $withoutTools = [
            "choices" => [
                ["message" => ["content" => "Hello"]],
            ],
        ];

        $this->assertTrue($parser->hasToolCalls($withTools));
        $this->assertFalse($parser->hasToolCalls($withoutTools));
    }
}