<?php

use App\Models\Artwork;
use App\Models\Category;
use App\Models\ContentType;
use App\Models\Group;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\DB;

uses(RefreshDatabase::class);

it('keeps similar artworks results queries bounded when hydrating gallery items', function (): void {
    $author = User::factory()->create([
        'username' => 'similar-results-author',
        'name' => 'Similar Results Author',
    ]);

    $contentType = ContentType::query()->create([
        'name' => 'Skins',
        'slug' => 'skins',
        'description' => 'Skins content type',
    ]);

    $category = Category::query()->create([
        'content_type_id' => $contentType->id,
        'name' => 'Internet',
        'slug' => 'internet-similar-results',
        'description' => 'Internet skins',
        'is_active' => true,
        'sort_order' => 1,
    ]);

    $source = Artwork::factory()->for($author)->create([
        'title' => 'Similar Results Source',
        'slug' => 'similar-results-source',
        'published_at' => now()->subHour(),
        'is_public' => true,
        'is_approved' => true,
    ]);
    $source->categories()->attach($category->id);

    foreach (range(1, 20) as $index) {
        $artwork = Artwork::factory()->for($author)->create([
            'title' => 'Similar Results Artwork ' . $index,
            'slug' => 'similar-results-artwork-' . $index,
            'published_at' => now()->subMinutes($index),
            'is_public' => true,
            'is_approved' => true,
        ]);

        $artwork->categories()->attach($category->id);
    }

    $categoryQueryCount = 0;
    $userQueryCount = 0;
    DB::listen(function ($query) use (&$categoryQueryCount, &$userQueryCount): void {
        if (preg_match('/\b(from|join)\s+["`\[]?artwork_category\b/i', $query->sql) === 1 || preg_match('/\bfrom\s+["`\[]?categories\b/i', $query->sql) === 1) {
            $categoryQueryCount++;
        }

        if (preg_match('/\bfrom\s+["`\[]?users\b/i', $query->sql) === 1) {
            $userQueryCount++;
        }
    });

    $this->getJson('/art/' . $source->id . '/similar-results')
        ->assertOk()
        ->assertJsonStructure(['data', 'similarity_source', 'total', 'current_page', 'last_page']);

    expect($categoryQueryCount)->toBeLessThanOrEqual(4);
    expect($userQueryCount)->toBeLessThanOrEqual(3);
});

it('keeps similar artworks results group queries bounded for group publishers', function (): void {
    $author = User::factory()->create([
        'username' => 'similar-results-group-author',
        'name' => 'Similar Results Group Author',
    ]);

    $group = Group::factory()->create([
        'owner_user_id' => $author->id,
        'name' => 'Similar Results Group',
        'slug' => 'similar-results-group',
        'visibility' => Group::VISIBILITY_PUBLIC,
        'status' => Group::LIFECYCLE_ACTIVE,
    ]);

    $contentType = ContentType::query()->create([
        'name' => 'Skins',
        'slug' => 'skins',
        'description' => 'Skins content type',
    ]);

    $category = Category::query()->create([
        'content_type_id' => $contentType->id,
        'name' => 'Internet',
        'slug' => 'internet-similar-results-group',
        'description' => 'Internet skins',
        'is_active' => true,
        'sort_order' => 1,
    ]);

    $source = Artwork::factory()->for($author)->create([
        'title' => 'Similar Results Group Source',
        'slug' => 'similar-results-group-source',
        'group_id' => $group->id,
        'published_as_type' => Artwork::PUBLISHED_AS_GROUP,
        'published_as_id' => $group->id,
        'published_at' => now()->subHour(),
        'is_public' => true,
        'is_approved' => true,
    ]);
    $source->categories()->attach($category->id);

    foreach (range(1, 16) as $index) {
        $artwork = Artwork::factory()->for($author)->create([
            'title' => 'Similar Results Group Artwork ' . $index,
            'slug' => 'similar-results-group-artwork-' . $index,
            'group_id' => $group->id,
            'published_as_type' => Artwork::PUBLISHED_AS_GROUP,
            'published_as_id' => $group->id,
            'published_at' => now()->subMinutes($index),
            'is_public' => true,
            'is_approved' => true,
        ]);

        $artwork->categories()->attach($category->id);
    }

    $groupQueryCount = 0;
    DB::listen(function ($query) use (&$groupQueryCount): void {
        if (preg_match('/\bfrom\s+["`\[]?groups\b/i', $query->sql) === 1) {
            $groupQueryCount++;
        }
    });

    $this->getJson('/art/' . $source->id . '/similar-results')
        ->assertOk()
        ->assertJsonStructure(['data', 'similarity_source', 'total', 'current_page', 'last_page']);

    expect($groupQueryCount)->toBeLessThanOrEqual(3);
});