<?php

namespace Tests\Feature;

use App\Models\Campaign;
use App\Models\CampaignPerformanceStat;
use App\Models\CampaignPerformanceSuggestion;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Http;
use Tests\TestCase;

class CampaignPerformanceMapTest extends TestCase
{
    use RefreshDatabase;

    public function test_map_writes_a_pending_pause_suggestion_from_stats(): void
    {
        $this->travelTo('2026-09-22 12:00:00');
        config(['campaign-performance.llm_enabled' => false]);

        $user = User::factory()->create();
        $campaign = Campaign::create([
            'user_id' => $user->id,
            'name' => 'Italy packages',
            'platform' => 'meta',
            'status' => 'published',
            'budget' => 20,
            'ad_account_id' => 'act_111',
            'external_campaign_id' => '1201',
        ]);

        $this->seedDailyStats($user, $campaign, 6.0, 0, 7);

        Http::fake();

        $this->artisan('campaigns:sync-performance', ['--map' => true])->assertSuccessful();

        $row = CampaignPerformanceSuggestion::query()->first();
        $this->assertNotNull($row);
        $this->assertSame('stop', $row->status);
        $this->assertSame('php', $row->source);
        $this->assertSame('pending', $row->action_state);
        $this->assertSame('stop', $row->snapshot['final_verdict'] ?? null);
        $this->assertSame('unknown', $row->snapshot['trend'] ?? null);
        $this->assertSame(0, $row->snapshot['last_7_hours']['hours'] ?? null);
        Http::assertNothingSent();
    }

    public function test_map_records_an_improving_trend_against_the_prior_week(): void
    {
        $this->travelTo('2026-09-22 12:00:00');
        config(['campaign-performance.llm_enabled' => false]);

        $user = User::factory()->create();
        $campaign = Campaign::create([
            'user_id' => $user->id,
            'name' => 'Italy packages',
            'platform' => 'meta',
            'status' => 'published',
            'budget' => 20,
            'ad_account_id' => 'act_111',
            'external_campaign_id' => '1201',
        ]);

        CampaignPerformanceStat::create([
            'user_id' => $user->id,
            'platform' => 'meta',
            'external_campaign_id' => '1201',
            'local_campaign_id' => $campaign->id,
            'stat_date' => '2026-09-10',
            'spend' => 20.00,
            'impressions' => 2000,
            'clicks' => 10,
            'platform_status' => 'ACTIVE',
            'fetched_at' => now(),
        ]);
        CampaignPerformanceStat::create([
            'user_id' => $user->id,
            'platform' => 'meta',
            'external_campaign_id' => '1201',
            'local_campaign_id' => $campaign->id,
            'stat_date' => '2026-09-20',
            'spend' => 20.00,
            'impressions' => 2000,
            'clicks' => 20,
            'platform_status' => 'ACTIVE',
            'fetched_at' => now(),
        ]);

        Http::fake();

        $this->artisan('campaigns:sync-performance', ['--map' => true])->assertSuccessful();

        $row = CampaignPerformanceSuggestion::query()->first();
        $this->assertNotNull($row);
        $this->assertSame('improving', $row->snapshot['trend']);
        $this->assertSame(40.0, (float) $row->snapshot['lifetime']['spend']);
        $this->assertSame('continue', $row->status);
    }

    public function test_hourly_sync_maps_a_suggestion_including_recent_hours(): void
    {
        $this->travelTo('2026-09-22 12:00:00');
        config([
            'campaign-performance.platforms' => ['meta'],
            'campaign-performance.llm_enabled' => false,
            'platforms.meta.token' => 'test-token',
            'platforms.meta.version' => 'v23.0',
            'platforms.guardrails.retry_backoff_ms' => 0,
            'platforms.guardrails.allowed_ad_accounts' => ['act_111'],
        ]);

        $user = User::factory()->create();
        $campaign = Campaign::create([
            'user_id' => $user->id,
            'name' => 'Italy packages',
            'platform' => 'meta',
            'status' => 'published',
            'budget' => 20,
            'ad_account_id' => 'act_111',
            'external_campaign_id' => '1201',
        ]);

        $this->seedDailyStats($user, $campaign, 10.0, 2, 7);

        Http::fake([
            '*/1201/insights*' => Http::response(['data' => [
                [
                    'date_start' => '2026-09-22',
                    'date_stop' => '2026-09-22',
                    'hourly_stats_aggregated_by_advertiser_time_zone' => '08:00:00 - 08:59:59',
                    'spend' => '1.00',
                    'impressions' => '10',
                    'clicks' => '1',
                ],
                [
                    'date_start' => '2026-09-22',
                    'date_stop' => '2026-09-22',
                    'hourly_stats_aggregated_by_advertiser_time_zone' => '09:00:00 - 09:59:59',
                    'spend' => '2.00',
                    'impressions' => '20',
                    'clicks' => '2',
                ],
                [
                    'date_start' => '2026-09-22',
                    'date_stop' => '2026-09-22',
                    'hourly_stats_aggregated_by_advertiser_time_zone' => '10:00:00 - 10:59:59',
                    'spend' => '3.00',
                    'impressions' => '30',
                    'clicks' => '3',
                ],
                [
                    'date_start' => '2026-09-22',
                    'date_stop' => '2026-09-22',
                    'hourly_stats_aggregated_by_advertiser_time_zone' => '11:00:00 - 11:59:59',
                    'spend' => '4.00',
                    'impressions' => '40',
                    'clicks' => '4',
                ],
                [
                    'date_start' => '2026-09-22',
                    'date_stop' => '2026-09-22',
                    'hourly_stats_aggregated_by_advertiser_time_zone' => '12:00:00 - 12:59:59',
                    'spend' => '5.00',
                    'impressions' => '50',
                    'clicks' => '5',
                ],
            ]]),
            '*/1201*' => Http::response([
                'id' => '1201',
                'name' => 'Italy packages',
                'status' => 'ACTIVE',
                'effective_status' => 'ACTIVE',
            ]),
        ]);

        $this->artisan('campaigns:sync-performance', ['--hourly' => true])->assertSuccessful();

        $row = CampaignPerformanceSuggestion::query()->first();
        $this->assertNotNull($row);
        $this->assertSame('continue', $row->status);
        $this->assertSame('pending', $row->action_state);
        $this->assertSame(15.0, (float) $row->snapshot['last_7_hours']['spend']);
        $this->assertGreaterThanOrEqual(5, (int) $row->snapshot['last_7_hours']['hours']);
        $this->assertSame(15, (int) $row->snapshot['last_7_hours']['clicks']);
        $this->assertSame(70.0, (float) $row->snapshot['last_7_days']['spend']);
        $this->assertSame('hourly', $row->snapshot['verdicts']['run_type'] ?? null);
    }

    private function seedDailyStats(User $user, Campaign $campaign, float $spend, int $clicks, int $days): void
    {
        foreach (range(0, $days - 1) as $offset) {
            CampaignPerformanceStat::create([
                'user_id' => $user->id,
                'platform' => 'meta',
                'external_campaign_id' => '1201',
                'local_campaign_id' => $campaign->id,
                'stat_date' => now()->subDays($days - 1 - $offset)->toDateString(),
                'spend' => $spend,
                'impressions' => 800,
                'clicks' => $clicks,
                'platform_status' => 'ACTIVE',
                'fetched_at' => now(),
            ]);
        }
    }
}
