<?php

namespace App\Console\Commands;

use App\Facades\Feature;
use App\Facades\Settings;
use Illuminate\Console\Command;
use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Support\Facades\App;
use Mtc\MercuryDataModels\BodyStyleType;
use Mtc\MercuryDataModels\DrivetrainType;
use Mtc\MercuryDataModels\Filters\IndexedFilter;
use Mtc\MercuryDataModels\FuelType;
use Mtc\MercuryDataModels\SearchIndex;
use Mtc\MercuryDataModels\TransmissionType;
use Mtc\MercuryDataModels\VehicleMake;
use Mtc\MercuryDataModels\VehicleModel;

class UpdateFilterSearchIndex extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'filter:update-search-index';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Update search index table ';

    /**
     * Execute the console command.
     */
    public function handle()
    {
        if (!Feature::isEnabled('indexed-search-page')) {
            return self::SUCCESS;
        }

        Relation::morphMap([
            'make' => VehicleMake::class,
            'model' => VehicleModel::class,
            'fuel_type' => FuelType::class,
            'transmission' => TransmissionType::class,
            'body_type' => BodyStyleType::class,
            'drivetrain' => DrivetrainType::class,
        ]);

        collect(config('filter.filters'))
            ->map(fn($filter_class) => App::make($filter_class))
            ->filter(fn($filter) => $filter instanceof IndexedFilter)
            ->filter(fn($filter, $name) => Settings::get("automotive-vehicle-filters-$name") === true)
            ->each(fn($filter, $name) => $this->updateIndex($filter, $name));

        return self::SUCCESS;
    }

    private function updateIndex(IndexedFilter $filter, $name): void
    {
        SearchIndex::query()->where('filter_type', $filter->filterType())->delete();

        if ($name === 'model') {
            $this->updateForModel($filter, $name);
            return;
        }
        $data = $filter->format($filter->getResults(fn($query) => $query, 1000));

        collect($data['results'])
            ->filter(fn ($model) => !empty($model['slug']) || !empty($model['id']))
            ->each(fn($model) => SearchIndex::query()->updateOrCreate(
                [
                    'filter_type' => $filter->filterType(),
                    'filter_id' => $model['slug'] ?? $model['id'],
                ],
                [
                    'name' => $model['name'],
                    'slug' => $model['slug'] ?? $model['id'],
                ],
            ));
    }

    private function updateForModel(IndexedFilter $filter, string $name): void
    {
        collect($filter->getResults(fn($query) => $query, 1000))
            ->each(fn($model) => SearchIndex::query()->updateOrCreate(
                [
                    'filter_type' => $filter->filterType(),
                    'filter_id' => $model->slug ?: $model[$filter->getIdAttribute()],
                    'selection_hash' => $model->make?->filterIndex?->slug,
                ],
                [
                    'name' => $model[$filter->getNameAttribute()],
                    'slug' => $model->slug,
                    'selection_hash' => $model->make?->filterIndex?->slug,
                ],
            ));
    }
}
