<?php

declare(strict_types=1);

use App\Jobs\Enhance\ProcessEnhanceJob;
use App\Models\EnhanceJob;
use App\Models\User;
use Illuminate\Support\Facades\Queue;
use Illuminate\Support\Facades\Storage;

beforeEach(function (): void {
    config()->set('enhance.disk', 'public');
    Storage::fake('public');
    Queue::fake();
});

it('blocks regular users from moderation enhance write actions', function (): void {
    $user = User::factory()->create();
    $owner = User::factory()->create();

    $job = EnhanceJob::query()->create([
        'user_id' => $owner->id,
        'status' => EnhanceJob::STATUS_FAILED,
        'engine' => EnhanceJob::ENGINE_STUB,
        'mode' => 'standard',
        'scale' => 2,
    ]);

    $this->actingAs($user)
        ->post(route('admin.enhance.retry', ['enhanceJob' => $job]))
        ->assertForbidden();

    $this->actingAs($user)
        ->post(route('admin.enhance.mark-failed', ['enhanceJob' => $job]))
        ->assertForbidden();

    $this->actingAs($user)
        ->delete(route('admin.enhance.destroy', ['enhanceJob' => $job]))
        ->assertForbidden();
});

it('allows a moderator to retry a failed enhance job', function (): void {
    $moderator = User::factory()->create(['role' => 'moderator']);
    $owner = User::factory()->create();
    Storage::disk('public')->put('enhance/sources/20/source.png', 'source');

    $job = EnhanceJob::query()->create([
        'user_id' => $owner->id,
        'status' => EnhanceJob::STATUS_FAILED,
        'engine' => EnhanceJob::ENGINE_STUB,
        'mode' => 'standard',
        'scale' => 2,
        'source_disk' => 'public',
        'source_path' => 'enhance/sources/20/source.png',
    ]);

    $this->actingAs($moderator)
        ->post(route('admin.enhance.retry', ['enhanceJob' => $job]))
        ->assertRedirect(route('admin.enhance.show', ['enhanceJob' => $job]));

    $job->refresh();

    expect($job->status)->toBe(EnhanceJob::STATUS_QUEUED);
    Queue::assertPushed(ProcessEnhanceJob::class);
});

it('allows a moderator to mark a stuck processing job as failed', function (): void {
    $moderator = User::factory()->create(['role' => 'moderator']);
    $owner = User::factory()->create();

    $job = EnhanceJob::query()->create([
        'user_id' => $owner->id,
        'status' => EnhanceJob::STATUS_PROCESSING,
        'engine' => EnhanceJob::ENGINE_STUB,
        'mode' => 'standard',
        'scale' => 2,
        'started_at' => now()->subMinutes(40),
    ]);

    $this->actingAs($moderator)
        ->post(route('admin.enhance.mark-failed', ['enhanceJob' => $job]))
        ->assertRedirect(route('admin.enhance.show', ['enhanceJob' => $job]));

    $job->refresh();

    expect($job->status)->toBe(EnhanceJob::STATUS_FAILED);
    expect($job->error_message)->toBe('Marked as failed by moderator.');
    expect($job->metadata['moderation']['marked_failed_by'])->toBe($moderator->id);
});

it('uses safe cleanup when moderation deletes a job', function (): void {
    $moderator = User::factory()->create(['role' => 'moderator']);
    $owner = User::factory()->create();
    Storage::disk('public')->put('uploads/artworks/unsafe.png', 'unsafe');
    Storage::disk('public')->put('enhance/outputs/21/output.webp', 'output');

    $job = EnhanceJob::query()->create([
        'user_id' => $owner->id,
        'status' => EnhanceJob::STATUS_COMPLETED,
        'engine' => EnhanceJob::ENGINE_STUB,
        'mode' => 'standard',
        'scale' => 2,
        'source_disk' => 'public',
        'source_path' => 'uploads/artworks/unsafe.png',
        'output_disk' => 'public',
        'output_path' => 'enhance/outputs/21/output.webp',
    ]);

    $this->actingAs($moderator)
        ->delete(route('admin.enhance.destroy', ['enhanceJob' => $job]))
        ->assertRedirect(route('admin.enhance.index'));

    expect(EnhanceJob::withTrashed()->find($job->id)?->trashed())->toBeTrue();
    Storage::disk('public')->assertExists('uploads/artworks/unsafe.png');
    Storage::disk('public')->assertMissing('enhance/outputs/21/output.webp');
});