<?php

declare(strict_types=1);

use App\Models\Artwork;
use App\Models\ArtworkEmbedding;
use App\Models\Tag;
use App\Models\User;
use App\Models\UserRecommendationCache;
use App\Services\Recommendations\SessionRecoService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Http;
use function Pest\Laravel\actingAs;
use function Pest\Laravel\getJson;

uses(RefreshDatabase::class);

it('can serve the feed through the v2 selector path', function () {
    config()->set('discovery.v2.enabled', true);
    config()->set('discovery.v2.rollout_percentage', 100);
    config()->set('discovery.v2.algo_version', 'clip-cosine-v2-adaptive');

    $user = User::factory()->create();
    $creator = User::factory()->create();
    $artwork = Artwork::factory()->create([
        'user_id' => $creator->id,
        'is_public' => true,
        'is_approved' => true,
        'published_at' => now()->subHour(),
        'trending_score_1h' => 5,
        'trending_score_24h' => 10,
        'trending_score_7d' => 20,
    ]);

    $tag = Tag::query()->create(['name' => 'Abstract', 'slug' => 'abstract']);
    DB::table('artwork_tag')->insert([
        'artwork_id' => $artwork->id,
        'tag_id' => $tag->id,
        'source' => 'user',
        'created_at' => now(),
    ]);

    DB::table('artwork_stats')->insert([
        'artwork_id' => $artwork->id,
        'views' => 150,
        'downloads' => 20,
        'favorites' => 15,
        'comments_count' => 5,
        'shares_count' => 2,
        'views_24h' => 150,
        'views_7d' => 150,
        'downloads_24h' => 20,
        'downloads_7d' => 20,
        'shares_24h' => 2,
        'comments_24h' => 5,
        'favourites_24h' => 15,
        'views_1h' => 40,
        'downloads_1h' => 5,
        'favourites_1h' => 4,
        'comments_1h' => 2,
        'shares_1h' => 1,
        'ranking_score' => 50,
        'engagement_velocity' => 12,
        'heat_score' => 30,
        'rating_avg' => 0,
        'rating_count' => 0,
    ]);

    UserRecommendationCache::query()->create([
        'user_id' => $user->id,
        'algo_version' => 'clip-cosine-v2-adaptive',
        'cache_version' => 'cache-v2',
        'recommendations_json' => [
            'items' => [
                ['artwork_id' => $artwork->id, 'score' => 1.2, 'source' => 'trending', 'layer_sources' => ['trending']],
            ],
        ],
        'generated_at' => now(),
        'expires_at' => now()->addMinutes(10),
    ]);

    actingAs($user);
    $response = getJson('/api/v1/feed?algo_version=clip-cosine-v2-adaptive&limit=2');

    $response->assertOk();
    $response->assertJsonPath('meta.engine', 'v2');
    $response->assertJsonPath('meta.algo_version', 'clip-cosine-v2-adaptive');
    $response->assertJsonPath('meta.local_embedding_count', 0);
    $response->assertJsonPath('meta.vector_indexed_count', 0);
    $response->assertJsonPath('data.0.primary_tag.slug', 'abstract');
    $response->assertJsonPath('data.0.has_local_embedding', false);
    $response->assertJsonPath('data.0.vector_indexed_at', null);
    $response->assertJsonPath('data.0.ranking_signals.local_embedding_present', false);
    $response->assertJsonPath('data.0.ranking_signals.vector_indexed_at', null);
    expect((array) $response->json('data'))->toHaveCount(1);
});

it('boosts vector-similar candidates in the v3 hybrid feed', function () {
    config()->set('discovery.v2.enabled', true);
    config()->set('discovery.v2.rollout_percentage', 100);
    config()->set('discovery.v2.algo_version', 'clip-cosine-v2-adaptive');
    config()->set('discovery.v3.enabled', true);
    config()->set('discovery.v3.vector_similarity_weight', 2.0);
    config()->set('vision.vector_gateway.enabled', true);
    config()->set('vision.vector_gateway.base_url', 'https://vision.klevze.net');
    config()->set('vision.vector_gateway.api_key', 'test-key');
    config()->set('vision.vector_gateway.search_endpoint', '/vectors/search');
    config()->set('cdn.files_url', 'https://files.skinbase.org');

    $user = User::factory()->create();
    $creator = User::factory()->create();
    $seedArtwork = Artwork::factory()->create([
        'user_id' => $creator->id,
        'hash' => 'aabbcc112233',
        'thumb_ext' => 'webp',
        'is_public' => true,
        'is_approved' => true,
        'published_at' => now()->subDays(10),
    ]);

    $vectorMatch = Artwork::factory()->create([
        'user_id' => $creator->id,
        'hash' => 'ddeeff445566',
        'thumb_ext' => 'webp',
        'title' => 'Vector winner',
        'slug' => 'vector-winner',
        'is_public' => true,
        'is_approved' => true,
        'published_at' => now()->subDays(10),
        'trending_score_1h' => 5,
        'trending_score_24h' => 5,
        'trending_score_7d' => 5,
        'last_vector_indexed_at' => now()->subMinutes(5),
    ]);

    $trendingLeader = Artwork::factory()->create([
        'user_id' => $creator->id,
        'hash' => '778899001122',
        'thumb_ext' => 'webp',
        'title' => 'Trending leader',
        'slug' => 'trending-leader',
        'is_public' => true,
        'is_approved' => true,
        'published_at' => now()->subDays(10),
        'trending_score_1h' => 30,
        'trending_score_24h' => 30,
        'trending_score_7d' => 30,
    ]);

    $sectionArtwork = Artwork::factory()->create([
        'user_id' => $creator->id,
        'hash' => '334455667788',
        'thumb_ext' => 'webp',
        'title' => 'Section artwork',
        'slug' => 'section-artwork',
        'is_public' => true,
        'is_approved' => true,
        'published_at' => now()->subDays(10),
        'trending_score_1h' => 6,
        'trending_score_24h' => 6,
        'trending_score_7d' => 6,
    ]);

    ArtworkEmbedding::query()->create([
        'artwork_id' => $vectorMatch->id,
        'model' => 'clip',
        'model_version' => 'v1',
        'algo_version' => 'clip-cosine-v1',
        'dim' => 2,
        'embedding_json' => json_encode([0.6, 0.8], JSON_THROW_ON_ERROR),
        'source_hash' => 'ddeeff445566',
        'is_normalized' => true,
        'generated_at' => now(),
        'meta' => ['source' => 'clip'],
    ]);

    foreach ([$seedArtwork, $vectorMatch, $trendingLeader, $sectionArtwork] as $artwork) {
        DB::table('artwork_stats')->insert([
            'artwork_id' => $artwork->id,
            'views' => 100,
            'downloads' => 10,
            'favorites' => 8,
            'comments_count' => 3,
            'shares_count' => 1,
            'views_24h' => 100,
            'views_7d' => 100,
            'downloads_24h' => 10,
            'downloads_7d' => 10,
            'shares_24h' => 1,
            'comments_24h' => 3,
            'favourites_24h' => 8,
            'views_1h' => 20,
            'downloads_1h' => 2,
            'favourites_1h' => 2,
            'comments_1h' => 1,
            'shares_1h' => 1,
            'ranking_score' => 25,
            'engagement_velocity' => 8,
            'heat_score' => 15,
            'rating_avg' => 0,
            'rating_count' => 0,
        ]);
    }

    Http::fake(function ($request) use ($seedArtwork, $vectorMatch, $sectionArtwork) {
        $payload = json_decode($request->body(), true);
        $url = (string) ($payload['url'] ?? '');

        if (str_contains($url, 'aabbcc112233')) {
            return Http::response([
                'results' => [
                    ['id' => $seedArtwork->id, 'score' => 1.0],
                    ['id' => $vectorMatch->id, 'score' => 0.98],
                ],
            ], 200);
        }

        if (str_contains($url, 'ddeeff445566')) {
            return Http::response([
                'results' => [
                    ['id' => $vectorMatch->id, 'score' => 1.0],
                    ['id' => $sectionArtwork->id, 'score' => 0.91],
                ],
            ], 200);
        }

        return Http::response(['results' => []], 200);
    });

    app(SessionRecoService::class)->applyEvent(
        userId: $user->id,
        eventType: 'view',
        artworkId: $seedArtwork->id,
        categoryId: null,
        occurredAt: now()->toIso8601String(),
        meta: []
    );

    actingAs($user);
    $response = getJson('/api/v1/feed?algo_version=clip-cosine-v2-adaptive&limit=2');

    $response->assertOk();
    $response->assertJsonPath('meta.engine', 'v2');
    $response->assertJsonPath('meta.vector_influenced_count', 1);
    $response->assertJsonPath('meta.local_embedding_count', 1);
    $response->assertJsonPath('meta.vector_indexed_count', 1);
    $response->assertJsonPath('data.0.id', $vectorMatch->id);
    $response->assertJsonPath('data.0.source', 'vector');
    $response->assertJsonPath('data.0.reason', 'Visually similar to art you engaged with');
    $response->assertJsonPath('data.0.vector_influenced', true);
    $response->assertJsonPath('data.0.has_local_embedding', true);
    expect($response->json('data.0.vector_indexed_at'))->not->toBeNull();
    $response->assertJsonPath('data.0.ranking_signals.vector_similarity_score', 0.98);
    $response->assertJsonPath('data.0.ranking_signals.local_embedding_present', true);
    expect($response->json('data.0.ranking_signals.vector_indexed_at'))->not->toBeNull();
    $response->assertJsonPath('sections.0.key', 'similar_style');
    $response->assertJsonPath('sections.1.key', 'you_may_also_like');
    $response->assertJsonPath('sections.2.key', 'visually_related');
    $response->assertJsonPath('sections.0.items.0.id', $sectionArtwork->id);
    $response->assertJsonPath('sections.2.items.0.id', $sectionArtwork->id);
});
