<?php

declare(strict_types=1);

use App\Models\Artwork;
use App\Models\Collection;
use App\Models\User;
use App\Services\CollectionHealthService;
use App\Services\CollectionService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

uses(TestCase::class, RefreshDatabase::class);

it('flags public collections as stale when freshness falls to zero', function (): void {
    $user = User::factory()->create();
    $service = app(CollectionHealthService::class);
    $collection = Collection::factory()->make([
        'user_id' => $user->id,
        'title' => 'Stale Health Candidate',
        'slug' => 'stale-health-candidate',
        'mode' => Collection::MODE_SMART,
        'artworks_count' => 6,
        'visibility' => Collection::VISIBILITY_PUBLIC,
        'moderation_status' => Collection::MODERATION_ACTIVE,
        'lifecycle_state' => Collection::LIFECYCLE_PUBLISHED,
        'summary' => 'A focused summary for stale health coverage.',
        'description' => 'A longer description that gives the stale collection enough metadata depth for the health service.',
        'likes_count' => 45,
        'followers_count' => 20,
        'saves_count' => 24,
        'comments_count' => 6,
        'shares_count' => 4,
        'views_count' => 1000,
        'last_activity_at' => now()->subDays(60),
        'updated_at' => now()->subDays(60),
        'published_at' => now()->subDays(60),
        'workflow_state' => Collection::WORKFLOW_APPROVED,
    ]);

    $collection->cover_artwork_id = 999;

    $collection->setRelation('coverArtwork', Artwork::factory()->for($user)->make([
        'width' => 1400,
        'height' => 900,
        'published_at' => now()->subDays(61),
    ]));

    $flagsMethod = new ReflectionMethod(CollectionHealthService::class, 'flags');
    $flagsMethod->setAccessible(true);

    $flags = $flagsMethod->invoke($service, $collection, 80.0, 0.0, 80.0, 80.0);

    expect($flags)->toContain(Collection::HEALTH_STALE);
});

it('flags collections with fewer than six artworks as low content', function (): void {
    $user = User::factory()->create();
    $service = app(CollectionHealthService::class);
    $collection = seededHealthyCollection($user, 'Thin Collection Candidate', 5);

    $payload = $service->evaluate($collection->fresh(['coverArtwork']));

    expect($payload['health_flags_json'])->toContain(Collection::HEALTH_LOW_CONTENT);
});

it('flags broken items when too many attached artworks are not publicly visible', function (): void {
    $user = User::factory()->create();
    $service = app(CollectionHealthService::class);
    $collection = Collection::factory()->for($user)->create([
        'title' => 'Broken Items Candidate',
        'slug' => 'broken-items-candidate',
        'visibility' => Collection::VISIBILITY_PUBLIC,
        'moderation_status' => Collection::MODERATION_ACTIVE,
        'lifecycle_state' => Collection::LIFECYCLE_PUBLISHED,
        'summary' => 'A collection used to validate broken item detection.',
        'description' => 'A detailed curatorial description for broken item health coverage.',
        'likes_count' => 40,
        'followers_count' => 20,
        'saves_count' => 15,
        'views_count' => 900,
        'published_at' => now()->subDays(10),
        'updated_at' => now()->subDay(),
        'last_activity_at' => now()->subDay(),
    ]);

    $visible = Artwork::factory()->for($user)->create(['width' => 1280, 'height' => 720]);
    $private = Artwork::factory()->for($user)->private()->create();
    $unapproved = Artwork::factory()->for($user)->unapproved()->create();
    $unpublished = Artwork::factory()->for($user)->unpublished()->create();
    app(CollectionService::class)->attachArtworks($collection, $user, [$visible->id, $private->id, $unapproved->id, $unpublished->id]);

    $collection->forceFill([
        'cover_artwork_id' => $visible->id,
        'updated_at' => now()->subDay(),
        'last_activity_at' => now()->subDay(),
    ])->save();

    $payload = $service->evaluate($collection->fresh(['coverArtwork']));

    expect($payload['health_flags_json'])->toContain(Collection::HEALTH_BROKEN_ITEMS)
        ->and($payload['placement_eligibility'])->toBeFalse();
});

it('flags collections without an explicit cover as weak cover', function (): void {
    $user = User::factory()->create();
    $service = app(CollectionHealthService::class);
    $collection = seededHealthyCollection($user, 'Weak Cover Candidate');

    $collection->forceFill(['cover_artwork_id' => null])->save();

    $payload = $service->evaluate($collection->fresh(['coverArtwork']));

    expect($payload['health_flags_json'])->toContain(Collection::HEALTH_WEAK_COVER);
});

it('keeps strong active collections healthy and placement eligible', function (): void {
    $user = User::factory()->create();
    $service = app(CollectionHealthService::class);
    $collection = seededHealthyCollection($user, 'Healthy Cover Candidate');

    $payload = $service->evaluate($collection->fresh(['coverArtwork']));

    expect($payload['health_state'])->toBe(Collection::HEALTH_HEALTHY)
        ->and($payload['health_flags_json'])->toBe([])
        ->and($payload['placement_eligibility'])->toBeTrue();
});

function seededHealthyCollection(User $user, string $title, int $artworksCount = 6): Collection
{
    $collection = Collection::factory()->for($user)->create([
        'title' => $title,
        'slug' => str($title)->slug()->value(),
        'visibility' => Collection::VISIBILITY_PUBLIC,
        'moderation_status' => Collection::MODERATION_ACTIVE,
        'lifecycle_state' => Collection::LIFECYCLE_PUBLISHED,
        'summary' => 'A focused summary for health scoring coverage.',
        'description' => 'A longer description that provides enough metadata depth for health scoring and editorial readiness calculations.',
        'likes_count' => 45,
        'followers_count' => 18,
        'saves_count' => 24,
        'comments_count' => 8,
        'shares_count' => 5,
        'views_count' => 1400,
        'published_at' => now()->subDays(5),
        'updated_at' => now()->subDay(),
        'last_activity_at' => now()->subDay(),
        'workflow_state' => Collection::WORKFLOW_APPROVED,
    ]);

    $artworkIds = Artwork::factory()->count($artworksCount)->for($user)->create([
        'width' => 1400,
        'height' => 900,
    ])->pluck('id')->all();

    app(CollectionService::class)->attachArtworks($collection, $user, $artworkIds);

    $collection->forceFill([
        'cover_artwork_id' => $artworkIds[0] ?? null,
        'updated_at' => now()->subDay(),
        'last_activity_at' => now()->subDay(),
    ])->save();

    return $collection->fresh(['coverArtwork']);
}