<?php

namespace App\Models\Shop;

use App\Repositories\Shop\SaleChannels;
use Cesargb\Database\Support\CascadeDelete;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Eloquent\Relations\MorphToMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Kalnoy\Nestedset\NestedSet;
use Rinvex\Categories\Models\Category as parentCategory;
use Rinvex\Tags\Traits\Taggable;
use Wildside\Userstamps\Userstamps;

class Category extends parentCategory
{
    use CascadeDelete, SoftDeletes, Taggable, Userstamps;

    public $translatable = [];

    protected $guarded = ['id'];

    protected $table = 'categories';

    protected $cascadeDeleteMorph = ['Articles'];

    protected $fillable = [
        'visible',
        'homepage',
        'slug',
        'name',
        'description',
        NestedSet::LFT,
        NestedSet::RGT,
        NestedSet::PARENT_ID,
    ];

    public function Articles(): MorphToMany
    {
        return $this->morphedByMany(Article::class, 'categorizable');
    }

    public function ArticlesTagged()
    {
        return $this->tags->articles;
    }

    public function Parent(): HasOne
    {
        return $this->hasOne(Category::class, 'id', 'parent_id');
    }

    public function categorizables(): HasMany
    {
        return $this->hasMany(Categorizable::class);
    }

    public function countArticlesTagged()
    {
        return $this->tags()->withCount('Articles');
    }

    public function scopeByCategory($query, $categoryId)
    {
        return $query->where('category_id', $categoryId);
    }

    public function scopeVisible($query)
    {
        return $query->where('visible', 1);
    }

    public function scopeHomepage($query)
    {
        return $query->where('homepage', 1);
    }

    public function scopeNotRoot($query)
    {
        return $query->where('id', '<>', 1);
    }

    public function scopeInRange($query, $left, $right)
    {
        return $query->where('_lft', '>=', $left)->where('_rgt', '<=', $right);
    }

    public function scopeHasAvailableOffers($query, $saleChannelId = false)
    {
        $saleChannelId = $saleChannelId ? $saleChannelId : SaleChannels::getDefaultID();

        return $query->whereHas('articles', function ($query) use ($saleChannelId) {
            $query->WithAvailableOffers($saleChannelId);
        });
    }

    public function scopeHasAvailableOffersByCategoryParent($query, $saleChannelId = false)
    {
        $saleChannelId = $saleChannelId ? $saleChannelId : SaleChannels::getDefaultID();

        return $query->whereHas('articles', function ($query) use ($saleChannelId) {
            $query->WithAvailableOffers($saleChannelId);
        })->orWhereHas('descendants.articles', function ($query) use ($saleChannelId) {
            $query->WithAvailableOffers($saleChannelId);
        });
    }
}
