<?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 Illuminate\Http\Client\Request as ClientRequest;
use Illuminate\Support\Facades\Http;
use Laravel\Ai\Tools\Request;
use Tests\TestCase;

/**
 * Making a pixel, which Events Manager calls a dataset.
 *
 * A buyer whose brand has no pixel on the account had nowhere to go: the list
 * showed other people's, and choosing one of those is how an AttestPath
 * campaign ended up attributing conversions to StockPrices.
 *
 * The object cannot be deleted through the API, only unshared, so every call
 * here leaves something behind for good. That is why this is its own tool and
 * not a branch of choose_pixel, and why an existing pixel of the same name is
 * reused rather than duplicated.
 */
class CreatingAPixelFromTheChatTest extends TestCase
{
    use RefreshDatabase;

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

        config(['platforms.meta.token' => 'test-token']);

        $this->actingAs(User::factory()->create());
        app(Workspace::class)->bindTo('conv-create-pixel');
    }

    private function campaign(array $attributes = []): Campaign
    {
        $campaign = Campaign::create([
            'user_id' => auth()->id(),
            'name' => 'AttestPath campaign',
            'platform' => 'meta',
            'status' => 'draft',
            'ad_account_id' => 'act_2220667645134722',
            'landing_url' => 'https://attestpath.ai',
            ...$attributes,
        ]);

        app(Workspace::class)->focusOn($campaign);

        return $campaign;
    }

    /** @param list<array<string,mixed>> $existing */
    private function metaReturning(array $existing, string $newId = '98765'): void
    {
        Http::fake([
            '*/adspixels*' => function (ClientRequest $request) use ($existing, $newId) {
                if ($request->method() === 'POST') {
                    return Http::response(['id' => $newId]);
                }

                return Http::response(['data' => $existing]);
            },
            '*' => Http::response(['id' => 'act_2220667645134722', 'business' => null]),
        ]);
    }

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

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

    public function test_a_pixel_is_created_and_selected(): void
    {
        $this->metaReturning([]);
        $campaign = $this->campaign();

        $result = $this->create(['name' => 'AttestPath']);

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

    /** The name goes to Meta as given. */
    public function test_the_name_reaches_meta(): void
    {
        $this->metaReturning([]);
        $this->campaign();

        $this->create(['name' => 'AttestPath']);

        Http::assertSent(fn (ClientRequest $r): bool => $r->method() === 'POST'
            && str_contains($r->url(), 'adspixels')
            && ($r->data()['name'] ?? null) === 'AttestPath');
    }

    /**
     * A pixel of that name already there is reused, not duplicated.
     *
     * Two pixels called the same thing is permanent: neither can be removed,
     * both appear in every later list, and nobody can tell which one the site
     * is firing.
     */
    public function test_an_existing_pixel_of_that_name_is_reused(): void
    {
        $this->metaReturning([['id' => '111', 'name' => 'AttestPath']]);
        $campaign = $this->campaign();

        $result = $this->create(['name' => 'attestpath']);

        $this->assertTrue($result['ok']);
        $this->assertFalse($result['created']);
        $this->assertSame('111', $campaign->refresh()->pixel_id);

        Http::assertNotSent(fn (ClientRequest $r): bool => $r->method() === 'POST' && str_contains($r->url(), 'adspixels'));
    }

    /** A pixel belonging to someone else is not treated as a match. */
    public function test_another_brands_pixel_does_not_count_as_existing(): void
    {
        $this->metaReturning([['id' => '111', 'name' => 'StockPrices']]);
        $this->campaign();

        $this->assertTrue($this->create(['name' => 'AttestPath'])['created']);
    }

    /** Google has no pixels, so it is told rather than sent somewhere odd. */
    public function test_a_google_campaign_is_refused(): void
    {
        $this->metaReturning([]);
        $this->campaign(['platform' => 'google', 'ad_account_id' => '3460855874']);

        $result = $this->create(['name' => 'AttestPath']);

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

    /** A pixel is created on an account, so there has to be one. */
    public function test_an_unverified_ad_account_is_refused(): void
    {
        $this->metaReturning([]);
        $this->campaign(['ad_account_id' => null]);

        $this->assertFalse($this->create(['name' => 'AttestPath'])['ok']);
    }

    /** An unnamed pixel is refused, because the name is the only thing that lasts. */
    public function test_a_missing_name_is_refused(): void
    {
        $this->metaReturning([]);
        $this->campaign();

        $result = $this->create([]);

        $this->assertFalse($result['ok']);
        $this->assertStringContainsString('name it after the brand', strtolower($result['error']));
    }

    /** Meta accepting without returning an id is a failure, not a success. */
    public function test_a_response_with_no_id_is_not_reported_as_created(): void
    {
        Http::fake([
            '*/adspixels*' => fn (ClientRequest $r) => $r->method() === 'POST'
                ? Http::response(['success' => true])
                : Http::response(['data' => []]),
            '*' => Http::response(['id' => 'act_2220667645134722', 'business' => null]),
        ]);

        $campaign = $this->campaign();

        $this->assertFalse($this->create(['name' => 'AttestPath'])['ok']);
        $this->assertNull($campaign->refresh()->pixel_id);
    }

    /** The reply says the two things a buyer will not guess. */
    public function test_the_reply_says_it_must_be_installed_and_cannot_be_deleted(): void
    {
        $this->metaReturning([]);
        $this->campaign();

        $note = strtolower($this->create(['name' => 'AttestPath'])['note']);

        $this->assertStringContainsString('installed', $note);
        $this->assertStringContainsString('cannot be deleted', $note);
    }
}
