<?php

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

uses(RefreshDatabase::class);

function createCategoryForAutosaveTests(): int
{
    $contentTypeId = DB::table('content_types')->insertGetId([
        'name' => 'Photography',
        'slug' => 'photography-' . Str::lower(Str::random(6)),
        'description' => null,
        'created_at' => now(),
        'updated_at' => now(),
    ]);

    return DB::table('categories')->insertGetId([
        'content_type_id' => $contentTypeId,
        'parent_id' => null,
        'name' => 'Nature',
        'slug' => 'nature-' . Str::lower(Str::random(6)),
        'description' => null,
        'image' => null,
        'is_active' => true,
        'sort_order' => 0,
        'created_at' => now(),
        'updated_at' => now(),
    ]);
}

function createDraftUploadForAutosave(int $userId, string $status = 'draft'): string
{
    $id = (string) Str::uuid();

    DB::table('uploads')->insert([
        'id' => $id,
        'user_id' => $userId,
        'type' => 'image',
        'status' => $status,
        'title' => 'Original Title',
        'description' => 'Original Description',
        'license' => 'default',
        'nsfw' => false,
        'created_at' => now(),
        'updated_at' => now(),
    ]);

    return $id;
}

it('owner can autosave', function () {
    Storage::fake('local');

    $owner = User::factory()->create();
    $categoryId = createCategoryForAutosaveTests();
    $uploadId = createDraftUploadForAutosave($owner->id);

    $response = $this->actingAs($owner)->postJson("/api/uploads/{$uploadId}/autosave", [
        'title' => 'Updated Title',
        'category_id' => $categoryId,
        'description' => 'Updated Description',
        'tags' => ['night', 'city'],
        'license' => 'cc-by',
        'nsfw' => true,
    ]);

    $response->assertOk()->assertJsonStructure([
        'success',
        'updated_at',
    ])->assertJson([
        'success' => true,
    ]);

    $this->assertDatabaseHas('uploads', [
        'id' => $uploadId,
        'title' => 'Updated Title',
        'category_id' => $categoryId,
        'description' => 'Updated Description',
        'license' => 'cc-by',
        'nsfw' => 1,
    ]);

    $row = DB::table('uploads')->where('id', $uploadId)->first();
    expect(json_decode((string) $row->tags, true))->toBe(['night', 'city']);
});

it('partial update works', function () {
    Storage::fake('local');

    $owner = User::factory()->create();
    $uploadId = createDraftUploadForAutosave($owner->id);

    $before = DB::table('uploads')->where('id', $uploadId)->first();

    $response = $this->actingAs($owner)->postJson("/api/uploads/{$uploadId}/autosave", [
        'title' => 'Only Title Changed',
    ]);

    $response->assertOk()->assertJson([
        'success' => true,
    ]);

    $after = DB::table('uploads')->where('id', $uploadId)->first();

    expect($after->title)->toBe('Only Title Changed');
    expect($after->description)->toBe($before->description);
    expect($after->license)->toBe($before->license);
});

it('guest denied', function () {
    Storage::fake('local');

    $owner = User::factory()->create();
    $uploadId = createDraftUploadForAutosave($owner->id);

    $response = $this->postJson("/api/uploads/{$uploadId}/autosave", [
        'title' => 'Nope',
    ]);

    expect(in_array($response->getStatusCode(), [401, 403]))->toBeTrue();
});

it('other user denied', function () {
    Storage::fake('local');

    $owner = User::factory()->create();
    $other = User::factory()->create();
    $uploadId = createDraftUploadForAutosave($owner->id);

    $response = $this->actingAs($other)->postJson("/api/uploads/{$uploadId}/autosave", [
        'title' => 'Hacker Update',
    ]);

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

it('published upload rejected', function () {
    Storage::fake('local');

    $owner = User::factory()->create();
    $uploadId = createDraftUploadForAutosave($owner->id, 'published');

    $response = $this->actingAs($owner)->postJson("/api/uploads/{$uploadId}/autosave", [
        'title' => 'Should Not Save',
    ]);

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

it('invalid category rejected', function () {
    Storage::fake('local');

    $owner = User::factory()->create();
    $uploadId = createDraftUploadForAutosave($owner->id);

    $response = $this->actingAs($owner)->postJson("/api/uploads/{$uploadId}/autosave", [
        'category_id' => 999999,
    ]);

    $response->assertStatus(422)->assertJsonValidationErrors(['category_id']);
});

it('rejects autosave descriptions with raw html', function () {
    Storage::fake('local');

    $owner = User::factory()->create();
    $uploadId = createDraftUploadForAutosave($owner->id);

    $response = $this->actingAs($owner)->postJson("/api/uploads/{$uploadId}/autosave", [
        'description' => '<img src="https://spam.example/test.jpg" alt="">',
    ]);

    $response->assertStatus(422)->assertJsonValidationErrors(['description']);
});
