<?php

declare(strict_types=1);

use App\Models\Tag;
use Illuminate\Support\Facades\Cache;

it('returns matching tags from the search endpoint', function (): void {
    Tag::factory()->create(['name' => 'cityscape', 'slug' => 'cityscape', 'usage_count' => 50, 'is_active' => true]);
    Tag::factory()->create(['name' => 'city', 'slug' => 'city', 'usage_count' => 100, 'is_active' => true]);
    Tag::factory()->create(['name' => 'night', 'slug' => 'night', 'usage_count' => 30, 'is_active' => true]);

    $response = $this->getJson('/api/tags/search?q=city');

    $response->assertOk()
        ->assertJsonStructure(['data' => [['id', 'name', 'slug', 'usage_count']]])
        ->assertJsonCount(2, 'data');

    // Results sorted by usage_count desc
    $slugs = collect($response->json('data'))->pluck('slug')->all();
    expect($slugs[0])->toBe('city');
});

it('excludes inactive tags from search', function (): void {
    Tag::factory()->create(['name' => 'hidden', 'slug' => 'hidden', 'usage_count' => 999, 'is_active' => false]);

    $response = $this->getJson('/api/tags/search?q=hidden');

    $response->assertOk()->assertJsonCount(0, 'data');
});

it('returns popular tags when no query given', function (): void {
    Tag::factory()->create(['name' => 'top', 'slug' => 'top', 'usage_count' => 500, 'is_active' => true]);
    Tag::factory()->create(['name' => 'second', 'slug' => 'second', 'usage_count' => 200, 'is_active' => true]);

    $response = $this->getJson('/api/tags/search');

    $response->assertOk()
        ->assertJsonStructure(['data'])
        ->assertJsonCount(2, 'data');
});

it('returns popular tags from the popular endpoint ordered by usage_count', function (): void {
    Tag::factory()->create(['name' => 'alpha', 'slug' => 'alpha', 'usage_count' => 10, 'is_active' => true]);
    Tag::factory()->create(['name' => 'beta', 'slug' => 'beta', 'usage_count' => 80, 'is_active' => true]);
    Tag::factory()->create(['name' => 'gamma', 'slug' => 'gamma', 'usage_count' => 40, 'is_active' => true]);

    $response = $this->getJson('/api/tags/popular?limit=3');

    $response->assertOk()
        ->assertJsonCount(3, 'data');

    $slugs = collect($response->json('data'))->pluck('slug')->all();
    expect($slugs[0])->toBe('beta');
    expect($slugs[1])->toBe('gamma');
});

it('caches popular tag results', function (): void {
    Cache::flush();

    Tag::factory()->create(['name' => 'cache-me', 'slug' => 'cache-me', 'usage_count' => 1, 'is_active' => true]);

    $this->getJson('/api/tags/popular?limit=10')->assertOk();

    expect(Cache::has('tags.popular.10'))->toBeTrue();
});

it('caches search results', function (): void {
    Cache::flush();

    Tag::factory()->create(['name' => 'searchable', 'slug' => 'searchable', 'usage_count' => 1, 'is_active' => true]);

    $this->getJson('/api/tags/search?q=searchable')->assertOk();

    expect(Cache::has('tags.search.' . md5('searchable')))->toBeTrue();
});

it('respects the limit parameter on popular endpoint', function (): void {
    Tag::factory()->count(10)->sequence(fn ($s) => [
        'name'        => 'tag-' . $s->index,
        'slug'        => 'tag-' . $s->index,
        'usage_count' => $s->index,
        'is_active'   => true,
    ])->create();

    $response = $this->getJson('/api/tags/popular?limit=3');

    $response->assertOk()->assertJsonCount(3, 'data');
});
