<?php

namespace App\Agent\Tools;

use App\Agent\Workspace;
use App\Models\ConversationArtifact;
use Illuminate\Contracts\JsonSchema\JsonSchema;
use Laravel\Ai\Contracts\Tool;
use Laravel\Ai\Tools\Request;
use Stringable;

/**
 * Point the conversation at a different thing it has already produced.
 *
 * Needed because one chat can hold several campaigns and landing pages, so
 * "make that one $30 a day" has to be resolvable to a specific row.
 */
class SwitchFocus implements Tool
{
    public function __construct(private readonly Workspace $workspace) {}

    public function description(): Stringable|string
    {
        return 'Switch to a different item already created in this conversation, so later '
            .'instructions apply to it. Use the id shown in the conversation state. Do not '
            .'call this straight after creating something; creating already focuses it.';
    }

    public function schema(JsonSchema $schema): array
    {
        return [
            'kind' => $schema->string()
                ->description('The kind of item, for example Campaign.')
                ->required(),
            'id' => $schema->integer()
                ->description('The numeric id of the item, as shown in the conversation state.')
                ->required(),
        ];
    }

    public function handle(Request $request): Stringable|string
    {
        $arguments = $request->all();

        $kind = (string) ($arguments['kind'] ?? '');
        $id = (int) ($arguments['id'] ?? 0);

        $link = $this->workspace->artifacts()
            ->first(fn (ConversationArtifact $link): bool => (int) $link->artifactable_id === $id
                && str_ends_with(strtolower($link->artifactable_type), strtolower($kind)));

        if (! $link || ! $link->artifactable) {
            return $this->json([
                'ok' => false,
                'error' => "No {$kind} with id {$id} in this conversation.",
                'available' => $this->workspace->artifacts()
                    ->map(fn (ConversationArtifact $l): string => class_basename($l->artifactable_type).' #'.$l->artifactable_id)
                    ->values()
                    ->all(),
            ]);
        }

        $this->workspace->focusOn($link->artifactable);

        return $this->json([
            'ok' => true,
            'now_in_focus' => class_basename($link->artifactable_type).' #'.$id,
        ]);
    }

    private function json(array $payload): string
    {
        return json_encode($payload, JSON_UNESCAPED_SLASHES);
    }
}
