<?php

namespace Tests\Feature;

use App\Jobs\RenderVideoCreativeJob;
use App\Models\Avatar;
use App\Models\Creative;
use App\Models\User;
use App\Models\Voice;
use App\Services\AI\VideoAvatarProviderFactory;
use Database\Seeders\AvatarSeeder;
use Database\Seeders\VoiceSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Storage;
use Tests\TestCase;

class RenderVideoCreativeJobTest extends TestCase
{
    use RefreshDatabase;

    private function makeCreative(int $duration = 8, string $ratio = '9:16'): Creative
    {
        $this->seed(AvatarSeeder::class);
        $this->seed(VoiceSeeder::class);

        return Creative::create([
            'user_id' => User::factory()->create()->id,
            'type' => 'video',
            'status' => 'generating',
            'source' => 'prompt',
            'prompt' => 'A video ad for our browser.',
            'ratio' => $ratio,
            'duration' => $duration,
            'avatar_id' => Avatar::first()->id,
            'voice_id' => Voice::first()->id,
            'script' => ['hook' => 'H', 'problem' => 'P', 'product' => 'Pr', 'benefits' => 'B', 'cta' => 'C'],
            'storyboard' => [['scene' => 'H'], ['scene' => 'P'], ['scene' => 'Pr'], ['scene' => 'B'], ['scene' => 'C']],
        ]);
    }

    public function test_it_renders_a_short_video_via_veo_and_marks_the_creative_completed(): void
    {
        Storage::fake('public');

        config([
            'ai.providers.gemini.key' => 'test-key',
            'ai.providers.gemini.url' => 'https://generativelanguage.googleapis.com/v1beta/',
            'creative.gemini_veo.poll_interval_seconds' => 0,
            'creative.gemini_veo.max_poll_attempts' => 3,
        ]);

        Http::fake([
            'generativelanguage.googleapis.com/v1beta/models/*:predictLongRunning' => Http::response([
                'name' => 'models/veo-3.0-generate-001/operations/abc123',
            ]),
            'generativelanguage.googleapis.com/v1beta/models/veo-3.0-generate-001/operations/abc123' => Http::response([
                'done' => true,
                'response' => [
                    'generateVideoResponse' => [
                        'generatedSamples' => [
                            ['video' => ['uri' => 'https://generativelanguage.googleapis.com/v1beta/files/abc123:download']],
                        ],
                    ],
                ],
            ]),
            'generativelanguage.googleapis.com/v1beta/files/abc123:download' => Http::response('FAKEVIDEOBYTES', 200),
        ]);

        $creative = $this->makeCreative(duration: 8);

        (new RenderVideoCreativeJob(
            $creative->id,
            $creative->avatar_id,
            $creative->voice_id,
            $creative->script,
            $creative->storyboard,
            $creative->duration,
            $creative->ratio,
        ))->handle(app(VideoAvatarProviderFactory::class));

        $creative->refresh();

        $this->assertSame('completed', $creative->status);
        $this->assertNotNull($creative->asset_path);
        $this->assertNull($creative->failure_reason);
        Storage::disk('public')->assertExists($creative->asset_path);
    }

    public function test_it_marks_the_creative_failed_when_the_provider_throws(): void
    {
        config(['ai.providers.gemini.key' => null]);

        $creative = $this->makeCreative(duration: 8);

        try {
            (new RenderVideoCreativeJob(
                $creative->id,
                $creative->avatar_id,
                $creative->voice_id,
                $creative->script,
                $creative->storyboard,
                $creative->duration,
                $creative->ratio,
            ))->handle(app(VideoAvatarProviderFactory::class));
            $this->fail('Expected exception was not thrown.');
        } catch (\Throwable $e) {
            // provider throws ProviderNotConfiguredException when the key is missing
        }

        $creative->refresh();

        $this->assertSame('failed', $creative->status);
        $this->assertNotNull($creative->failure_reason);
    }

    public function test_it_is_a_no_op_when_the_creative_is_already_completed(): void
    {
        $creative = $this->makeCreative(duration: 8);
        $creative->update(['status' => 'completed', 'asset_path' => 'creatives/videos/already-done.mp4']);

        (new RenderVideoCreativeJob(
            $creative->id,
            $creative->avatar_id,
            $creative->voice_id,
            $creative->script,
            $creative->storyboard,
            $creative->duration,
            $creative->ratio,
        ))->handle(app(VideoAvatarProviderFactory::class));

        $creative->refresh();

        $this->assertSame('completed', $creative->status);
        $this->assertSame('creatives/videos/already-done.mp4', $creative->asset_path);
    }
}
