<?php

namespace Lightscale\LaralightTables;

use Livewire\Component;
use Livewire\WithPagination;
use Livewire\Attributes\Url;

use Illuminate\Pagination\Paginator;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Str;
use Illuminate\Support\Collection;

use Exception;

abstract class TableComponent extends Component
{
    use WithPagination;

    // Config
    protected $paginationTheme = 'bootstrap';
    protected $model = null;
    protected int $defaultPageSize = 10;

    // Properties
    #[Url]
    public string $search = '';

    #[Url]
    public int $pageSize;
    public array $activeColumns = [];

    public function mount()
    {
        $this->setDefaultActiveColumns();
        $this->setDefaultPageSize();
    }

    protected function setDefaultPageSize(): void
    {
        if (!isset($this->pageSize)) {
            $this->pageSize = $this->defaultPageSize;
        }
    }

    protected function setDefaultActiveColumns(): void
    {
        foreach($this->getColumns() as $column) {
            $this->activeColumns[] = $column->name;
        }
    }

    protected function isSearching(): bool
    {
        $search = $this->getToolbar()->getSearch();
        return $search !== null && Str::length($this->search) >= $search->getMinLength();
    }

    public function updatedSearch(): void
    {
        if ($this->isSearching()) {
            $this->resetPage();
        }
    }

    protected function toolbar(): ?Toolbar
    {
        return null;
    }

    private ?Toolbar $toolbarCache;

    protected function getToolbar(): ?Toolbar
    {
        if (!isset($this->_toolbar)) {
            $this->toolbar = $this->toolbar();
        }
        return $this->toolbar;
    }

    protected function query() : Builder
    {
        if($this->model === null) {
            throw new Exception('Requires $model to be set or query() method to be overridden');
        }

        return $this->model::query();
    }

    abstract protected function columns() : array;

    protected function search(Builder $builder, string $search) : void {}

    protected function buildQuery() : Builder
    {
        $query = $this->query();

        if ($this->isSearching()) {
            $this->search($query, $this->search);
        }

        return $query;
    }

    private ?Collection $columnsCache = null;
    public function getColumns()
    {
        if($this->columnsCache === null) {
            $this->columnsCache = collect($this->columns())->each(
                fn($c) => $c->setTable($this)
            );
        }

        return $this->columnsCache;
    }

    public function render()
    {
        $data = $this->buildQuery()->paginate($this->pageSize);
        $allColumns = $this->getColumns();
        $columns = $allColumns->filter(fn($c) => in_array($c->name,$this->activeColumns));
        $toolbar = $this->toolbar();

        Paginator::defaultView('laralight-tables::pagination');

        return view('laralight-tables::table', compact(
            'data', 'allColumns', 'columns', 'toolbar',
        ));
    }
}