<?php


namespace App\Repositories;



use App\Models\File;
use App\Services\Pagination\Paginator;
use App\Support\Entity;
use App\Support\Query;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Query\Builder;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Log;

abstract class Repository
{
    protected $as;

    protected $for;

    /**
     * @throws \Exception
     */
    public function __call($method, $parameters)
    {
        return $this->query($this->as)->$method(...$parameters);
    }

    public function for($value = null)
    {
        $this->for = $value ? array_wrap($value) : null;

        return $this;
    }

    public function getFor()
    {
        return $this->for;
    }

    /**
     * @param null $name
     * @param null $table
     * @return \Illuminate\Database\Connection|\Illuminate\Database\Query\Builder
     */
    public function connection($name = null, $table = null)
    {
        $query = $this->db()->connection($name);

        return is_null($table) ? $query : $query->table($table);
    }

    /**
     * @param null $table
     * @param null $name
     * @return \Illuminate\Database\Connection|\Illuminate\Database\Query\Builder
     */
    public function on($table = null, $name = null)
    {
        return $this->connection($name, $table);
    }

    protected function resolve($query, $arguments, $callback = null)
    {
        if ($callback && is_callable($callback)) {
            $callback($query, $arguments);
        }

        return $query;
    }

    public function paginate($items, $query)
    {
        return Paginator::make($items, $query->get('paging', 20));
    }

    public function paginator(...$parameters)
    {
        return new Paginator(...$parameters);
    }

    /**
     * @param Builder $query
     * @param Entity $arguments
     * @return Builder
     */
    public function scopePaginate($query, $arguments): Builder
    {
        $perPage = $arguments->get('paging', 20);

        return $query->skip(($arguments->get('page', 1) - 1) * $perPage)
            ->take($perPage);
    }

    /**
     * @param Builder $query
     * @param Entity $arguments
     * @param string $column
     * @return Builder
     */
    public function scopeWithin($query, $arguments, $column = 'id'): Builder
    {
        if (!is_null($only = $arguments->only)) {
            $query->whereIn($column, is_array($only) ? $only : [$only]);
        }

        if (!is_null($except = $arguments->except)) {
            $query->whereNotIn($column, is_array($except) ? $except : [$except]);
        }

        return $query;
    }

    /**
     * @param Builder|\Laravel\Scout\Builder|\Illuminate\Database\Eloquent\Model $query
     * @param string $column
     * @return Builder|\Illuminate\Database\Eloquent\Builder
     */
    public function scopeFor($query, string $column = 'event_id')
    {
        if ($this->for) {
            $query->whereIn($column, array_wrap($this->for));
        }

        return $query;
    }

    /**
     * @return Model|null
     */
    abstract function model(): ?Model;

    /**
     * @return \Illuminate\Database\DatabaseManager|\Illuminate\Foundation\Application|mixed
     */
    public function db()
    {
        return app('db');
    }

    /**
     * @param null $as
     * @throws \Exception
     */
    public function query($as = null)
    {
        $model = $this->model();

        if (!is_object($model)) {
            throw new \Exception('Invalid model');
        }

        $as = $as ?: $this->as;

        $from = $model->getTable() . ($as ? " as {$as}" : '');

        return $this->db()
            ->connection($model->getConnectionName())
            ->table($from);
    }


    /**
     * @param Request $request
     * @return Query
     */
    public function arguments(Request $request): Query
    {
        $query = entity($request->all())
            ->put([
                'page' => $request->input('page', 0) + 1,
                'paging' => $request->input('paging', 10)
            ]);
        return new Query($query->all(), $request->url());
    }

    /**
     * @param $fileId
     * @return bool
     */
    public function deleteFile($fileId): bool
    {
        $file = File::find($fileId);
        if (!$file)
            return false;

        $delete = Storage::delete($file->filepath . '/' . $file->save_name);
        $file->delete();

        return true;
    }

    /**
     * @param $fileId
     * @return array
     */
    public function getAllUsersByEmailType(string $emailType):array
    {
        $fields = json_decode(json_encode(config('schedule_mail_settings')), true);
        $result = [];
        foreach($fields[$emailType]['fields'] as $field){
            if($field['field_id'] == "users"){
                $result = $field['options'];
            }
        }
        return $result;
    }
}
