<?php

declare(strict_types=1);

use App\Models\Artwork;
use App\Models\User;

beforeEach(function () {
    // Use null Scout driver so no Meilisearch calls are made
    config(['scout.driver' => 'null']);
});

// ── 404 cases ─────────────────────────────────────────────────────────────────

it('returns 404 for a non-existent artwork id', function () {
    $this->getJson('/api/art/99999/similar')
        ->assertStatus(404)
        ->assertJsonPath('error', 'Artwork not found');
});

it('returns 404 for a private artwork', function () {
    $artwork = Artwork::factory()->create(['is_public' => false]);

    $this->getJson("/api/art/{$artwork->id}/similar")
        ->assertStatus(404);
});

it('returns 404 for an unapproved artwork', function () {
    $artwork = Artwork::factory()->create(['is_approved' => false]);

    $this->getJson("/api/art/{$artwork->id}/similar")
        ->assertStatus(404);
});

it('returns 404 for an unpublished artwork', function () {
    $artwork = Artwork::factory()->unpublished()->create();

    $this->getJson("/api/art/{$artwork->id}/similar")
        ->assertStatus(404);
});

// ── Success cases ─────────────────────────────────────────────────────────────

it('returns a data array for a valid public artwork', function () {
    $artwork = Artwork::factory()->create([
        'is_public'    => true,
        'is_approved'  => true,
        'published_at' => now()->subDay(),
    ]);

    $response = $this->getJson("/api/art/{$artwork->id}/similar");

    $response->assertStatus(200);
    $response->assertJsonStructure(['data']);
    expect($response->json('data'))->toBeArray();
});

it('the source artwork id is never present in results', function () {
    $artwork = Artwork::factory()->create([
        'is_public'    => true,
        'is_approved'  => true,
        'published_at' => now()->subDay(),
    ]);

    $ids = collect($this->getJson("/api/art/{$artwork->id}/similar")->json('data'))
        ->pluck('id')
        ->all();

    expect($ids)->not->toContain($artwork->id);
});

it('result count does not exceed 12', function () {
    $artwork = Artwork::factory()->create([
        'is_public'    => true,
        'is_approved'  => true,
        'published_at' => now()->subDay(),
    ]);

    $count = count($this->getJson("/api/art/{$artwork->id}/similar")->json('data'));

    // null Scout driver returns 0 results; max is 12
    expect($count <= 12)->toBeTrue();
});

it('results do not include artworks by the same creator', function () {
    $creatorA = User::factory()->create();
    $creatorB = User::factory()->create();

    $source = Artwork::factory()->create([
        'user_id'      => $creatorA->id,
        'is_public'    => true,
        'is_approved'  => true,
        'published_at' => now()->subDay(),
    ]);

    // A matching artwork from a different creator
    Artwork::factory()->create([
        'user_id'      => $creatorB->id,
        'is_public'    => true,
        'is_approved'  => true,
        'published_at' => now()->subDay(),
    ]);

    $response = $this->getJson("/api/art/{$source->id}/similar");
    $response->assertStatus(200);

    $items = $response->json('data');

    // With null Scout driver the search returns 0 items; if items are present
    // none should belong to the source artwork's creator.
    foreach ($items as $item) {
        expect($item)->toHaveKeys(['id', 'title', 'slug', 'thumb', 'url', 'author_id']);
        expect($item['author_id'])->not->toBe($creatorA->id);
    }

    expect(true)->toBeTrue(); // always at least one assertion
});
