<?php

namespace App\Agent\Tools\Campaign;

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

/**
 * Set the daily budget on the campaign in focus.
 *
 * The second half of the worked example: a tool that acts on whatever is in
 * focus rather than taking an id. This is what makes "make it thirty a day"
 * work in a conversation holding three campaigns.
 *
 * The ceiling here is a product limit, deliberately checked in plain code. The
 * model may propose any number; only this decides what is allowed.
 */
class SetCampaignBudget implements Tool
{
    public function __construct(private readonly Workspace $workspace) {}

    public function description(): Stringable|string
    {
        return 'Set the daily budget of the campaign currently in focus. Amount is in the '
            .'account currency. Switch focus first if the user means a different campaign.';
    }

    public function schema(JsonSchema $schema): array
    {
        return [
            'daily_budget' => $schema->number()
                ->description('Daily budget as a decimal amount, for example 20 or 37.50.')
                ->required(),
        ];
    }

    public function handle(Request $request): Stringable|string
    {
        $campaign = $this->workspace->focus();

        if (! $campaign instanceof Campaign) {
            return $this->json([
                'ok' => false,
                'error' => 'No campaign is in focus. Create one, or switch focus to an existing one, first.',
            ]);
        }

        $budget = round((float) ($request->all()['daily_budget'] ?? 0), 2);
        // The same ceiling the publish gate enforces. Two sources for one
        // limit meant a budget the tool accepted and the gate refused.
        $ceiling = (float) config('platforms.guardrails.max_daily_budget');

        if ($budget <= 0) {
            return $this->json(['ok' => false, 'error' => 'Daily budget must be greater than zero.']);
        }

        if ($budget > $ceiling) {
            return $this->json([
                'ok' => false,
                'error' => sprintf(
                    'A daily budget of %.2f is above the %.2f ceiling this product is configured to allow. '
                    .'Tell the user the limit rather than choosing a lower number yourself.',
                    $budget,
                    $ceiling,
                ),
            ]);
        }

        $campaign->update(['budget' => $budget]);
        $this->workspace->recordSource($campaign, 'budget', ArtifactFieldSource::USER_STATED);

        return $this->json([
            'ok' => true,
            'campaign_id' => $campaign->id,
            'daily_budget' => number_format($budget, 2, '.', ''),
        ]);
    }

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