<?php

namespace App\Filtros;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\Request;
use Illuminate\Database\Eloquent\Builder;

class Filtro extends Model
{
    protected $request;
    protected $builder;
    protected $MENSAJES_ERROR = [
    	'ARGUMENTO' => 'Argumento inválido para el parámetro %s. Revise la documentación.'
    ];

    public function __construct(Request $request)
    {
        $this->request = $request;
    }

    /**
     * Apply all existing filters, if available.
     *
     * @param  \Illuminate\Database\Eloquent\Builder  $builder
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function aplicar(Builder $builder)
    {
        $this->builder = $builder;

        //Aplicar filtros que aparecen en los parámetros, si los hay
        $filtros = $this->request->all();

        //el filtro nombre debe tomar precedencia sobre otros como (alfabetico)
        if (isset($filtros["nombre"])) {
            $nombre = $filtros["nombre"];
            unset($filtros["nombre"]);
            $filtros = array_merge(["nombre" => $nombre],$filtros);
        }

        foreach($filtros as $filtro => $valor) {
            //Obtener nombre del método  (snake_case a camelCase)
            $metodo = str_replace('_', '', lcfirst(ucwords($filtro, '_')));

            if(!method_exists($this, $metodo)) { continue; }

            //Llamar métodos sin argumentos
            if ($valor === null|| (is_a($valor,'String') && trim($valor)=='')){ $this->$metodo(); continue; }
            
            //Llamar métodos con argumentos
            try {
                $this->$metodo($valor);
            } catch (\Throwable $th) {
                if (is_a($th,'TypeError') ) { throw new HttpException(400, sprintf($this->MENSAJES_ERROR['ARGUMENTO'],$filtro)); }
                throw $th;
            }

        }
        return $this->builder;
    }

    //Buscar un término en el nombre
    public function nombre(String $valor)
    {
        $this->builder->where('nombre', "LIKE", "%" . $valor . "%")->orderByRaw("IF(nombre = '{$valor}',2,IF(nombre LIKE '{$valor}%',1,0)) DESC");
    }

    public function alfabetico(String $order = 'asc')
    {
        if(!in_array($order,['asc','desc'])) { throw new TypeError(); }
        $this->builder->orderBy('nombre', $order);
    }
}