<?php


namespace App\Filters;


use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;

class LogFilters
{
    protected $request;
    protected $queryBuilder;
    protected $filters = ['username', 'type', 'description',
        'created_at_start', 'created_at_end', 'is_exception', 'class', 'method'];
    protected $array_filter;

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

    public function apply($builder)
    {
        $this->queryBuilder = $builder;
        foreach ($this->array_filter as $filter => $value) {
            if (method_exists($this, $filter)) {
                $this->$filter($value, $this->queryBuilder);
            }
        }
        return $this->afterApply($this->queryBuilder);
    }

    /**
     * 后置处理，解决查询条件之间的关联关系，方法名后缀’_after‘
     * @param $builder
     * @return mixed
     */
    public function afterApply($builder)
    {
        $this->queryBuilder = $builder;
        foreach ($this->array_filter as $filter => $value) {
            $filter .= '_after';
            if (method_exists($this, $filter)) {
                $this->$filter($value, $this->queryBuilder);
            }
        }
        if (!Arr::hasAny($this->array_filter, ['created_at_start', 'created_at_end'])) {
            $start = Carbon::now()->toDateString();
            $end = Carbon::tomorrow()->toDateString();
            $this->queryBuilder = $this->queryBuilder->where('created_at', '>=', $start)->where('created_at', '<', $end);
        }
        return $this->queryBuilder;
    }

    private function created_at_start($created_at_start)
    {
        $this->queryBuilder->where('created_at', '>=', $created_at_start);
    }

    private function created_at_end($created_at_end)
    {
        $this->queryBuilder->where('created_at', '<', Carbon::parse($created_at_end)->addDay()->toDateString());
    }

    /**
     * 如果中传入开始时间，默认结束时间为开始时间的下一天
     * @param $created_at_start
     */
    private function created_at_start_after($created_at_start)
    {
        if (!Arr::has($this->array_filter, 'created_at_end')) {
            $endDay = Carbon::parse($created_at_start)->addDay()->toDateString();
            $this->queryBuilder->where('created_at', '<', $endDay);
        }
    }

    /**
     * 如果只传入截止时间，只查询截止时间这一天的数据
     * @param $created_at_end
     */
    private function created_at_end_after($created_at_end)
    {
        if (!Arr::has($this->array_filter, 'created_at_start')) {
            $startDay = Carbon::parse($created_at_end)->toDateString();
            $this->queryBuilder->where('created_at', '>=', $startDay);
        }
    }

    private function description($description)
    {
        $this->queryBuilder->where("description", 'like', $description . '%');
    }

    private function class($class)
    {
        $class = str_replace('\\', '\\\\', $class);
        $this->queryBuilder->where("class", 'like', $class . '%');
    }

    private function method($method)
    {
        $this->queryBuilder->where("method", 'like', $method . '%');
    }

    private function type($type)
    {
        $types = array_filter(preg_split('/[,， ]+/is', $type));
        $this->queryBuilder->whereIn("type", $types);
    }

    private function username($username)
    {
        $this->queryBuilder->whereIn("id_user", function ($query) use ($username) {
            return $query->from("users")->select("id")->where("name", 'like', $username . '%');
        });
    }

    private function is_exception()
    {
        $this->queryBuilder->where(function ($query) {
            $query->where("method", "like", "ERROR%")->orWhere("method", "like", "EXCEPTION%");
        });
    }
}
