<?php
namespace boru\ai\Tests\Compat\LegacyTool;

use boru\ai\AI;
use boru\ai\Compat\LegacyTool\LegacyToolAdapter;
use boru\ai\Compat\LegacyTool\LegacyToolInvocation;
use boru\ai\Runtime\ToolExecutionContext;
use PHPUnit\Framework\TestCase;

class LegacyToolAdapterTest extends TestCase
{
    protected function setUp(): void
    {
        if (!class_exists(\boru\boruai\Models\Functions\FunctionBase::class)) {
            $this->markTestSkipped('Legacy BoruAI compatibility tests require the optional boru/boruai package.');
        }
    }

    public function testFromClassBuildsNativeToolDefinitionFromLegacyDefinition()
    {
        $definition = LegacyToolAdapter::fromClass(__NAMESPACE__ . '\\LegacyWeatherTool');

        $this->assertSame('get_current_temperature', $definition->name());
        $this->assertSame('Get the current temperature for a specific location', $definition->description());

        $schema = $definition->schema();
        $this->assertSame('object', $schema['type']);
        $this->assertArrayHasKey('location', $schema['properties']);
        $this->assertArrayHasKey('unit', $schema['properties']);
        $this->assertSame(array('location', 'unit'), $schema['required']);

        $metadata = $definition->metadata();
        $this->assertTrue($metadata['legacy_adapter']);
        $this->assertSame(__NAMESPACE__ . '\\LegacyWeatherTool', $metadata['legacy_class']);
        $this->assertTrue($metadata['legacy_strict']);
        $this->assertSame('Use this only when the user asks for weather.', $metadata['legacy_agent_instructions']);
        $this->assertSame('get_current_temperature', $metadata['legacy_compiled']['name']);
    }

    public function testAdaptedLegacyToolInvokesWithLegacyStyleAccessors()
    {
        $definition = LegacyToolAdapter::fromClass(__NAMESPACE__ . '\\LegacyWeatherTool');
        $context = new ToolExecutionContext(null, null, null, array(
            'temp' => 72,
            'user' => array(
                'region' => 'southeast',
            ),
        ));

        $result = $definition->invoke(array(
            'location' => 'Atlanta, GA',
            'unit' => 'Fahrenheit',
            'meta' => array(
                'requested_by' => 'test-suite',
            ),
        ), $context);

        $decoded = json_decode($result, true);

        $this->assertSame('Atlanta, GA', $decoded['location']);
        $this->assertSame('Fahrenheit', $decoded['unit']);
        $this->assertSame(72, $decoded['temperature']);
        $this->assertSame('test-suite', $decoded['requested_by']);
        $this->assertSame('southeast', $decoded['region']);
        $this->assertSame('legacy-compatible', $decoded['status']);
    }

    public function testLegacyInvocationSupportsDotGetSetAndContextAccess()
    {
        $context = new ToolExecutionContext(null, null, null, array(
            'repo' => array(
                'name' => 'ai',
            ),
        ));

        $invocation = new LegacyToolInvocation(array(
            'meta' => array(
                'requested_by' => 'initial',
            ),
        ), $context);

        $this->assertSame('initial', $invocation->get('meta.requested_by'));

        $invocation->set('meta.requested_by', 'updated');
        $this->assertSame('updated', $invocation->get('meta.requested_by'));
        $this->assertSame('ai', $invocation->context('repo.name'));
        $this->assertSame('fallback', $invocation->context('repo.branch', 'fallback'));
    }

    public function testAiFacadeCanRegisterLegacyTool()
    {
        $ai = new AI();
        $ai->addLegacyTool(__NAMESPACE__ . '\\LegacyWeatherTool');

        $tools = $ai->request()->tools();
        $this->assertCount(1, $tools);
        $this->assertSame('get_current_temperature', $tools[0]['name']);
        $this->assertTrue($tools[0]['metadata']['legacy_adapter']);
        $this->assertSame(__NAMESPACE__ . '\\LegacyWeatherTool', $tools[0]['metadata']['legacy_class']);
    }
}

if (class_exists(\boru\boruai\Models\Functions\FunctionBase::class)) {
    class LegacyWeatherTool extends \boru\boruai\Models\Functions\FunctionBase
    {
        public static function functionDefinitions()
        {
            $tool = new \boru\boruai\Models\ToolDefinition();
            $tool->name(static::functionName());
            $tool->description(static::functionDescription());
            static::setupParameters($tool);
            $tool->register(static::class);
            return $tool;
        }

        public static function functionName()
        {
            return 'get_current_temperature';
        }

        public static function functionDescription()
        {
            return 'Get the current temperature for a specific location';
        }

        public static function agentInstructions()
        {
            return 'Use this only when the user asks for weather.';
        }

        public static function setupParameters($toolDefinition)
        {
            $toolDefinition->addString('location', 'The city and state, e.g., San Francisco, CA');
            $toolDefinition->addString('unit', 'The temperature unit to use. Infer this from the user\'s location.', array('Fahrenheit', 'Celsius'));
        }

        public static function handle($tool)
        {
            $tool->set('status', 'legacy-compatible');

            return json_encode(array(
                'location' => $tool->get('location'),
                'unit' => $tool->get('unit'),
                'temperature' => $tool->context('temp', 69),
                'requested_by' => $tool->get('meta.requested_by'),
                'region' => $tool->context('user.region'),
                'status' => $tool->get('status'),
            ));
        }
    }
}
