<?php

namespace App\Filter;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Mtc\Filter\Contracts\FilterIndexContract;
use Mtc\Filter\Contracts\IsFilter;
use Mtc\MercuryDataModels\BodyStyleType;

class FilterIndex extends FilterIndexContract
{
    /**
     * Index a model
     *
     * @param string $filter_type
     * @param Model $model
     * @param IsFilter $filter
     * @throws \RuntimeException
     */
    #[\Override]
    public static function index(string $filter_type, Model $model, IsFilter $filter): void
    {
        if ($model instanceof BodyStyleType && $model->has_subcategories) {
            self::indexWithSubTypes($filter_type, $model, $filter);
            return;
        }

        $type = $filter_type;
        $id = $model->getAttribute($filter->getIdAttribute(true));
        $name = $model->getAttribute($filter->getNameAttribute(true));
        $slug = self::resolveSlug($model, $filter);

        if (empty($id)) {
            return;
        }

        if (empty($slug) && $slug !== '0') {
            return;
        }

        try {
            if (!in_array($type, ['model', 'make', 'vehicle_type']) && self::checkExisting($type, $id, $slug)) {
                $slug = self::uniqueSlug($type, $id, $slug);
            }

            self::query()
                ->updateOrCreate([
                    'filter_type' => $type,
                    'filter_id' => $id,
                ], [
                    'slug' => $slug,
                    'name' => $name
                ]);
        } catch (\RuntimeException $exception) {
            Log::error(tenant('id') . $exception->getMessage(), [
                'type' => $type,
                'model' => $model->id,
                'name' => $name,
            ]);
        }
    }

    private static function resolveSlug(Model $model, IsFilter $filter): string
    {
        if ($filter->getIdAttribute(true) === $model->getKeyName()) {
            $existing = $model->getAttribute('slug');
            if (is_string($existing) && trim($existing) !== '') {
                return trim($existing);
            }
        }

        return trim(Str::slug($filter->modelSlug($model)));
    }
    private static function indexWithSubTypes(string $filter_type, BodyStyleType $model, IsFilter $filter)
    {

        $type = $filter_type;
        $id = $model->getAttribute($filter->getIdAttribute(true));
        $name = $model->getAttribute($filter->getNameAttribute(true));
        $slug_small = Str::slug('small-' . $filter->modelSlug($model));
        $slug_medium = Str::slug('medium-' . $filter->modelSlug($model));
        $slug_large = Str::slug('large-' . $filter->modelSlug($model));

        if ($id === null || empty(trim($id))) {
            return;
        }

        self::query()
            ->updateOrCreate([
                'filter_type' => $type,
                'filter_id' => $id,
                'slug' => $slug_small,
            ], [
                'name' => 'Small ' . $name
            ]);

        self::query()
            ->updateOrCreate([
                'filter_type' => $type,
                'filter_id' => $id,
                'slug' => $slug_medium,
            ], [
                'name' => 'Medium ' . $name
            ]);

        self::query()
            ->updateOrCreate([
                'filter_type' => $type,
                'filter_id' => $id,
                'slug' => $slug_large,
            ], [
                'name' => 'Large ' . $name
            ]);
    }

    /**
     * Check if slug is not already used
     *
     * @param string $type
     * @param $id
     * @param string $slug
     * @return bool
     */
    #[\Override]
    protected static function checkExisting(string $type, $id, string $slug): bool
    {
        $safe_id = DB::getPdo()->quote($id);
        $safe_type = DB::getPdo()->quote($type);
        return self::query()
            ->where('filter_type', $type)
            ->where('slug', $slug)
            ->whereRaw(DB::raw("NOT ( `filter_id` = $safe_id and `filter_type` = $safe_type)"))
            ->exists();
    }
}
