<?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\Facades\App;
use Mtc\MercuryDataModels\Features\VehicleFeature;
use Mtc\MercuryDataModels\FilterFeature;
use Mtc\MercuryDataModels\Filters\FeatureFilter;
use Mtc\MercuryDataModels\VehicleStandardEquipment;

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

    /**
     * Create a new job instance.
     */
    public function __construct(private readonly ?FilterFeature $feature = null)
    {
        $this->onQueue('sync');
    }

    /**
     * Execute the job.
     */
    public function handle(): void
    {
        if ($this->feature) {
            $this->singleFeature($this->feature, true);
        } else {
            $this->allFeatures();
        }
    }

    public function allFeatures(): void
    {
        FilterFeature::all()
            ->each(fn(FilterFeature $feature) => $this->singleFeature($feature));
    }

    public function singleFeature(FilterFeature $feature, bool $reset = false): void
    {
        if (empty($feature->terms)) {
            // No terms defined, stop trying to assign
            return;
        }

        if ($reset) {
            // Reset all entries with this as terms might have changed
            VehicleStandardEquipment::query()
                ->where('feature_id', $feature->id)
                ->update(['feature_id' => null]);
        }

        $query = VehicleStandardEquipment::query()
            ->distinct()
            ->select(['description']);

        foreach ($feature->terms as $term) {
            $term = trim((string) $term);
            if ($feature->exact_match) {
                $query->orWhere('description', $term);
            } else {
                // ensure that we don't match e.g. 'leather' feature when equipment name includes 'leather-free'
                $query->orWhere(fn ($subquery) => $subquery->where('description', 'like', '%' . $term . '%')
                    ->where('description', 'not like', '%' . $term . '-free%'));
            }
        }

        $query->update(['feature_id' => $feature->id]);

        // reindex the feature
        config('filter.filter_index_model')::index('features', $feature, App::make(FeatureFilter::class));
    }
}
