<?php

namespace Tests\Feature;

use App\Models\Avatar;
use Database\Seeders\AvatarSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\File;
use Laravel\Ai\Image;
use Tests\TestCase;

class GenerateAvatarPhotosTest extends TestCase
{
    use RefreshDatabase;

    public function test_it_uses_gemini_for_presenter_portraits_even_when_openai_is_the_default(): void
    {
        config([
            'ai.default_for_images' => 'openai',
            'ai.providers.gemini.models.image.default' => 'gemini-3.1-flash-image',
        ]);
        $avatar = Avatar::create([
            'name' => 'Test Presenter',
            'gender' => 'female',
            'accent' => 'American',
            'type' => 'stock',
        ]);
        $source = imagecreatetruecolor(2, 2);
        ob_start();
        imagepng($source);
        $png = ob_get_clean();
        Image::fake([base64_encode($png)]);
        File::shouldReceive('ensureDirectoryExists')->once();
        File::shouldReceive('put')->once()->andReturn(18);

        $this->artisan('avatars:generate-photos')->assertSuccessful();

        Image::assertGenerated(fn ($prompt): bool => $prompt->provider->name() === 'gemini'
            && $prompt->model === 'gemini-3.1-flash-image'
            && $prompt->isSquare());
        $this->assertStringStartsWith('assets/avatars/', $avatar->fresh()->source_path);
        $this->assertStringEndsWith('.jpg', $avatar->fresh()->source_path);
    }

    public function test_it_reports_failure_and_preserves_the_previous_avatar_when_gemini_returns_invalid_image_data(): void
    {
        $avatar = Avatar::create([
            'name' => 'Test Presenter',
            'gender' => 'female',
            'accent' => 'American',
            'type' => 'stock',
            'source_path' => 'assets/avatars/existing.png',
        ]);
        Image::fake([base64_encode('not an image')]);

        $this->artisan('avatars:generate-photos', ['--force' => true])->assertFailed();

        $this->assertSame('assets/avatars/existing.png', $avatar->fresh()->source_path);
    }

    public function test_it_does_not_update_the_avatar_when_the_portrait_file_cannot_be_saved(): void
    {
        $avatar = Avatar::create([
            'name' => 'Test Presenter',
            'gender' => 'female',
            'accent' => 'American',
            'type' => 'stock',
        ]);
        $source = imagecreatetruecolor(2, 2);
        ob_start();
        imagepng($source);
        $png = ob_get_clean();
        Image::fake([base64_encode($png)]);
        File::shouldReceive('ensureDirectoryExists')->once();
        File::shouldReceive('put')->once()->andReturn(false);

        $this->artisan('avatars:generate-photos')->assertFailed();

        $this->assertNull($avatar->fresh()->source_path);
    }

    public function test_reseeding_replaces_an_old_stock_portrait_with_the_gemini_asset(): void
    {
        $avatar = Avatar::create([
            'name' => 'Ava',
            'gender' => 'female',
            'accent' => 'American',
            'type' => 'stock',
            'source_path' => 'assets/avatars/old-openai.png',
        ]);

        $this->seed(AvatarSeeder::class);

        $this->assertStringEndsWith('.jpg', $avatar->fresh()->source_path);
        $this->assertFileExists(public_path($avatar->fresh()->source_path));
    }

    public function test_seeded_gemini_presenter_portraits_are_shipped_as_valid_jpegs(): void
    {
        $this->seed(AvatarSeeder::class);

        $this->assertSame(12, Avatar::count());
        foreach (Avatar::all() as $avatar) {
            $path = public_path($avatar->source_path);
            $this->assertFileExists($path);
            $this->assertSame('image/jpeg', mime_content_type($path));
            $this->assertSame([1024, 1024], array_slice(getimagesize($path), 0, 2));
        }
    }
}
