<?php

namespace Tests\Feature;

use App\Agent\Choices;
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;

/**
 * How long it runs, offered as lengths that say what they are for.
 *
 * Every option was "14 days", which tells a media buyer everything and a
 * first-time advertiser nothing: the question is not how many days but what
 * each length is for, and that is the difference between picking one and
 * guessing one.
 *
 * Two lengths have a well understood purpose and now carry it. The rest stay
 * as plain lengths rather than being given invented names, and none were
 * removed: naming three options is not a reason to take the others away.
 */
class SchedulePresetsTest extends TestCase
{
    use RefreshDatabase;

    private function offerFor(string $budgetMode): array
    {
        $this->actingAs(User::factory()->create());

        $workspace = app(Workspace::class);
        $workspace->bindTo('conv-schedule-'.$budgetMode);

        $campaign = Campaign::create([
            'user_id' => auth()->id(),
            'name' => 'Winter Sale',
            'platform' => 'meta',
            'status' => 'draft',
            'budget' => 20,
            'budget_mode' => $budgetMode,
        ]);

        $workspace->produced($campaign);

        collect(app(ToolRegistry::class)->resolve())
            ->first(fn ($t) => $t->name() === 'campaign__set_schedule')
            ->handle(new Request([]));

        return collect(app(Choices::class)->all())->firstWhere('field', 'ends_at')['options'];
    }

    public function test_continuous_is_offered_first_on_a_daily_budget(): void
    {
        $options = $this->offerFor('daily');

        $this->assertSame('Continuous', $options[0]['label']);
        $this->assertSame('', $options[0]['value'], 'Continuous means no end date.');
        $this->assertSame('Suggested', $options[0]['badge']);
    }

    public function test_the_named_lengths_say_what_they_are_for(): void
    {
        $byLabel = collect($this->offerFor('daily'))->keyBy('label');

        $this->assertArrayHasKey('14-day test', $byLabel);
        $this->assertArrayHasKey('30-day flight', $byLabel);

        $this->assertStringContainsString('learn what works', $byLabel['14-day test']['hint']);
        $this->assertStringContainsString('full month', $byLabel['30-day flight']['hint']);
    }

    /** The end date stays in the hint, because it is the thing being chosen. */
    public function test_every_length_still_says_when_it_ends(): void
    {
        foreach ($this->offerFor('daily') as $option) {
            if ($option['value'] === '') {
                continue;
            }

            $this->assertStringStartsWith('Ends ', $option['hint']);
        }
    }

    /** Nothing was taken away to make room for the named ones. */
    public function test_the_unnamed_lengths_are_still_offered(): void
    {
        $labels = array_column($this->offerFor('daily'), 'label');

        foreach (['7 days', '60 days', '90 days'] as $length) {
            $this->assertContains($length, $labels);
        }
    }

    /**
     * A lifetime budget is the total to spend by a date, so Meta refuses it
     * without one and the publish gate refuses first. Continuous cannot be
     * offered, and the suggestion moves to the lower commitment length.
     */
    public function test_a_lifetime_budget_cannot_run_continuously(): void
    {
        $options = $this->offerFor('lifetime');

        $this->assertNotContains('Continuous', array_column($options, 'label'));

        $suggested = collect($options)->firstWhere('badge', 'Suggested');

        $this->assertNotNull($suggested, 'Nothing was suggested where an end date is compulsory.');
        $this->assertSame('14-day test', $suggested['label']);
    }
}
