<?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 createCategoryForPublishEndpointTests(): 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' => 'Street',
        'slug' => 'street-' . Str::lower(Str::random(6)),
        'description' => null,
        'image' => null,
        'is_active' => true,
        'sort_order' => 0,
        'created_at' => now(),
        'updated_at' => now(),
    ]);
}

function createReadyDraftForPublishEndpoint(int $ownerId, int $categoryId, string $status = 'draft'): array
{
    $uploadId = (string) Str::uuid();
    $hash = 'aabbccddeeff00112233';

    DB::table('uploads')->insert([
        'id' => $uploadId,
        'user_id' => $ownerId,
        'type' => 'image',
        'status' => $status,
        'moderation_status' => 'approved',
        'title' => 'Publish Endpoint Test',
        'category_id' => $categoryId,
        'is_scanned' => true,
        'has_tags' => true,
        'preview_path' => "tmp/drafts/{$uploadId}/preview.webp",
        'created_at' => now(),
        'updated_at' => now(),
    ]);

    Storage::disk('local')->put("tmp/drafts/{$uploadId}/main/main.jpg", 'jpg');
    Storage::disk('local')->put("tmp/drafts/{$uploadId}/preview.webp", 'preview');

    DB::table('upload_files')->insert([
        'upload_id' => $uploadId,
        'path' => "tmp/drafts/{$uploadId}/main/main.jpg",
        'type' => 'main',
        'hash' => $hash,
        'size' => 3,
        'mime' => 'image/jpeg',
        'created_at' => now(),
    ]);

    return [$uploadId, $hash];
}

it('owner can publish valid draft', function () {
    Storage::fake('local');

    $owner = User::factory()->create();
    $categoryId = createCategoryForPublishEndpointTests();
    [$uploadId, $hash] = createReadyDraftForPublishEndpoint($owner->id, $categoryId);

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

    $response->assertOk()->assertJsonStructure([
        'success',
        'upload_id',
        'status',
        'published_at',
        'final_path',
    ])->assertJson([
        'success' => true,
        'upload_id' => $uploadId,
        'status' => 'published',
        'final_path' => 'files/artworks/aa/bb/' . $hash,
    ]);
});

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

    $owner = User::factory()->create();
    $categoryId = createCategoryForPublishEndpointTests();
    [$uploadId] = createReadyDraftForPublishEndpoint($owner->id, $categoryId);

    $response = $this->postJson("/api/uploads/{$uploadId}/publish");

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

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

    $owner = User::factory()->create();
    $other = User::factory()->create();
    $categoryId = createCategoryForPublishEndpointTests();
    [$uploadId] = createReadyDraftForPublishEndpoint($owner->id, $categoryId);

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

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

it('incomplete draft rejected', function () {
    Storage::fake('local');

    $owner = User::factory()->create();
    $categoryId = createCategoryForPublishEndpointTests();
    [$uploadId] = createReadyDraftForPublishEndpoint($owner->id, $categoryId);

    DB::table('uploads')->where('id', $uploadId)->update(['title' => null]);

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

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

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

    $owner = User::factory()->create();
    $categoryId = createCategoryForPublishEndpointTests();
    [$uploadId] = createReadyDraftForPublishEndpoint($owner->id, $categoryId, 'published');

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

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