<?php

namespace App\Models\Shop;

use App\Models\Botanic\Specie;
use App\Models\Botanic\Variety;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphToMany;
use Illuminate\Support\Facades\DB;
use Rinvex\Tags\Models\Tag as parentTag;

class Tag extends parentTag
{
    public $translatable = [];

    protected $guarded = ['id'];

    protected $fillable = [
        'slug',
        'name',
        'description',
        'sort_order',
        'group',
        'tag_group_id',
    ];

    // TODO
    public function offers(): MorphToMany
    {
        return $this->articles();
    }

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

    public function categories(): MorphToMany
    {
        return $this->morphedByMany(Category::class, 'taggable');
    }

    public function tag_group(): BelongsTo
    {
        return $this->belongsTo(TagGroup::class);
    }

    public function shelves(): MorphToMany
    {
        return $this->morphedByMany(Shelve::class, 'taggable');
    }

    public function species(): MorphToMany
    {
        return $this->morphedByMany(Specie::class, 'taggable');
    }

    public function varieties(): MorphToMany
    {
        return $this->morphedByMany(Variety::class, 'taggable');
    }

    public function merchandises(): MorphToMany
    {
        return $this->morphedByMany(Merchandise::class, 'taggable');
    }

    public function scopeByGroup($query, $id)
    {
        return $query->where($this->table.'.tag_group_id', $id);
    }

    public function scopeWithCountDirectArticlesByCategory($query, $categoryId)
    {
        return $query->withCount([
            'articles as direct_article_count' => function ($query) use ($categoryId) {
                $query->byCategoryParent($categoryId)->withAvailableOffers();
            },
        ])->having('direct_article_count', '>', 0);
    }

    public function scopeWithCountIndirectArticlesByCategory($query, $categoryId)
    {
        return $query->select(['tags.*'])
            ->selectRaw('(SELECT COUNT(*) 
                      FROM shop_articles 
                      WHERE EXISTS (
                          SELECT 1 
                          FROM botanic_varieties 
                          INNER JOIN taggables 
                          ON taggables.taggable_id = botanic_varieties.id 
                          AND taggables.taggable_type = ? 
                          WHERE shop_articles.product_id = botanic_varieties.id 
                          AND shop_articles.product_type = ? 
                          AND taggables.tag_id = tags.id
                      )
                      AND EXISTS (
                          SELECT 1 
                          FROM categories 
                          INNER JOIN categorizables 
                          ON categorizables.category_id = categories.id 
                          WHERE categorizables.categorizable_id = shop_articles.id 
                          AND categorizables.categorizable_type = ? 
                          AND categories._lft >= ? 
                          AND categories._rgt <= ?
                      )
                      AND shop_articles.id IN (
                        SELECT id FROM shop_articles WHERE EXISTS (
                            SELECT 1 FROM shop_offers 
                                WHERE shop_offers.article_id = shop_articles.id 
                                AND shop_offers.stock_current > 0
                            )
                        )
                  ) AS indirect_article_count', [
            Variety::class, // Type des variétés dans taggables
            Variety::class, // Type du produit dans articles
            Article::class, // Type de l'article dans categorizables
            optional(Category::find($categoryId))->_lft ?? 0, // Limite gauche
            optional(Category::find($categoryId))->_rgt ?? PHP_INT_MAX, // Limite droite
        ])
        ->having('indirect_article_count', '>', 0);
    }

    public function scopeById($query, $id)
    {
        return $query->where($this->table.'.id', $id);
    }

    public function scopeByIds($query, $ids)
    {
        return $query->whereIntegerInRaw($this->table.'.id', $ids);
    }
}
