<?php

namespace Daylight\Core\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;

/**
 * Job to re-index products in the search engine.
 *
 * This job batches product re-indexing to improve performance
 * and avoid overwhelming the search engine.
 */
class ReindexProductsJob implements ShouldBeUnique, ShouldQueue
{
    use Dispatchable;
    use InteractsWithQueue;
    use Queueable;
    use SerializesModels;

    /**
     * The number of times the job may be attempted.
     */
    public int $tries = 3;

    /**
     * The number of seconds to wait before retrying the job.
     */
    public int $backoff = 10;

    /**
     * Create a new job instance.
     *
     * @param  array<int>  $productIds
     */
    public function __construct(
        public array $productIds
    ) {}

    /**
     * Execute the job.
     */
    public function handle(): void
    {
        if (empty($this->productIds)) {
            return;
        }

        $productModel = daylightModel('product');

        // Chunk the IDs to avoid memory issues with large batches
        $chunks = array_chunk($this->productIds, 100);

        foreach ($chunks as $chunk) {
            $products = $productModel::query()
                ->whereIn('id', $chunk)
                ->with([
                    'translations',
                    'variants',
                    'brand',
                    'categories.translations',
                    'categories.ancestorsAndSelf.translations',
                    'attributeValues.attribute.translations',
                ])
                ->get();

            // Use Scout's searchable method to update the index
            $products->searchable();
        }

        Log::debug('ReindexProductsJob: Re-indexed '.count($this->productIds).' products');
    }

    /**
     * Get the unique ID for the job.
     *
     * This helps prevent duplicate jobs for the same products.
     */
    public function uniqueId(): string
    {
        sort($this->productIds);

        return 'reindex-products-'.md5(implode(',', $this->productIds));
    }

    /**
     * The number of seconds after which the job's unique lock will be released.
     */
    public int $uniqueFor = 60;
}
