<?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\Facades\App;
use Illuminate\Support\Facades\Log;
use Mtc\Filter\Contracts\CustomPatternFilter;
use Mtc\Filter\Contracts\IsFilter;
use Mtc\MercuryDataModels\KeyloopLeaseVehicleVariant;
use Mtc\MercuryDataModels\Vehicle;
use Throwable;

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

    public function __construct()
    {
        $this->onQueue('sync');
    }

    public function handle(): void
    {
        $vehicle_type_filters = [
            'filters' => Vehicle::class,
            'lease_vehicle_filters' => KeyloopLeaseVehicleVariant::class,
        ];

        $filter_index_class = config('filter.filter_index_model');

        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(IsFilter $filter) => $filter instanceof CustomPatternFilter || !$filter->reindexModel())
                ->each(fn(IsFilter $filter, $type) => $this->reindexFilter($filter, $type, $filter_index_class));
        }
    }

    private function reindexFilter(IsFilter $filter, string $type, string $filter_index_class): void
    {
        App::make($filter->getModel())->newQuery()
            ->chunk(250, function ($chunk) use ($type, $filter, $filter_index_class) {
                $chunk->each(fn($model) => $filter_index_class::index($type, $model, $filter));
            });
    }

    public function failed(?Throwable $exception): void
    {
        Log::error('RefreshFilterIndexJob failed', [
            'exception_class' => $exception ? get_class($exception) : 'null (worker death or reservation race)',
            'message' => $exception?->getMessage(),
            'file' => $exception?->getFile(),
            'line' => $exception?->getLine(),
        ]);
    }
}
