<?php

namespace App\Agent\Tools\Campaign;

use App\Agent\Tools\Campaign\Concerns\ActsOnFocusedCampaign;
use App\Agent\Workspace;
use App\Campaigns\Platforms\Platforms;
use App\Services\Meta\Meta;
use App\Services\Meta\MetaException;
use Illuminate\Contracts\JsonSchema\JsonSchema;
use Laravel\Ai\Contracts\Tool;
use Laravel\Ai\Tools\Request;
use Stringable;

/**
 * The ad accounts this product may use.
 *
 * Reads the allow list and fetches each account directly rather than asking the
 * platform for everything the token can see. Those are the only usable accounts
 * anyway, and the me/adaccounts edge sweeps every account on the token, sharing
 * an hourly limit with production reporting jobs and getting throttled first.
 */
class ListAdAccounts implements Tool
{
    use ActsOnFocusedCampaign;

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

    public function description(): Stringable|string
    {
        return 'List the ad accounts available. If the user already named an account, '
            .'skip this and call verify_ad_account instead.';
    }

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

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

        // These are Meta accounts. Returning them for a campaign on another
        // platform invites the model to offer them as a choice, and then to ask
        // for an account id for a platform that is not connected at all.
        if ($campaign && $campaign->platform !== 'meta') {
            return $this->json([
                'ok' => false,
                'error' => sprintf(
                    '%s is not connected yet, so it has no ad accounts to list.',
                    app(Platforms::class)->for($campaign)->name(),
                ),
                'note' => 'Say it is not connected. Do not ask the user for an account id for it.',
            ]);
        }

        $allowed = (array) config('platforms.guardrails.allowed_ad_accounts');

        if ($allowed === []) {
            return $this->json([
                'ok' => false,
                'error' => 'No ad accounts are configured. Someone needs to set PLATFORM_ALLOWED_AD_ACCOUNTS.',
            ]);
        }

        $meta = $this->meta->on($this->focused()?->id, 'agent');
        $accounts = [];
        $unreachable = [];

        foreach ($allowed as $id) {
            try {
                $account = $meta->adAccount($id);

                $accounts[] = [
                    'id' => $account['id'],
                    'name' => $account['name'] ?? null,
                    'currency' => $account['currency'] ?? null,
                    'usable' => (int) ($account['account_status'] ?? 0) === 1,
                ];
            } catch (MetaException $e) {
                $unreachable[] = ['id' => $id, 'reason' => $e->getMessage()];
            }
        }

        return $this->json(array_filter([
            'ok' => true,
            'ad_accounts' => $accounts,
            'unreachable' => $unreachable ?: null,
        ], fn ($v) => $v !== null));
    }
}
