<?php

namespace App\Agent\Tools\Campaign;

use App\Agent\Tools\Campaign\Concerns\ActsOnFocusedCampaign;
use App\Agent\Workspace;
use App\Campaigns\Publisher;
use App\Support\Actor;
use Illuminate\Contracts\JsonSchema\JsonSchema;
use Laravel\Ai\Contracts\Tool;
use Laravel\Ai\Tools\Request;
use Stringable;
use Throwable;

/**
 * Stop a running campaign spending.
 *
 * Not gated behind an approval, and that is the considered position rather than an
 * omission. Approvals exist to stand between a buyer and their money leaving; this
 * is the direction that stops it. Asking somebody to confirm twice before they can
 * halt a campaign is a way to lose money, not a way to protect it.
 *
 * It is also what makes offering activation reasonable at all. A product that can
 * start a campaign and not stop it has handed the buyer a one-way door and sent
 * them to the platform's own interface to close it - which is exactly the position
 * they were in before any of this, in the other direction.
 */
class PauseCampaign implements Tool
{
    use ActsOnFocusedCampaign;

    public function __construct(
        private readonly Workspace $workspace,
        private readonly Publisher $publisher,
        private readonly Actor $actor,
    ) {}

    public function description(): Stringable|string
    {
        return 'Stop the campaign in focus so it stops spending. Call this as soon as the user asks '
            .'to pause, stop or halt it - it does not need approval, because stopping spend is not '
            .'something to make anybody confirm twice.';
    }

    public function schema(JsonSchema $schema): array
    {
        return [];
    }

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

        if (! $campaign->isPublished()) {
            return $this->json([
                'ok' => false,
                'error' => 'This campaign has not been published, so there is nothing running to stop.',
                'note' => 'Do not describe this as a failure. Nothing is spending.',
            ]);
        }

        if (! $campaign->isRunning()) {
            // Not an error. The buyer asked for a state the campaign is already in,
            // and telling them it "failed" would read as though it were spending.
            return $this->json([
                'ok' => true,
                'running' => false,
                'note' => 'It was already paused and is not spending. Say so in one line.',
            ]);
        }

        try {
            $this->publisher->pause($campaign, $this->actor->describe());
        } catch (Throwable $e) {
            return $this->json([
                'ok' => false,
                'running' => true,
                'error' => $e->getMessage(),
                'note' => 'It may still be spending. Say that plainly and tell them to pause it on '
                    .ucfirst($campaign->platform).' directly if this keeps failing.',
            ]);
        }

        return $this->json([
            'ok' => true,
            'running' => false,
            'campaign' => $campaign->name,
            'note' => 'It has stopped spending. Say so in one line, and that it can be started again '
                .'whenever they want.',
        ]);
    }
}
