<?php

namespace App\Services\Filters;

use App\Services\Filters\Companies\CompanyFiltersServices;
use App\Services\Filters\Registries\RegistryFiltersServices;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Date;

class FiltersService {
    public static array $services = [
        RegistryFiltersServices::class,
        CompanyFiltersServices::class
    ];


    public function __construct() {

    }

    public static function getService($type) {
        foreach (self::$services as $service) {
            $services = $service::$services;
            if (($class = $services[$type] ?? null) && class_exists($class)) return new $class();
        }
        return null;
    }



    public function applyOrder($query, Collection $order) {
        $by = $order->get('by', 'dates');
        $dir = $order->get('dir', 'desc');
        if ($by === 'dates') $query->orderBy('created_at', $dir);
        elseif ($by === 'names') $query->orderBy('name', $dir);
    }



    public function applySearchFilter($query, $string, $props = [], $has = []) {
        $this->stringToWords($string)->each(function($word) use($query, $props, $has) {
            $query->where(function($query) use($word, $props, $has) {
                collect($props)->each(function($prop, $index) use($query, $word) {
                    if (is_array($prop)) $this->applyRelationalSearchFilter($query, $prop, $word);
                    else $index ? $query->orWhere($prop, 'like', $word) : $query->where($prop, 'like', $word);
                });
            });
        });
    }
    public function applyRelationalSearchFilter($query, $data, $word) {
        collect($data)->each(function($props, $relation) use($query, $word) {
            $query->orWhereHas($relation, function($query) use($props, $word) {
                collect($props)->each(function($prop, $index) use($query, $word) {
                    $index ? $query->orWhere($prop, 'like', $word) : $query->where($prop, 'like', $word);
                });
            });
        });
    }
    public function stringToWords($string): Collection {
        return collect(explode(' ', $string))->map(function($word) {
            return '%' . trim($word) . '%';
        });
    }

    public function applyDateFilter($query, $prop, $value) {
        if ($v = $value['gt'] ?? null) $query->where($prop, '>=', Date::create($v));
        if ($v = $value['lt'] ?? null) $query->where($prop, '<=', Date::create($v));
    }
    public function applyRelationFilter(Builder $query, $relation, $value) {
        $query->whereHas($relation, function($query) use($value) {
            $query->whereIn('uuid', is_array($value) ? $value : [$value]);
        });
    }


    public function getRelationItems(array $items): array {
        return ['data' => collect($items)->map(function($title, $id) {
            return ['id' => $id, 'title' => $title];
        })->values()];
    }

    public function getRelationValue($value, $items): array {
        return collect($value)->filter(function($value) {return $value;})->map(function($value) use($items) {
            return ['id' => $value, 'title' => $items[$value] ?? null];
        })->values()->all();
    }

}
