<?php

namespace Tests\Feature;

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

/**
 * A campaign created before the page was read still gets the page's name.
 *
 * StartCampaign names from the landing page when there is one, but on a first
 * message the campaigns exist before the URL does: "create a campaign across
 * multiple platforms", platforms picked, and only then the page. Every campaign
 * was therefore called "Meta campaign 25 Sep 05:48" and stayed that way, and
 * nothing went back once the page was read.
 *
 * That name reaches the ad platform. On arb-dev on 25 Sep a campaign published
 * to Meta as "Meta campaign 25 Sep 05:48" while the chat had shown the buyer
 * "A Platform with Autonomous Intelligence to Achieve Growth", so searching Ads
 * Manager for the only name they had been given found nothing.
 *
 * Renamed only where provenance says fallback, which means "generated because
 * nobody said otherwise". A name somebody typed is never touched.
 */
class PlaceholderNamesAreReplacedByThePageTest extends TestCase
{
    use RefreshDatabase;

    protected Workspace $workspace;

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

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

        $this->workspace = app(Workspace::class);
        $this->workspace->bindTo('conv-placeholder-names');

        $this->app->bind(LandingPageAnalyzer::class, fn (): object => new class extends LandingPageAnalyzer
        {
            public function __construct() {}

            public function analyze(string $url): LandingPageAnalysis
            {
                return new LandingPageAnalysis(
                    url: $url,
                    title: 'WebCrawlers',
                    description: 'Enterprise data extraction.',
                    headings: ['A Platform with Autonomous Intelligence to Achieve Growth'],
                    text: 'Enterprise data extraction and autonomous SEO.',
                    keywords: ['extraction', 'seo'],
                );
            }
        });
    }

    private function campaign(string $platform, string $name, string $source): Campaign
    {
        $campaign = Campaign::create([
            'user_id' => auth()->id(),
            'name' => $name,
            'platform' => $platform,
            'status' => 'draft',
        ]);

        $this->workspace->produced($campaign, focus: false);
        $this->workspace->recordSource($campaign, 'name', $source);

        return $campaign;
    }

    private function readThePage(): void
    {
        collect(app(ToolRegistry::class)->resolve())
            ->first(fn ($t) => $t->name() === 'campaign__analyze_landing_page')
            ->handle(new Request(['url' => 'https://webcrawlers.com']));
    }

    /** The defect: the placeholder survives the page being read. */
    public function test_a_generated_name_is_replaced_once_the_page_is_read(): void
    {
        $meta = $this->campaign('meta', 'Meta campaign 25 Sep 05:48', ArtifactFieldSource::FALLBACK);

        $this->readThePage();

        $this->assertSame(
            'A Platform with Autonomous Intelligence to Achieve Growth - Meta',
            $meta->fresh()->name,
        );
    }

    /** Every platform on the conversation, not only the one in focus. */
    public function test_every_campaign_with_a_generated_name_is_renamed(): void
    {
        $meta = $this->campaign('meta', 'Meta campaign 25 Sep 05:48', ArtifactFieldSource::FALLBACK);
        $google = $this->campaign('google', 'Google campaign 25 Sep 05:48', ArtifactFieldSource::FALLBACK);

        $this->readThePage();

        $this->assertStringEndsWith('- Meta', $meta->fresh()->name);
        $this->assertStringEndsWith('- Google Ads', $google->fresh()->name);
        $this->assertStringStartsWith('A Platform with Autonomous', $google->fresh()->name);
    }

    /** A name the buyer typed is theirs and is left alone. */
    public function test_a_user_stated_name_is_never_overwritten(): void
    {
        $chosen = $this->campaign('meta', 'Q4 Enterprise Push', ArtifactFieldSource::USER_STATED);

        $this->readThePage();

        $this->assertSame('Q4 Enterprise Push', $chosen->fresh()->name);
    }

    /**
     * And a campaign already on the platform keeps the name that went out.
     *
     * Renaming it here would make our record disagree with what is live
     * without changing anything on the platform.
     */
    public function test_a_published_campaign_is_not_renamed(): void
    {
        $live = $this->campaign('meta', 'Meta campaign 25 Sep 05:48', ArtifactFieldSource::FALLBACK);
        $live->update(['status' => 'published', 'external_campaign_id' => '52626656086665']);

        $this->readThePage();

        $this->assertSame('Meta campaign 25 Sep 05:48', $live->fresh()->name);
    }

    /**
     * The name stops being reported as an unanswered placeholder.
     *
     * Raised on the PR: the provenance was never moved off FALLBACK, so the
     * panel kept showing a name taken from the page as though nobody had
     * answered the question yet.
     */
    public function test_a_name_taken_from_the_page_is_recorded_as_inferred(): void
    {
        $campaign = $this->campaign('meta', 'Meta campaign 25 Sep 05:48', ArtifactFieldSource::FALLBACK);

        $this->readThePage();

        $this->assertSame(
            ArtifactFieldSource::MODEL_INFERRED,
            $this->workspace->sourcesFor($campaign->refresh())['name'] ?? null,
        );
    }

    /** A name the buyer typed is still never touched. */
    public function test_a_name_the_user_typed_survives_a_second_analysis(): void
    {
        $campaign = $this->campaign('meta', 'My own name', ArtifactFieldSource::USER_STATED);

        $this->readThePage();

        $this->assertSame('My own name', $campaign->refresh()->name);
    }
}
