<?php

namespace Tests\Unit\Services;

use App\Exceptions\ProviderNotConfiguredException;
use App\Models\Avatar;
use App\Models\Voice;
use App\Services\AI\GeminiVeoVideoAvatarProvider;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Storage;
use RuntimeException;
use Tests\TestCase;

class GeminiVeoVideoAvatarProviderTest extends TestCase
{
    private function script(): array
    {
        return [
            'hook' => 'Tired of slow browsing?',
            'problem' => 'Ads slow you down.',
            'product' => 'Chromium Browser',
            'benefits' => 'Faster pages, no clutter.',
            'cta' => 'Download free today.',
        ];
    }

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

        $this->expectException(ProviderNotConfiguredException::class);

        (new GeminiVeoVideoAvatarProvider)->render(
            new Avatar(['name' => 'Ava', 'gender' => 'female', 'accent' => 'American']),
            new Voice(['name' => 'Kore', 'tone' => 'warm']),
            $this->script(),
            [['scene' => 'Opening shot']],
            duration: 15,
            ratio: '9:16',
        );
    }

    public function test_it_submits_polls_and_downloads_the_generated_video(): 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),
        ]);

        $result = (new GeminiVeoVideoAvatarProvider)->render(
            new Avatar(['name' => 'Ava', 'gender' => 'female', 'accent' => 'American']),
            new Voice(['name' => 'Kore', 'tone' => 'warm']),
            $this->script(),
            [['scene' => 'Opening shot']],
            duration: 15,
            ratio: '9:16',
        );

        $this->assertSame('gemini-veo', $result->meta['provider']);
        $this->assertSame(8, $result->meta['duration']);
        Storage::disk('public')->assertExists($result->assetPath);
        $this->assertSame('FAKEVIDEOBYTES', Storage::disk('public')->get($result->assetPath));
        Http::assertSent(fn ($request) => str_contains($request->url(), 'predictLongRunning')
            && $request['parameters']['durationSeconds'] === 8
            && $request['parameters']['aspectRatio'] === '9:16');
    }

    public function test_it_throws_when_polling_times_out(): void
    {
        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' => 2,
        ]);

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

        $this->expectException(RuntimeException::class);
        $this->expectExceptionMessage('Veo video generation timed out');

        (new GeminiVeoVideoAvatarProvider)->render(
            new Avatar(['name' => 'Ava']),
            new Voice(['name' => 'Kore']),
            $this->script(),
            [['scene' => 'Opening shot']],
            duration: 8,
            ratio: '16:9',
        );
    }
}
