<?php

declare(strict_types=1);

use App\Models\Artwork;
use App\Models\User;
use App\Services\HomepageService;
use App\Services\ArtworkService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\DB;

uses(RefreshDatabase::class);

function makeFeaturedArtwork(array $attributes = []): Artwork
{
    return Artwork::factory()->create(array_merge([
        'is_public' => true,
        'is_approved' => true,
        'published_at' => now()->subDay(),
    ], $attributes));
}

test('featured hero ordering uses recent medal score as tie-break inside the same priority', function () {
    $owner = User::factory()->create();
    $artworkA = makeFeaturedArtwork(['user_id' => $owner->id, 'title' => 'A']);
    $artworkB = makeFeaturedArtwork(['user_id' => $owner->id, 'title' => 'B']);

    foreach ([$artworkA, $artworkB] as $artwork) {
        DB::table('artwork_features')->insert([
            'artwork_id' => $artwork->id,
            'featured_at' => now()->subHour(),
            'expires_at' => null,
            'priority' => 100,
            'label' => null,
            'note' => null,
            'is_active' => true,
            'created_by' => null,
            'created_at' => now(),
            'updated_at' => now(),
            'deleted_at' => null,
        ]);
    }

    DB::table('artwork_medal_stats')->insert([
        'artwork_id' => $artworkA->id,
        'gold_count' => 0,
        'silver_count' => 1,
        'bronze_count' => 0,
        'score_total' => 3,
        'score_7d' => 3,
        'score_30d' => 3,
        'last_medaled_at' => now()->subDay(),
        'created_at' => now(),
        'updated_at' => now(),
    ]);

    DB::table('artwork_medal_stats')->insert([
        'artwork_id' => $artworkB->id,
        'gold_count' => 1,
        'silver_count' => 0,
        'bronze_count' => 0,
        'score_total' => 5,
        'score_7d' => 5,
        'score_30d' => 5,
        'last_medaled_at' => now()->subHour(),
        'created_at' => now(),
        'updated_at' => now(),
    ]);

    $featured = app(ArtworkService::class)->getFeaturedArtworks(null, 1);

    expect($featured->items()[0]->id)->toBe($artworkB->id);
});

test('featured query excludes inactive and expired feature rows', function () {
    $owner = User::factory()->create();
    $activeArtwork = makeFeaturedArtwork(['user_id' => $owner->id, 'title' => 'Active']);
    $inactiveArtwork = makeFeaturedArtwork(['user_id' => $owner->id, 'title' => 'Inactive']);
    $expiredArtwork = makeFeaturedArtwork(['user_id' => $owner->id, 'title' => 'Expired']);

    DB::table('artwork_features')->insert([
        [
            'artwork_id' => $activeArtwork->id,
            'featured_at' => now()->subHour(),
            'expires_at' => null,
            'priority' => 50,
            'label' => null,
            'note' => null,
            'is_active' => true,
            'created_by' => null,
            'created_at' => now(),
            'updated_at' => now(),
            'deleted_at' => null,
        ],
        [
            'artwork_id' => $inactiveArtwork->id,
            'featured_at' => now(),
            'expires_at' => null,
            'priority' => 999,
            'label' => null,
            'note' => null,
            'is_active' => false,
            'created_by' => null,
            'created_at' => now(),
            'updated_at' => now(),
            'deleted_at' => null,
        ],
        [
            'artwork_id' => $expiredArtwork->id,
            'featured_at' => now(),
            'expires_at' => now()->subMinute(),
            'priority' => 999,
            'label' => null,
            'note' => null,
            'is_active' => true,
            'created_by' => null,
            'created_at' => now(),
            'updated_at' => now(),
            'deleted_at' => null,
        ],
    ]);

    $featuredIds = app(ArtworkService::class)
        ->getFeaturedArtworks(null, 10)
        ->getCollection()
        ->pluck('id')
        ->all();

    expect($featuredIds)->toContain($activeArtwork->id)
        ->and($featuredIds)->not->toContain($inactiveArtwork->id)
        ->and($featuredIds)->not->toContain($expiredArtwork->id);
});

test('featured hero sorts by priority before featured_at', function () {
    $owner = User::factory()->create();
    $higherPriority = makeFeaturedArtwork(['user_id' => $owner->id, 'title' => 'Higher Priority']);
    $newerFeaturedAt = makeFeaturedArtwork(['user_id' => $owner->id, 'title' => 'Newer Featured']);

    DB::table('artwork_features')->insert([
        [
            'artwork_id' => $higherPriority->id,
            'featured_at' => now()->subDays(2),
            'expires_at' => null,
            'priority' => 200,
            'label' => null,
            'note' => null,
            'is_active' => true,
            'created_by' => null,
            'created_at' => now(),
            'updated_at' => now(),
            'deleted_at' => null,
        ],
        [
            'artwork_id' => $newerFeaturedAt->id,
            'featured_at' => now(),
            'expires_at' => null,
            'priority' => 100,
            'label' => null,
            'note' => null,
            'is_active' => true,
            'created_by' => null,
            'created_at' => now(),
            'updated_at' => now(),
            'deleted_at' => null,
        ],
    ]);

    $featured = app(ArtworkService::class)->getFeaturedArtworks(null, 1);

    expect($featured->items()[0]->id)->toBe($higherPriority->id);
});

test('force hero overrides normal homepage eligibility filters without leaking into the public featured listing', function () {
    $owner = User::factory()->create();
    $forcedHero = makeFeaturedArtwork([
        'user_id' => $owner->id,
        'title' => 'Forced Hero',
        'has_missing_thumbnails' => true,
    ]);
    $naturalWinner = makeFeaturedArtwork([
        'user_id' => $owner->id,
        'title' => 'Natural Winner',
    ]);

    DB::table('artwork_features')->insert([
        [
            'artwork_id' => $forcedHero->id,
            'featured_at' => now()->subDays(2),
            'expires_at' => null,
            'priority' => 50,
            'label' => null,
            'note' => null,
            'is_active' => true,
            'force_hero' => true,
            'created_by' => null,
            'created_at' => now(),
            'updated_at' => now(),
            'deleted_at' => null,
        ],
        [
            'artwork_id' => $naturalWinner->id,
            'featured_at' => now()->subHour(),
            'expires_at' => null,
            'priority' => 500,
            'label' => null,
            'note' => null,
            'is_active' => true,
            'force_hero' => false,
            'created_by' => null,
            'created_at' => now(),
            'updated_at' => now(),
            'deleted_at' => null,
        ],
    ]);

    $winner = app(ArtworkService::class)->getFeaturedArtworkWinner();
    $featuredIds = app(ArtworkService::class)
        ->getFeaturedArtworks(null, 10)
        ->getCollection()
        ->pluck('id')
        ->all();

    expect($winner?->id)->toBe($forcedHero->id)
        ->and($featuredIds)->toContain($naturalWinner->id)
        ->and($featuredIds)->not->toContain($forcedHero->id);
});

test('homepage hero payload uses the forced hero artwork when one is set', function () {
    $owner = User::factory()->create();
    $forcedHero = makeFeaturedArtwork([
        'user_id' => $owner->id,
        'title' => 'Forced Homepage Hero',
        'has_missing_thumbnails' => true,
    ]);
    $naturalWinner = makeFeaturedArtwork([
        'user_id' => $owner->id,
        'title' => 'Natural Homepage Winner',
    ]);

    DB::table('artwork_features')->insert([
        [
            'artwork_id' => $forcedHero->id,
            'featured_at' => now()->subDays(2),
            'expires_at' => null,
            'priority' => 10,
            'label' => null,
            'note' => null,
            'is_active' => true,
            'force_hero' => true,
            'created_by' => null,
            'created_at' => now(),
            'updated_at' => now(),
            'deleted_at' => null,
        ],
        [
            'artwork_id' => $naturalWinner->id,
            'featured_at' => now()->subHour(),
            'expires_at' => null,
            'priority' => 500,
            'label' => null,
            'note' => null,
            'is_active' => true,
            'force_hero' => false,
            'created_by' => null,
            'created_at' => now(),
            'updated_at' => now(),
            'deleted_at' => null,
        ],
    ]);

    $hero = app(HomepageService::class)->getHeroArtwork();

    expect($hero)->not->toBeNull()
        ->and($hero['id'])->toBe($forcedHero->id)
        ->and($hero['title'])->toBe('Forced Homepage Hero');
});

test('community favorites returns artworks ordered by recent medal score', function () {
    $owner = User::factory()->create();
    $leader = makeFeaturedArtwork(['user_id' => $owner->id, 'title' => 'Leader']);
    $runnerUp = makeFeaturedArtwork(['user_id' => $owner->id, 'title' => 'Runner Up', 'published_at' => now()->subDays(2)]);

    DB::table('artwork_medal_stats')->insert([
        [
            'artwork_id' => $runnerUp->id,
            'gold_count' => 0,
            'silver_count' => 2,
            'bronze_count' => 0,
            'score_total' => 6,
            'score_7d' => 6,
            'score_30d' => 6,
            'last_medaled_at' => now()->subHour(),
            'created_at' => now(),
            'updated_at' => now(),
        ],
        [
            'artwork_id' => $leader->id,
            'gold_count' => 2,
            'silver_count' => 0,
            'bronze_count' => 0,
            'score_total' => 10,
            'score_7d' => 10,
            'score_30d' => 10,
            'last_medaled_at' => now(),
            'created_at' => now(),
            'updated_at' => now(),
        ],
    ]);

    $results = app(HomepageService::class)->getCommunityFavorites(8);

    expect($results)->toHaveCount(2)
        ->and($results[0]['id'])->toBe($leader->id)
        ->and($results[1]['id'])->toBe($runnerUp->id);
});

test('hall of fame returns artworks ordered by all time medal score', function () {
    $owner = User::factory()->create();
    $leader = makeFeaturedArtwork(['user_id' => $owner->id, 'title' => 'Legend']);
    $runnerUp = makeFeaturedArtwork(['user_id' => $owner->id, 'title' => 'Veteran']);

    DB::table('artwork_medal_stats')->insert([
        [
            'artwork_id' => $runnerUp->id,
            'gold_count' => 1,
            'silver_count' => 1,
            'bronze_count' => 1,
            'score_total' => 9,
            'score_7d' => 0,
            'score_30d' => 0,
            'last_medaled_at' => now(),
            'created_at' => now(),
            'updated_at' => now(),
        ],
        [
            'artwork_id' => $leader->id,
            'gold_count' => 3,
            'silver_count' => 0,
            'bronze_count' => 0,
            'score_total' => 15,
            'score_7d' => 0,
            'score_30d' => 0,
            'last_medaled_at' => now()->subDay(),
            'created_at' => now(),
            'updated_at' => now(),
        ],
    ]);

    $results = app(HomepageService::class)->getHallOfFame(8);

    expect($results)->toHaveCount(2)
        ->and($results[0]['id'])->toBe($leader->id)
        ->and($results[1]['id'])->toBe($runnerUp->id);
});