<?php

namespace Tests\Feature;

use App\Agent\ToolRegistry;
use App\Agent\Workspace;
use App\Models\Campaign;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Laravel\Ai\Tools\Request;
use Tests\TestCase;

/**
 * The Google account is checked when it is adopted, not when it is used.
 *
 * Campaign 97 on arb-dev is what the old order cost. Google's account is taken
 * from configuration rather than chosen, and it was written to the campaign
 * without anyone asking whether it was permitted. Every following question was
 * answered, three ads were written, publish was approved, and only then did the
 * guardrail say "3460855874 is not on the allowed list" against a list holding
 * two Meta accounts and no Google one. The campaign ended in status=failed with
 * no external id, and nothing before that moment had any reason to doubt it.
 *
 * Meta's branch builds its list from the allowed accounts and LinkedIn's
 * filters against them, so Google was the one platform that skipped the
 * question entirely.
 */
class GoogleAccountIsCheckedBeforeItIsAdoptedTest extends TestCase
{
    use RefreshDatabase;

    protected Campaign $campaign;

    protected function setUp(): void
    {
        parent::setUp();

        $this->actingAs(User::factory()->create());

        app(Workspace::class)->bindTo('conv-google-account');

        $this->campaign = Campaign::create([
            'user_id' => auth()->id(),
            'name' => 'Google campaign',
            'platform' => 'google',
            'status' => 'draft',
        ]);

        app(Workspace::class)->produced($this->campaign);

        // The shared connection is built from configuration rather than read
        // from a row, which is the whole reason this account arrives without
        // anybody having chosen it.
        config([
            'services.google_ads.refresh_token' => 'test-refresh-token',
            'services.google_ads.customer_id' => '3460855874',
        ]);
    }

    private function listAccounts(): array
    {
        $result = collect(app(ToolRegistry::class)->resolve())
            ->first(fn ($t) => $t->name() === 'campaign__list_ad_accounts')
            ->handle(new Request([]));

        return json_decode((string) $result, true);
    }

    /** The defect: an account nothing could publish to, adopted without comment. */
    public function test_an_account_that_is_not_allowed_is_refused_at_the_first_step(): void
    {
        config(['platforms.guardrails.allowed_ad_accounts' => [
            'act_2220667645134722', 'act_1418821929380936',
        ]]);

        $result = $this->listAccounts();

        $this->assertFalse($result['ok']);
        $this->assertStringContainsString('3460855874', $result['error']);
    }

    /** And the campaign is left alone, rather than carrying an id it cannot use. */
    public function test_the_campaign_does_not_keep_an_account_it_cannot_publish_to(): void
    {
        config(['platforms.guardrails.allowed_ad_accounts' => ['act_2220667645134722']]);

        $this->listAccounts();

        $this->assertNull($this->campaign->refresh()->ad_account_id);
    }

    /** The reply says who can fix it, because the buyer cannot. */
    public function test_the_refusal_names_the_setting_rather_than_asking_the_user(): void
    {
        config(['platforms.guardrails.allowed_ad_accounts' => ['act_2220667645134722']]);

        $result = $this->listAccounts();

        $this->assertStringContainsString('PLATFORM_ALLOWED_AD_ACCOUNTS', $result['error']);
        $this->assertStringContainsString('administrator', $result['note']);
    }

    /** An allowed account is still adopted without a question, which is the point of it. */
    public function test_an_allowed_account_is_adopted_silently(): void
    {
        config(['platforms.guardrails.allowed_ad_accounts' => [
            'act_2220667645134722', '3460855874',
        ]]);

        $result = $this->listAccounts();

        $this->assertTrue($result['ok'], $result['error'] ?? '');
        $this->assertSame('3460855874', $this->campaign->refresh()->ad_account_id);
    }

    /**
     * A Meta entry does not authorise the Google account with the same digits.
     *
     * The allow-list is one flat variable for every platform, so this is the
     * trap next door to the one above.
     */
    public function test_a_meta_entry_with_the_same_digits_does_not_let_google_through(): void
    {
        config(['platforms.guardrails.allowed_ad_accounts' => ['act_3460855874']]);

        $result = $this->listAccounts();

        $this->assertFalse($result['ok']);
    }

    /** An empty list fails closed, the same as the publish guardrail does. */
    public function test_an_empty_allow_list_refuses_rather_than_permits(): void
    {
        config(['platforms.guardrails.allowed_ad_accounts' => []]);

        $this->assertFalse($this->listAccounts()['ok']);
    }
}
