<?php

declare(strict_types=1);

namespace App\Jobs;

use App\Models\Artwork;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
use Meilisearch\Client as MeilisearchClient;

/**
 * Queued job: index (or re-index) a single Artwork in Meilisearch.
 *
 * Writes directly to the Meilisearch HTTP API instead of going through
 * Scout's searchable() / MakeSearchable pipeline. This avoids the
 * after_commit double-dispatch problem and ensures the document lands
 * in the index within this job's execution, with no extra queue hop.
 */
class IndexArtworkJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public int $tries   = 3;
    public int $timeout = 60;

    public function __construct(public readonly int $artworkId) {}

    public function handle(MeilisearchClient $client): void
    {
        $artwork = Artwork::with([
            'user',
            'group',
            'tags',
            'categories.contentType',
            'stats',
            'awardStat',
        ])->find($this->artworkId);

        if (! $artwork) {
            return;
        }

        if (! $artwork->is_public || ! $artwork->is_approved || ! $artwork->published_at) {
            // Not eligible — remove from index if present.
            $client->index($artwork->searchableAs())->deleteDocument($this->artworkId);
            return;
        }

        $document = $artwork->toSearchableArray();
        $client->index($artwork->searchableAs())->addDocuments([$document]);
    }

    public function failed(\Throwable $e): void
    {
        Log::error('IndexArtworkJob failed', [
            'artwork_id' => $this->artworkId,
            'error'      => $e->getMessage(),
        ]);
    }
}
