<?php

namespace App\Livewire;

use App\Models\Category;
use App\Models\News;
use Livewire\Attributes\Url;
use Livewire\Component;
use Livewire\WithPagination;

class NewsDatabase extends Component
{
    use WithPagination;

    /**
     * News title search
     * @var string
     */
    #[Url(as: 's', except: '')]
    public string $search = '';

    /**
     * Categories IDs filter.
     * @var array
     */
    #[Url(except:[])]
    public array $categories = [];

    /**
     * Sort by field.
     * @var string
     */
    #[Url(as: 'sort',except: 'created_at')]
    public string $sortBy = 'created_at';

    /**
     * asc/desc
     * @var string
     */
    #[Url(as: 'dir',except: 'desc')]
    public string $sortDir = 'desc';

    /**
     * Translation of sort options key.
     */
    public const array SORT_OPTIONS = [
        'created_at' => 'Date added',
        'title' => 'Title'
    ];

    public const int PAGINATION = 30;

    public function updatedSearch(): void { $this->resetPage(); $this->dispatch('filters-updated'); }
    public function updatedCategories():     void { $this->resetPage(); $this->dispatch('filters-updated'); }
    public function updatedCategoriesMode(): void { $this->resetPage(); $this->dispatch('filters-updated'); }

    public function clearFilters(): void
    {
        $this->reset([
            'search', 'categories',
        ]);
        $this->resetPage();
    }

    public function setSort(string $field): void
    {
        if( $this->sortBy === $field ) {
            $this->sortDir = $this->sortDir === 'asc' ? 'desc' : 'asc';
        } else {
            $this->sortBy = $field;
            $this->sortDir = 'asc';
        }
        $this->resetPage();
        $this->dispatch('filters-updated');
    }

    private function buildQuery()
    {
        $query = News::query()->published();

        if( $this->search ){
            $query->where(function($q){
                $q->where('title', 'like', '%'.$this->search.'%');
            });
        }

        if( $this->categories ) {
            $query->whereIn('category_id', $this->categories);
        }

        return $query->orderBy($this->sortBy, $this->sortDir);
    }

    public function render()
    {
        return view('livewire.news-database', [
            'news' => $this->buildQuery()->paginate(self::PAGINATION),
            'allCategories' => Category::where(function ($query) {
                $query->whereJsonContains('restricted_to', "news")
                    ->orWhereNull('restricted_to');
            })->orderBy('name')->get()
        ]);
    }
}
