<?php

namespace Tests\Feature;

use App\Campaigns\CampaignPerformanceAdopsMonitor;
use App\Library\CampaignDecision\CampaignDecisionEngine;
use App\Library\CampaignDecision\CampaignDecisionVerdict;
use App\Library\CampaignDecision\CampaignPerformanceDataAssembler;
use App\Models\CampaignDecision;
use App\Models\CampaignPerformanceSuggestion;
use App\Models\User;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Schema;
use Tests\Concerns\CreatesAdopsWhaleTables;
use Tests\TestCase;

class CampaignDecisionEngineTest extends TestCase
{
    use CreatesAdopsWhaleTables;
    use RefreshDatabase;

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

        Config::set([
            'campaign-decisions.engine_enabled' => true,
            'campaign-performance.llm_enabled' => false,
            'campaign-performance.whale_enabled' => true,
            'campaign-performance.adops_enabled' => true,
            'campaign-decisions.defaults.learning_period_days' => 0,
            'campaign-decisions.defaults.max_test_spend' => 0,
        ]);
    }

    public function test_hour_spend_without_clicks_yields_pause(): void
    {
        $this->travelTo('2026-09-22 14:00:00');
        $this->createAdopsWhaleTables();
        $this->seedAdopsCampaignMeta('1201', 'Italy packages');
        $this->seedAdopsHourly('1201', now()->copy()->startOfHour(), 12.0, 0);

        $decision = $this->evaluateCampaign('1201');

        $this->assertSame(CampaignDecisionVerdict::Pause->value, $decision['verdict']);
        $this->assertSame('PAUSE', $decision['recommended_action']);
    }

    public function test_sync_failure_without_metrics_yields_data_issue(): void
    {
        $this->travelTo('2026-09-22 14:00:00');
        $this->createAdopsWhaleTables();
        $this->seedAdopsCampaignMeta('1201', 'Italy packages');

        $user = User::factory()->create();
        $group = [
            'platform' => 'meta',
            'external_campaign_id' => '1201',
            'user_id' => $user->id,
            'local_campaign_id' => null,
            'local_google_ads_campaign_id' => null,
            'name' => 'Italy packages',
            'account_id' => 'act_111',
            'platform_status' => 'ACTIVE',
            'delivery_status' => null,
            'daily_budget' => 20,
            'started_at' => now()->subDays(10)->toDateString(),
            'sync_failed' => true,
            'sync_error' => 'rate limited',
            'days' => collect(),
            'hours' => collect(),
        ];

        $context = app(CampaignPerformanceDataAssembler::class)->assemble($group, 'scheduled_hourly');
        $decision = app(CampaignDecisionEngine::class)->evaluate($context);

        $this->assertSame(CampaignDecisionVerdict::DataIssue->value, $decision['verdict']);
    }

    public function test_lagged_affiliate_roas_can_recommend_scale_up(): void
    {
        $this->travelTo('2026-09-22 14:00:00');
        $this->createAdopsWhaleTables();
        $this->seedAffiliatePerformanceTable();
        $this->seedAdopsCampaignMeta('1201', 'Italy packages');

        for ($offset = 2; $offset < 9; $offset++) {
            $this->seedAdopsDaily(
                '1201',
                now()->subDays($offset)->toDateString(),
                50.0,
                40,
            );
        }

        $lagDays = (int) config('campaign-decisions.monitor.internal_reporting_lag_days', 2);
        $end = now()->copy()->startOfDay()->subDays($lagDays);

        for ($i = 0; $i < 7; $i++) {
            $date = $end->copy()->subDays(6 - $i)->toDateString();
            Schema::connection('whale')->getConnection()->table('arb_adops_campaign_performance')->insert([
                'date' => $date,
                'campaign_id' => '1201',
                'clicks' => 10,
                'sum_cpc' => 0.5,
                'orders' => 2,
                'net_revenue' => 200,
            ]);
        }

        $decision = $this->evaluateCampaign('1201');

        $this->assertSame(CampaignDecisionVerdict::ScaleUp->value, $decision['verdict']);
        $this->assertGreaterThan(0, $decision['recommended_budget_change_percent']);
    }

    public function test_monitor_persists_decision_and_suggestion_when_v2_enabled(): void
    {
        $this->travelTo('2026-09-22 14:00:00');
        $this->createAdopsWhaleTables();
        User::factory()->create();
        $this->seedAdopsCampaignMeta('1201', 'Italy packages');
        $this->seedAdopsHourly('1201', now()->copy()->startOfHour(), 12.0, 0);

        $this->artisan('campaigns:monitor-adops', ['--hourly' => true, '--campaign' => '1201'])
            ->assertSuccessful();

        $this->assertSame(1, CampaignDecision::query()->count());
        $suggestion = CampaignPerformanceSuggestion::query()->first();
        $this->assertNotNull($suggestion);
        $this->assertSame(CampaignDecisionVerdict::Pause->value, $suggestion->status);
        $this->assertSame('v2', $suggestion->snapshot['decision_engine'] ?? null);
    }

    /**
     * @return array<string, mixed>
     */
    private function evaluateCampaign(string $id): array
    {
        User::factory()->create();
        $group = app(CampaignPerformanceAdopsMonitor::class)->group(
            [
                'platform' => 'meta',
                'campaign_id' => $id,
                'name' => 'Italy packages',
                'account_id' => 'act_111',
                'status' => 'ACTIVE',
                'effective_status' => 'ACTIVE',
                'daily_budget' => 20,
                'learning_status' => null,
                'started_at' => now()->subDays(10)->toDateString(),
            ],
            'hourly',
        );

        $context = app(CampaignPerformanceDataAssembler::class)->assemble($group, 'scheduled_hourly');

        return app(CampaignDecisionEngine::class)->evaluate($context);
    }

    private function seedAffiliatePerformanceTable(): void
    {
        $schema = Schema::connection('whale');

        if (! $schema->hasTable('arb_adops_campaign_performance')) {
            $schema->create('arb_adops_campaign_performance', function (Blueprint $table): void {
                $table->date('date');
                $table->string('campaign_id');
                $table->unsignedInteger('clicks')->default(0);
                $table->decimal('sum_cpc', 12, 4)->default(0);
                $table->decimal('orders', 12, 4)->default(0);
                $table->decimal('net_revenue', 12, 4)->default(0);
            });
        }
    }
}
