<?php

namespace App\Jobs;

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\Collection;
use Mtc\Filter\Contracts\CustomPatternFilter;
use Mtc\Filter\Contracts\FilterInstance;
use Mtc\Filter\Contracts\IsFilter;
use Mtc\Filter\FilterIndex;

class RefreshFilterIndexJob implements ShouldQueue
{
    use Dispatchable;
    use InteractsWithQueue;
    use Queueable;
    use SerializesModels;

    /**
     * Create a new job instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->onQueue('sync');
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        app(FilterInstance::class)->getFilters()
            ->reject(fn($filter) => $filter instanceof CustomPatternFilter)
            ->each(fn(IsFilter $filter, $type) => $this->reindexFilter($filter, $type));
    }

    private function reindexFilter(IsFilter $filter, string $type): void
    {
        $this->getValuesToIndex($filter, $type)
            ->each(fn ($model) => FilterIndex::index($type, $model, $filter));
    }

    private function getValuesToIndex(IsFilter $filter, string $type): Collection
    {
        $results = $filter->getResults(fn($query) => $query, 0);

        $existing = FilterIndex::query()
            ->where('filter_type', $type)
            ->whereIn('filter_id', $results->map(fn($entry) => $entry[$filter->getIdAttribute(true)]))
            ->pluck('filter_id')
            ->unique()
            ->flip();

        return $results->reject(fn($entry) => $existing->has($entry[$filter->getIdAttribute(true)]));
    }
}
