<?php

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

uses(RefreshDatabase::class);

function createCleanupUpload(array $overrides = []): string
{
    $id = (string) Str::uuid();

    $defaults = [
        'id' => $id,
        'user_id' => User::factory()->create()->id,
        '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('runs uploads cleanup command and deletes stale drafts', function () {
    Storage::fake('local');

    $expiredId = createCleanupUpload([
        'status' => 'draft',
        'expires_at' => now()->subMinute(),
    ]);

    $activeId = createCleanupUpload([
        'status' => 'draft',
        'expires_at' => now()->addHours(2),
        'updated_at' => now()->subHours(2),
    ]);

    Storage::disk('local')->put("tmp/drafts/{$expiredId}/meta.json", '{}');
    Storage::disk('local')->put("tmp/drafts/{$activeId}/meta.json", '{}');

    $code = Artisan::call('uploads:cleanup');

    expect($code)->toBe(0);
    expect(Artisan::output())->toContain('Uploads cleanup deleted 1 draft(s).');

    expect(DB::table('uploads')->where('id', $expiredId)->exists())->toBeFalse();
    expect(DB::table('uploads')->where('id', $activeId)->where('status', 'draft')->exists())->toBeTrue();
    expect(Storage::disk('local')->exists("tmp/drafts/{$expiredId}/meta.json"))->toBeFalse();
    expect(Storage::disk('local')->exists("tmp/drafts/{$activeId}/meta.json"))->toBeTrue();
});

it('respects command limit option', function () {
    Storage::fake('local');

    for ($index = 0; $index < 5; $index++) {
        $uploadId = createCleanupUpload([
            'status' => 'draft',
            'updated_at' => now()->subHours(26),
        ]);

        Storage::disk('local')->put("tmp/drafts/{$uploadId}/meta.json", '{}');
    }

    $code = Artisan::call('uploads:cleanup', ['--limit' => 2]);

    expect($code)->toBe(0);
    expect(Artisan::output())->toContain('Uploads cleanup deleted 2 draft(s).');

    expect(DB::table('uploads')->count())->toBe(3);
});
