<?php

namespace Tests\Feature;

use App\Jobs\GenerateImageCreativeJob;
use App\Models\Creative;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Queue;
use Illuminate\Support\Facades\Storage;
use Tests\TestCase;

class ManualCreativeUploadTest extends TestCase
{
    use RefreshDatabase;

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

        Storage::fake('public');
    }

    public function test_an_image_upload_is_stored_as_a_completed_creative(): void
    {
        $user = User::factory()->create();
        $file = $this->pngUpload('bottle.png');

        $response = $this->actingAs($user)->post(route('creatives.manual-upload'), [
            'title' => 'Bottle ad',
            'project_name' => 'ARB',
            'type' => 'image',
            'file' => $file,
        ]);

        $creative = Creative::sole();

        $response->assertRedirect(route('creatives.show', $creative));
        $this->assertSame('manual_upload', $creative->source);
        $this->assertSame('image', $creative->type);
        $this->assertSame('completed', $creative->status);
        $this->assertSame('Bottle ad', $creative->title);
        $this->assertSame('ARB', $creative->project_name);
        $this->assertSame('1:1', $creative->ratio);
        $this->assertNotNull($creative->asset_path);
        Storage::disk('public')->assertExists($creative->asset_path);
        $this->assertNotNull($creative->fresh()->asset_id);
    }

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

        $this->actingAs($user)->post(route('creatives.manual-upload'), [
            'title' => 'No project',
            'type' => 'image',
            'file' => $this->pngUpload('ad.png'),
        ])->assertRedirect();

        $this->assertNull(Creative::sole()->project_name);
    }

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

        $this->actingAs($user)->post(route('creatives.manual-upload'), [
            'title' => 'Wrong file',
            'type' => 'image',
            'file' => UploadedFile::fake()->create('clip.mp4', 100, 'video/mp4'),
        ])->assertSessionHasErrors('file');

        $this->assertSame(0, Creative::count());
    }

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

        $this->actingAs($user)->post(route('creatives.manual-upload'), [
            'title' => 'Wrong file',
            'type' => 'video',
            'file' => $this->pngUpload('ad.png'),
        ])->assertSessionHasErrors('file');

        $this->assertSame(0, Creative::count());
    }

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

        $this->actingAs($user)->post(route('creatives.manual-upload'), [
            'title' => 'Clip',
            'type' => 'video',
            'file' => UploadedFile::fake()->create('clip.mp4', 100, 'video/mp4'),
        ])->assertRedirect();

        $creative = Creative::sole();
        $this->assertSame('video', $creative->type);
        $this->assertSame('manual_upload', $creative->source);
        $this->assertNull($creative->ratio);
        Storage::disk('public')->assertExists($creative->asset_path);
    }

    public function test_regenerate_is_hidden_and_does_not_rerun_generation(): void
    {
        Queue::fake();
        $user = User::factory()->create();
        Storage::disk('public')->put('creatives/images/kept.png', 'bytes');

        $creative = Creative::create([
            'user_id' => $user->id,
            'type' => 'image',
            'status' => 'completed',
            'source' => 'manual_upload',
            'title' => 'Uploaded',
            'asset_path' => 'creatives/images/kept.png',
        ]);

        $this->actingAs($user)
            ->get(route('creatives.show', $creative))
            ->assertOk()
            ->assertDontSee('Regenerate');

        $this->actingAs($user)
            ->post(route('creatives.regenerate', $creative))
            ->assertRedirect(route('creatives.show', $creative));

        $creative->refresh();
        $this->assertSame('completed', $creative->status);
        $this->assertSame('creatives/images/kept.png', $creative->asset_path);
        Queue::assertNotPushed(GenerateImageCreativeJob::class);
    }

    private function pngUpload(string $name): UploadedFile
    {
        $png = base64_decode('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==');

        return UploadedFile::fake()->createWithContent($name, $png);
    }
}
