<?php
namespace boru\ai\Conversation\Tool;

use boru\ai\AI;
use boru\ai\Conversation\Conversation;
use boru\ai\Conversation\ConversationNote;
use boru\ai\Runtime\AbstractTool;
use boru\ai\Runtime\ToolExecutionContext;
use boru\ai\Runtime\ToolPromptAdditionInterface;

class ReplaceConversationNotesTool extends AbstractTool implements ToolPromptAdditionInterface
{
    public function name()
    {
        return 'replace_conversation_notes';
    }

    public function description()
    {
        return 'Replace the current conversation note set with a curated list of structured notes.';
    }

    public function schema()
    {
        return array(
            'type' => 'object',
            'properties' => array(
                'notes' => array(
                    'type' => 'array',
                    'items' => array(
                        'type' => 'object',
                        'properties' => array(
                            'text' => array('type' => 'string'),
                            'kind' => array('type' => 'string'),
                            'confidence' => array('type' => 'number'),
                        ),
                        'required' => array('text'),
                    ),
                    'description' => 'Full replacement note set.',
                ),
            ),
            'required' => array('notes'),
        );
    }

    public function promptAddition()
    {
        return 'When the current note set has become stale or should be curated as a whole, replace the conversation notes with an updated structured set.';
    }

    public function handle(array $arguments, ToolExecutionContext $context = null)
    {
        $conversation = $this->requireConversation($context);
        $conversation->memory()->clearNotes();

        $notes = isset($arguments['notes']) && is_array($arguments['notes']) ? $arguments['notes'] : array();
        $turnNumber = $this->inferSourceTurnNumber($conversation);

        foreach ($notes as $item) {
            if (!is_array($item) || !isset($item['text'])) {
                continue;
            }

            $note = new ConversationNote();
            $note->text($item['text']);
            $note->kind(isset($item['kind']) && $item['kind'] !== '' ? $item['kind'] : 'note');
            if (isset($item['confidence'])) {
                $note->confidence($item['confidence']);
            }
            if ($turnNumber !== null) {
                $note->sourceTurnNumber($turnNumber);
            }
            $conversation->memory()->addNote($note);
        }

        AI::persistence()->saveConversation($conversation);
        return $conversation->memory()->toArray();
    }

    protected function requireConversation(ToolExecutionContext $context = null)
    {
        $request = $context ? $context->request() : null;
        $conversation = $request ? $request->metadata('conversation') : null;
        if (!$conversation instanceof Conversation) {
            throw new \RuntimeException('Conversation memory tools require an active conversation context');
        }
        return $conversation;
    }

    protected function inferSourceTurnNumber(Conversation $conversation)
    {
        $turn = $conversation->latestTurn();
        if (!$turn) {
            return null;
        }
        return $turn->number();
    }
}
