<?php

use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;

uses(RefreshDatabase::class);

function createUploadForStatusTests(int $userId, array $overrides = []): string
{
    $id = (string) Str::uuid();

    $defaults = [
        'id' => $id,
        'user_id' => $userId,
        'type' => 'image',
        'status' => 'draft',
        'title' => null,
        'slug' => null,
        'category_id' => null,
        'description' => null,
        'tags' => null,
        'license' => null,
        'nsfw' => false,
        'is_scanned' => false,
        'has_tags' => false,
        'preview_path' => null,
        'published_at' => null,
        'final_path' => null,
        'expires_at' => null,
        'created_at' => now(),
        'updated_at' => now(),
    ];

    DB::table('uploads')->insert(array_merge($defaults, $overrides));

    return $id;
}

it('owner sees processing status payload', function () {
    $owner = User::factory()->create();
    $uploadId = createUploadForStatusTests($owner->id, [
        'status' => 'draft',
        'processing_state' => 'analyzing_tags',
        'is_scanned' => true,
        'preview_path' => 'tmp/drafts/preview.webp',
        'has_tags' => false,
    ]);

    $response = $this->actingAs($owner)->getJson("/api/uploads/{$uploadId}/status");

    $response->assertOk()->assertJson([
        'id' => $uploadId,
        'status' => 'draft',
        'is_scanned' => true,
        'preview_ready' => true,
        'has_tags' => false,
        'processing_state' => 'analyzing_tags',
    ]);
});

it('other user is denied', function () {
    $owner = User::factory()->create();
    $other = User::factory()->create();

    $uploadId = createUploadForStatusTests($owner->id);

    $response = $this->actingAs($other)->getJson("/api/uploads/{$uploadId}/status");

    $response->assertStatus(403);
});

it('returns explicit processing states', function (array $input, string $expectedState) {
    $owner = User::factory()->create();

    $uploadId = createUploadForStatusTests($owner->id, $input);

    $response = $this->actingAs($owner)->getJson("/api/uploads/{$uploadId}/status");

    $response->assertOk()->assertJsonPath('processing_state', $expectedState);
})
    ->with([
        'pending scan' => [[
            'status' => 'draft',
            'processing_state' => 'pending_scan',
        ], 'pending_scan'],
        'scanning status' => [[
            'status' => 'scanning',
            'processing_state' => 'scanning',
        ], 'scanning'],
        'generating preview' => [[
            'status' => 'draft',
            'processing_state' => 'generating_preview',
        ], 'generating_preview'],
        'analyzing tags' => [[
            'status' => 'draft',
            'processing_state' => 'analyzing_tags',
        ], 'analyzing_tags'],
        'ready' => [[
            'status' => 'draft',
            'processing_state' => 'ready',
        ], 'ready'],
    ]);

it('returns rejected processing step when upload is rejected', function () {
    $owner = User::factory()->create();
    $uploadId = createUploadForStatusTests($owner->id, [
        'status' => 'rejected',
        'processing_state' => 'rejected',
    ]);

    $response = $this->actingAs($owner)->getJson("/api/uploads/{$uploadId}/status");

    $response->assertOk()->assertJsonPath('processing_state', 'rejected');
});

it('returns published processing step when upload is published', function () {
    $owner = User::factory()->create();
    $uploadId = createUploadForStatusTests($owner->id, [
        'status' => 'published',
        'processing_state' => 'published',
        'published_at' => now()->subMinute(),
    ]);

    $response = $this->actingAs($owner)->getJson("/api/uploads/{$uploadId}/status");

    $response->assertOk()->assertJsonPath('processing_state', 'published');
});
