<?php

declare(strict_types=1);

use App\Models\Artwork;
use App\Models\User;
use App\Models\UserFollower;
use App\Models\UserRecommendationCache;
use Illuminate\Foundation\Testing\RefreshDatabase;

uses(RefreshDatabase::class);

beforeEach(function () {
    // Disable Meilisearch so tests remain fast
    config(['scout.driver' => 'null']);
});

// ─────────────────────────────────────────────────────────────────────────────
// /discover/for-you
// ─────────────────────────────────────────────────────────────────────────────

it('redirects guests away from /discover/for-you', function () {
    $this->get('/discover/for-you')
        ->assertRedirect();
});

it('renders For You page for authenticated user', function () {
    $user = User::factory()->create();

    $this->actingAs($user)
        ->get('/discover/for-you')
        ->assertOk();
});

it('For You page shows empty state with no prior activity', function () {
    $user = User::factory()->create();

    $this->actingAs($user)
        ->get('/discover/for-you')
        ->assertOk()
        ->assertSee('For You');
});

it('For You page uses cached recommendations when available', function () {
    $user    = User::factory()->create();
    $artwork = Artwork::factory()->create([
        'is_public'    => true,
        'is_approved'  => true,
        'published_at' => now()->subMinutes(5),
    ]);

    UserRecommendationCache::query()->create([
        'user_id'              => $user->id,
        'algo_version'         => (string) config('discovery.algo_version', 'clip-cosine-v1'),
        'cache_version'        => (string) config('discovery.cache_version', 'cache-v1'),
        'recommendations_json' => [
            'items' => [
                ['artwork_id' => $artwork->id, 'score' => 0.9, 'source' => 'profile'],
            ],
        ],
        'generated_at' => now(),
        'expires_at'   => now()->addMinutes(30),
    ]);

    $this->actingAs($user)
        ->get('/discover/for-you')
        ->assertOk();
});

// ─────────────────────────────────────────────────────────────────────────────
// /api/user/suggestions/creators
// ─────────────────────────────────────────────────────────────────────────────

it('requires auth for suggested creators endpoint', function () {
    $this->getJson('/api/user/suggestions/creators')
        ->assertUnauthorized();
});

it('returns data array from suggested creators endpoint', function () {
    $user = User::factory()->create();

    $this->actingAs($user)
        ->getJson('/api/user/suggestions/creators')
        ->assertOk()
        ->assertJsonStructure(['data']);
});

it('suggested creators does not include the requesting user', function () {
    $user = User::factory()->create();

    $response = $this->actingAs($user)
        ->getJson('/api/user/suggestions/creators')
        ->assertOk();

    $ids = collect($response->json('data'))->pluck('id')->all();
    expect($ids)->not->toContain($user->id);
});

it('suggested creators excludes already-followed creators', function () {
    $user     = User::factory()->create();
    $followed = User::factory()->create();

    UserFollower::create([
        'user_id'     => $followed->id,
        'follower_id' => $user->id,
    ]);

    $response = $this->actingAs($user)
        ->getJson('/api/user/suggestions/creators')
        ->assertOk();

    $ids = collect($response->json('data'))->pluck('id')->all();
    expect($ids)->not->toContain($followed->id);
});

// ─────────────────────────────────────────────────────────────────────────────
// /api/user/suggestions/tags
// ─────────────────────────────────────────────────────────────────────────────

it('requires auth for suggested tags endpoint', function () {
    $this->getJson('/api/user/suggestions/tags')
        ->assertUnauthorized();
});

it('returns data array from suggested tags endpoint', function () {
    $user = User::factory()->create();

    $this->actingAs($user)
        ->getJson('/api/user/suggestions/tags')
        ->assertOk()
        ->assertJsonStructure(['data']);
});

it('suggested tags returns correct shape', function () {
    $user = User::factory()->create();

    $response = $this->actingAs($user)
        ->getJson('/api/user/suggestions/tags')
        ->assertOk();

    $data = $response->json('data');
    expect($data)->toBeArray();

    // If non-empty each item must have these keys
    foreach ($data as $item) {
        expect($item)->toHaveKeys(['id', 'name', 'slug', 'usage_count', 'source']);
    }
});

// ─────────────────────────────────────────────────────────────────────────────
// Similar artworks cache TTL
// ─────────────────────────────────────────────────────────────────────────────

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

    $this->getJson("/api/art/{$artwork->id}/similar")
        ->assertOk()
        ->assertJsonStructure(['data']);
});

it('similar artworks response is cached (second call hits cache layer)', function () {
    $artwork = Artwork::factory()->create([
        'is_public'    => true,
        'is_approved'  => true,
        'published_at' => now()->subDay(),
    ]);

    // Two consecutive calls – the second must also succeed (confirming cache does not corrupt)
    $this->getJson("/api/art/{$artwork->id}/similar")->assertOk();
    $this->getJson("/api/art/{$artwork->id}/similar")->assertOk();
});
