<?php

namespace App\Jobs;

use App\Filter;
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\MercuryDataModels\KeyloopLeaseVehicleVariant;
use Mtc\MercuryDataModels\Vehicle;

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()
    {
        $vehicle_type_filters = [
            'filters' => Vehicle::class,
            'lease_vehicle_filters' => KeyloopLeaseVehicleVariant::class,
        ];

        foreach ($vehicle_type_filters as $filter_group => $target_model) {
            $filter_class = app(Filter::class);
            $filter_class->setFilterTargetModel($target_model);
            $filter_class->setConfigKey($filter_group);
            $filter_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
    {
        $filter_index_class = config('filter.filter_index_model');
        $this->getValuesToIndex($filter, $type)
            ->each(fn ($model) => $filter_index_class::index($type, $model, $filter));
    }

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

        $filter_index_class = config('filter.filter_index_model');
        $existing = $filter_index_class::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)]));
    }
}
