<?php

namespace Tests\Feature;

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

class CampaignPerformancePageTest extends TestCase
{
    use RefreshDatabase;

    public function test_the_owner_sees_name_spend_and_reason(): void
    {
        $this->travelTo('2026-09-22 12:00:00');

        $user = User::factory()->create();
        $this->seedBoard($user, 'Italy packages', '1201', 12.10, 'Pause this campaign.', [
            'trend' => 'improving',
            'trend_summary' => 'CPC improved 20% vs prior 7 days.',
        ]);

        $this->actingAs($user)
            ->get(route('campaigns.performance'))
            ->assertOk()
            ->assertSee('Campaign performance', false)
            ->assertSee('title="Campaign performance"', false)
            ->assertSee('bi-graph-up-arrow', false)
            ->assertSee('Italy packages', false)
            ->assertSee('$12.10', false)
            ->assertSee('Pause', false)
            ->assertSee('7-day spend', false)
            ->assertSee('View details', false)
            ->assertSee('Improving', false)
            ->assertSee('What to do', false)
            ->assertSee('AI suggestion', false)
            ->assertSee('Pause this campaign on the ad platform when you are ready.', false)
            ->assertSee('Pause this campaign.', false);
    }

    public function test_guests_are_redirected_to_login(): void
    {
        $this->get(route('campaigns.performance'))
            ->assertRedirect(route('login'));
    }

    public function test_the_page_lives_at_campaign_performance(): void
    {
        $user = User::factory()->create();

        $this->actingAs($user)
            ->get('/campaign-performance')
            ->assertOk();

        $this->actingAs($user)
            ->get('/campaigns')
            ->assertRedirect('/campaign-performance');
    }

    public function test_another_users_campaign_is_not_listed(): void
    {
        $this->travelTo('2026-09-22 12:00:00');

        $owner = User::factory()->create();
        $stranger = User::factory()->create();
        $this->seedBoard($stranger, 'Secret campaign', '9999', 40.00, 'Keep this secret.');

        $this->actingAs($owner)
            ->get(route('campaigns.performance'))
            ->assertOk()
            ->assertDontSee('Secret campaign', false);

        $this->actingAs($owner)
            ->get(route('campaigns.performance.show', ['platform' => 'meta', 'campaign' => '9999']))
            ->assertNotFound();
    }

    public function test_the_page_does_not_call_ad_platforms(): void
    {
        $this->travelTo('2026-09-22 12:00:00');

        $user = User::factory()->create();
        $this->seedBoard($user, 'Italy packages', '1201', 12.10, 'Pause this campaign.');

        Http::fake();

        $this->actingAs($user)
            ->get(route('campaigns.performance'))
            ->assertOk();

        $this->actingAs($user)
            ->get(route('campaigns.performance.show', ['platform' => 'meta', 'campaign' => '1201']))
            ->assertOk();

        Http::assertNothingSent();
    }

    public function test_status_chips_filter_the_listing(): void
    {
        $this->travelTo('2026-09-22 12:00:00');

        $user = User::factory()->create();
        $this->seedBoard($user, 'Italy packages', '1201', 12.10, 'Pause this campaign.');

        $this->actingAs($user)
            ->get(route('campaigns.performance', ['status' => 'pause']))
            ->assertOk()
            ->assertSee('Italy packages', false);

        $this->actingAs($user)
            ->get(route('campaigns.performance', ['status' => 'continue']))
            ->assertOk()
            ->assertDontSee('Italy packages', false)
            ->assertSee('No live campaigns yet', false);
    }

    public function test_a_campaign_past_the_learning_window_does_not_say_day_n_of_m(): void
    {
        $this->travelTo('2026-09-22 12:00:00');

        $user = User::factory()->create();
        $this->seedBoard($user, 'Italy packages', '1201', 52.65, 'Keep running.', [
            'days_live' => 7,
            'learning_window_days' => 3,
            'max_test_spend' => 40,
        ]);

        $this->actingAs($user)
            ->get(route('campaigns.performance.show', ['platform' => 'meta', 'campaign' => '1201']))
            ->assertOk()
            ->assertSee('7 days live', false)
            ->assertSee('$52.65 spend vs $40.00 test cap', false)
            ->assertDontSee('Day 7 of 3', false);
    }

    public function test_the_detail_page_lists_historic_daily_stats(): void
    {
        $this->travelTo('2026-09-22 12:00:00');

        $user = User::factory()->create();
        $this->seedBoard($user, 'Italy packages', '1201', 12.10, 'Pause this campaign.', [
            'trend' => 'improving',
            'trend_summary' => 'CPC improved 20% vs prior 7 days.',
            'verdicts' => [
                'run_type' => 'daily',
                'windows' => [
                    '3h' => [
                        'window' => '3h',
                        'from' => '2026-09-22 09:00:00',
                        'to' => '2026-09-22 11:00:00',
                        'spend' => 0,
                        'clicks' => 0,
                        'cpc' => null,
                        'verdict' => 'pause',
                        'reason' => '3H: $0.00 spend, 0 clicks. Suggestion: pause this campaign.',
                    ],
                    '7d' => [
                        'window' => '7d',
                        'from' => '2026-09-16 00:00:00',
                        'to' => '2026-09-22 00:00:00',
                        'spend' => 12.10,
                        'clicks' => 0,
                        'cpc' => null,
                        'verdict' => 'pause',
                        'reason' => '7D: $12.10 spend, 0 clicks. Suggestion: pause this campaign.',
                    ],
                ],
            ],
        ]);

        CampaignPerformanceStat::create([
            'user_id' => $user->id,
            'platform' => 'meta',
            'external_campaign_id' => '1201',
            'stat_date' => '2026-09-21',
            'spend' => 8.50,
            'impressions' => 400,
            'clicks' => 2,
            'ctr' => 0.005,
            'cpc' => 4.25,
            'platform_status' => 'ACTIVE',
            'fetched_at' => now(),
        ]);

        CampaignPerformanceHourStat::create([
            'user_id' => $user->id,
            'platform' => 'meta',
            'external_campaign_id' => '1201',
            'stat_hour' => '2026-09-21 10:00:00',
            'spend' => 3.00,
            'impressions' => 150,
            'clicks' => 1,
            'ctr' => 0.0067,
            'cpc' => 3.00,
            'platform_status' => 'ACTIVE',
            'fetched_at' => now(),
        ]);

        CampaignPerformanceHourStat::create([
            'user_id' => $user->id,
            'platform' => 'meta',
            'external_campaign_id' => '1201',
            'stat_hour' => '2026-09-21 14:00:00',
            'spend' => 5.50,
            'impressions' => 250,
            'clicks' => 1,
            'ctr' => 0.004,
            'cpc' => 5.50,
            'platform_status' => 'ACTIVE',
            'fetched_at' => now(),
        ]);

        $this->actingAs($user)
            ->get(route('campaigns.performance.show', ['platform' => 'meta', 'campaign' => '1201']))
            ->assertOk()
            ->assertSee('Italy packages', false)
            ->assertSee('Pause this campaign.', false)
            ->assertSee('Daily history', false)
            ->assertSee('mb-perf-day-entry', false)
            ->assertSee('Hourly breakdown', false)
            ->assertSee('10:00 AM', false)
            ->assertSee('2:00 PM', false)
            ->assertSee('2026-09-21', false)
            ->assertSee('2026-09-22', false)
            ->assertSee('$8.50', false)
            ->assertSee('Lifetime spend', false)
            ->assertSee('CPC improved 20% vs prior 7 days.', false)
            ->assertSee('Daily performance', false)
            ->assertSee('Suggestion & window verdicts', false)
            ->assertSee('3H:', false)
            ->assertSee('7D:', false)
            ->assertSee('mb-perf-chart', false)
            ->assertSee('mb-perf-line', false);
    }

    public function test_the_detail_history_table_is_paginated(): void
    {
        $this->travelTo('2026-09-22 12:00:00');

        $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',
        ]);

        foreach (range(0, 11) as $offset) {
            CampaignPerformanceStat::create([
                'user_id' => $user->id,
                'platform' => 'meta',
                'external_campaign_id' => '1201',
                'local_campaign_id' => $campaign->id,
                'stat_date' => now()->subDays(11 - $offset)->toDateString(),
                'spend' => $offset === 0 ? 1.11 : ($offset === 11 ? 9.99 : 2.00),
                'impressions' => 100,
                'clicks' => 1,
                'platform_status' => 'ACTIVE',
                'fetched_at' => now(),
            ]);
        }

        $this->actingAs($user)
            ->get(route('campaigns.performance.show', ['platform' => 'meta', 'campaign' => '1201']))
            ->assertOk()
            ->assertSee('Daily performance', false)
            ->assertSee('All 12 dumped days. Not paginated.', false)
            ->assertSee('$9.99', false)
            ->assertDontSee('$1.11', false)
            ->assertSee('Showing', false)
            ->assertSee('of', false);

        $this->actingAs($user)
            ->get(route('campaigns.performance.show', ['platform' => 'meta', 'campaign' => '1201', 'page' => 2]))
            ->assertOk()
            ->assertSee('$1.11', false)
            ->assertDontSee('$9.99', false)
            ->assertSee('All 12 dumped days. Not paginated.', false);
    }

    public function test_a_dumped_campaign_without_a_local_row_still_opens(): void
    {
        $this->travelTo('2026-09-22 12:00:00');

        $user = User::factory()->create();

        CampaignPerformanceStat::create([
            'user_id' => $user->id,
            'platform' => 'meta',
            'external_campaign_id' => '120251607606470626',
            'stat_date' => '2026-09-22',
            'spend' => 5.00,
            'impressions' => 100,
            'clicks' => 1,
            'platform_status' => 'ACTIVE',
            'fetched_at' => now(),
        ]);

        $this->actingAs($user)
            ->get(route('campaigns.performance.show', ['platform' => 'meta', 'campaign' => '120251607606470626']))
            ->assertOk()
            ->assertSee('Campaign 120251607606470626', false)
            ->assertSee('Daily history', false);
    }

    public function test_guests_cannot_open_a_campaign_detail(): void
    {
        $this->get(route('campaigns.performance.show', ['platform' => 'meta', 'campaign' => '1201']))
            ->assertRedirect(route('login'));
    }

    public function test_the_detail_page_shows_an_expandable_verdict_log(): void
    {
        $this->travelTo('2026-09-22 12:00:00');

        $user = User::factory()->create();
        $this->seedBoard($user, 'Italy packages', '1201', 12.10, 'Pause this campaign.');

        CampaignPerformanceVerdictLog::create([
            'user_id' => $user->id,
            'platform' => 'meta',
            'external_campaign_id' => '1201',
            'evaluated_at' => now(),
            'run_type' => 'daily',
            'final_verdict' => 'stop',
            'final_reason' => 'Multiple windows agree: pause campaign now.',
            'windows' => [
                '3h' => [
                    'window' => '3h',
                    'verdict' => 'pause',
                    'spend' => 4.2,
                    'clicks' => 0,
                    'cpc' => null,
                    'reason' => '3H: $4.20 spend, 0 clicks. Suggestion: pause this campaign.',
                ],
                '7d' => [
                    'window' => '7d',
                    'verdict' => 'pause',
                    'spend' => 42.0,
                    'clicks' => 0,
                    'cpc' => null,
                    'reason' => '7D: $42.00 spend, 0 clicks. Suggestion: pause this campaign.',
                ],
            ],
            'source' => 'php',
        ]);

        $this->actingAs($user)
            ->get(route('campaigns.performance.show', ['platform' => 'meta', 'campaign' => '1201']))
            ->assertOk()
            ->assertSee('Campaign profile', false)
            ->assertSee('Verdict log', false)
            ->assertSee('mb-perf-log-entry', false)
            ->assertSee('Multiple windows agree: pause campaign now.', false)
            ->assertSee('3H: $4.20 spend, 0 clicks. Suggestion: pause this campaign.', false);
    }

    public function test_verdict_log_filters_by_run_type(): void
    {
        $this->travelTo('2026-09-22 12:00:00');

        $user = User::factory()->create();
        $this->seedBoard($user, 'Italy packages', '1201', 12.10, 'Pause this campaign.');

        CampaignPerformanceVerdictLog::create([
            'user_id' => $user->id,
            'platform' => 'meta',
            'external_campaign_id' => '1201',
            'evaluated_at' => now()->subHour(),
            'run_type' => 'hourly',
            'final_verdict' => 'pause',
            'final_reason' => 'Hourly intraday pause signal.',
            'windows' => [
                '3h' => ['window' => '3h', 'verdict' => 'pause', 'spend' => 4.2, 'clicks' => 0, 'reason' => 'Hourly window bad.'],
            ],
            'hourly_verdict' => ['verdict' => 'pause', 'reason' => 'Hourly check: pause.'],
            'source' => 'php',
        ]);

        CampaignPerformanceVerdictLog::create([
            'user_id' => $user->id,
            'platform' => 'meta',
            'external_campaign_id' => '1201',
            'evaluated_at' => now(),
            'run_type' => 'daily',
            'final_verdict' => 'stop',
            'final_reason' => 'Daily stop signal.',
            'windows' => [
                '7d' => ['window' => '7d', 'verdict' => 'pause', 'spend' => 42.0, 'clicks' => 0, 'reason' => 'Daily window bad.'],
            ],
            'source' => 'php',
        ]);

        $this->actingAs($user)
            ->get(route('campaigns.performance.show', [
                'platform' => 'meta',
                'campaign' => '1201',
                'log_run_type' => 'hourly',
            ]))
            ->assertOk()
            ->assertSee('Hourly intraday pause signal.', false)
            ->assertDontSee('Daily window bad.', false);
    }

    public function test_hourly_only_campaigns_still_appear_on_the_listing(): void
    {
        $this->travelTo('2026-09-22 12:00:00');

        $user = User::factory()->create();

        CampaignPerformanceHourStat::create([
            'user_id' => $user->id,
            'platform' => 'meta',
            'external_campaign_id' => '120252303208750683',
            'stat_hour' => '2026-09-22 10:00:00',
            'spend' => 4.20,
            'impressions' => 100,
            'clicks' => 2,
            'platform_status' => 'ACTIVE',
            'fetched_at' => now(),
        ]);

        CampaignPerformanceProfile::create([
            'user_id' => $user->id,
            'platform' => 'meta',
            'external_campaign_id' => '120252303208750683',
            'name' => 'WirelessHeadphones_OfficeDepot_20260717',
            'fetched_at' => now(),
        ]);

        CampaignPerformanceSuggestion::create([
            'user_id' => $user->id,
            'platform' => 'meta',
            'external_campaign_id' => '120252303208750683',
            'status' => 'no_action',
            'source' => 'php',
            'reason' => 'Keep monitoring.',
            'action_state' => 'pending',
            'snapshot' => [],
            'suggested_at' => now(),
        ]);

        $this->actingAs($user)
            ->get(route('campaigns.performance'))
            ->assertOk()
            ->assertSee('WirelessHeadphones_OfficeDepot_20260717', false)
            ->assertSee('120252303208750683', false);
    }

    public function test_suggestion_section_shows_affiliate_conversion_and_cpc(): void
    {
        $this->travelTo('2026-09-22 12:00:00');

        $user = User::factory()->create();
        $this->seedBoard($user, 'Italy packages', '1201', 12.10, 'Continue monitoring.', [
            'affiliate' => [
                'matched' => true,
                'campaign_id' => '1201',
                '3d' => [
                    'clicks' => 10,
                    'sum_cpc' => 1.50,
                    'orders' => 1,
                    'net_revenue' => 25.00,
                ],
                '7d' => [
                    'clicks' => 42,
                    'sum_cpc' => 5.25,
                    'orders' => 3,
                    'net_revenue' => 89.44,
                ],
            ],
            'verdicts' => [
                'run_type' => 'daily',
                'windows' => [
                    '3d' => [
                        'window' => '3d',
                        'from' => '2026-09-20 00:00:00',
                        'to' => '2026-09-22 00:00:00',
                        'spend' => 8.00,
                        'clicks' => 2,
                        'cpc' => 4.00,
                        'verdict' => 'no_action',
                        'reason' => '3D: within test budget.',
                    ],
                    '7d' => [
                        'window' => '7d',
                        'from' => '2026-09-16 00:00:00',
                        'to' => '2026-09-22 00:00:00',
                        'spend' => 12.10,
                        'clicks' => 0,
                        'cpc' => null,
                        'verdict' => 'no_action',
                        'reason' => '7D: affiliate revenue supports continue.',
                    ],
                ],
            ],
        ]);

        $this->actingAs($user)
            ->get(route('campaigns.performance.show', ['platform' => 'meta', 'campaign' => '1201']))
            ->assertOk()
            ->assertSee('Suggestion & window verdicts', false)
            ->assertSee('Meta conversion', false)
            ->assertSee('Whale DB — actual conversion (7 days)', false)
            ->assertSee('Sum CPC', false)
            ->assertSee('$89.44', false)
            ->assertSee('$1.50', false)
            ->assertSee('7D: affiliate revenue supports continue.', false);
    }

    public function test_the_list_uses_meta_profile_name_over_placeholder_local_name(): void
    {
        $this->travelTo('2026-09-22 12:00:00');

        $user = User::factory()->create();
        $campaign = Campaign::create([
            'user_id' => $user->id,
            'name' => 'Campaign 1201',
            '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-22',
            'spend' => 12.10,
            'impressions' => 800,
            'clicks' => 0,
            'platform_status' => 'ACTIVE',
            'fetched_at' => now(),
        ]);

        CampaignPerformanceProfile::create([
            'user_id' => $user->id,
            'platform' => 'meta',
            'external_campaign_id' => '1201',
            'local_campaign_id' => $campaign->id,
            'name' => 'Italy packages live',
            'fetched_at' => now(),
        ]);

        CampaignPerformanceSuggestion::create([
            'user_id' => $user->id,
            'platform' => 'meta',
            'external_campaign_id' => '1201',
            'local_campaign_id' => $campaign->id,
            'status' => 'pause',
            'source' => 'php',
            'reason' => 'Pause this campaign.',
            'action_state' => 'pending',
            'snapshot' => [],
            'suggested_at' => now(),
        ]);

        $this->actingAs($user)
            ->get(route('campaigns.performance'))
            ->assertOk()
            ->assertSee('Italy packages live', false)
            ->assertDontSee('Campaign 1201', false);
    }

    /**
     * @param  array<string, mixed>  $snapshot
     */
    private function seedBoard(User $user, string $name, string $externalId, float $spend, string $reason, array $snapshot = []): void
    {
        $campaign = Campaign::create([
            'user_id' => $user->id,
            'name' => $name,
            'platform' => 'meta',
            'status' => 'published',
            'budget' => 20,
            'ad_account_id' => 'act_111',
            'external_campaign_id' => $externalId,
        ]);

        CampaignPerformanceStat::create([
            'user_id' => $user->id,
            'platform' => 'meta',
            'external_campaign_id' => $externalId,
            'local_campaign_id' => $campaign->id,
            'stat_date' => '2026-09-22',
            'spend' => $spend,
            'impressions' => 800,
            'clicks' => 0,
            'platform_status' => 'ACTIVE',
            'fetched_at' => now(),
        ]);

        CampaignPerformanceSuggestion::create([
            'user_id' => $user->id,
            'platform' => 'meta',
            'external_campaign_id' => $externalId,
            'local_campaign_id' => $campaign->id,
            'status' => 'pause',
            'source' => 'php',
            'reason' => $reason,
            'action_state' => 'pending',
            'snapshot' => $snapshot,
            'suggested_at' => now(),
        ]);
    }
}
