<?php

namespace App\Agent\Tools\Campaign;

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

/**
 * How the campaign in focus bids.
 *
 * A target cost per lead or acquisition is expressed as COST_CAP with an
 * amount; without an amount the platform rejects the ad set.
 */
class SetBidding implements Tool
{
    use ActsOnFocusedCampaign;

    public function __construct(private readonly Workspace $workspace) {}

    public function description(): Stringable|string
    {
        return 'Set the bid strategy on the campaign in focus. Use COST_CAP with target_cost '
            .'when the user states a target cost per lead or per acquisition.';
    }

    public function schema(JsonSchema $schema): array
    {
        return [
            'strategy' => $schema->string()
                ->description('LOWEST_COST_WITHOUT_CAP, COST_CAP or LOWEST_COST_WITH_BID_CAP.')
                ->required(),
            'target_cost' => $schema->number()
                ->description('Target cost per result, required for COST_CAP and LOWEST_COST_WITH_BID_CAP.'),
        ];
    }

    public function handle(Request $request): Stringable|string
    {
        if (! $campaign = $this->focused()) {
            return $this->noCampaign();
        }

        $arguments = $request->all();
        $strategy = strtoupper(trim((string) ($arguments['strategy'] ?? '')));

        if (! in_array($strategy, Objectives::BID_STRATEGIES, true)) {
            return $this->json([
                'ok' => false,
                'error' => "[{$strategy}] is not a supported bid strategy.",
                'supported' => Objectives::BID_STRATEGIES,
            ]);
        }

        $needsAmount = $strategy !== 'LOWEST_COST_WITHOUT_CAP';
        $amount = isset($arguments['target_cost']) ? round((float) $arguments['target_cost'], 2) : null;

        if ($needsAmount && ! $amount) {
            return $this->json(['ok' => false, 'error' => "{$strategy} needs a target_cost."]);
        }

        $campaign->update([
            'bid_strategy' => $strategy,
            'bid_amount' => $needsAmount ? $amount : null,
        ]);

        $this->workspace->recordSource($campaign, 'bid_strategy', ArtifactFieldSource::USER_STATED);

        if ($needsAmount) {
            $this->workspace->recordSource($campaign, 'bid_amount', ArtifactFieldSource::USER_STATED);
        }

        return $this->json(array_filter([
            'ok' => true,
            'campaign_id' => $campaign->id,
            'strategy' => $strategy,
            'target_cost' => $needsAmount ? number_format($amount, 2, '.', '') : null,
        ], fn ($v) => $v !== null));
    }
}
