<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphOne;
use Illuminate\Support\Facades\Storage;
use Staudenmeir\LaravelAdjacencyList\Eloquent\HasRecursiveRelationships;

class Category extends Model
{
    use HasFactory, HasRecursiveRelationships;

    protected $fillable = [
        'name',
        'parent_category_id',
        'image',
        'slug',
        'status',
        'description',
        'is_job_category',
        'price_optional',
    ];

    public function getParentKeyName()
    {
        return 'parent_category_id';
    }

    protected $appends = ['translated_name', 'translated_description'];

    protected $with = ['translations'];

    public function subcategories()
    {
        return $this->hasMany(self::class, 'parent_category_id');
    }

    public function custom_fields()
    {
        return $this->hasMany(CustomFieldCategory::class);
    }

    public function getImageAttribute($image)
    {
        if (! empty($image)) {
            return url(Storage::url($image));
        }

        return $image;
    }

    public function items()
    {
        return $this->hasMany(Item::class);
    }

    public function approved_items()
    {
        return $this->hasMany(Item::class)->where('status', 'approved');
    }

    public function getAllItemsCountAttribute()
    {
        // Count items in this category
        $totalItems = $this->items()->where('status', 'approved')->getNonExpiredItems()->count();

        // Count items from ALL descendants (not just loaded ones) using recursive query
        $descendantIds = $this->descendants()
            ->where('status', 1)
            ->pluck('id')
            ->toArray();

        if (! empty($descendantIds)) {
            $descendantItemsCount = Item::without('translations')
                ->whereIn('category_id', $descendantIds)
                ->where('status', 'approved')
                ->getNonExpiredItems()
                ->count();

            $totalItems += $descendantItemsCount;
        }

        return $totalItems;
    }

    public function scopeSearch($query, $search)
    {
        $search = '%'.$search.'%';

        return $query->where(function ($q) use ($search) {
            $q->orWhere('name', 'LIKE', $search)
                ->orWhere('description', 'LIKE', $search)
                ->orWhereHas('translations', function ($q) use ($search) {
                    $q->where('description', 'LIKE', $search);
                });
        });
    }

    public function slider(): MorphOne
    {
        return $this->morphOne(Slider::class, 'model');
    }

    public function translations()
    {
        return $this->hasMany(CategoryTranslation::class);
    }

    public function getTranslatedNameAttribute()
    {
        $languageCode = request()->header('Content-Language') ?? app()->getLocale();
        if (! empty($languageCode)) {
            // NOTE : This code can be done in Cache
            $language = Language::select(['id', 'code'])->where('code', $languageCode)->first();

            if (empty($language)) {
                return $this->name;
            }

            $languageId = $language->id;
            $translation = $this->translations->first(static function ($data) use ($languageId) {
                return $data->language_id == $languageId;
            });

            return ! empty($translation?->name) ? $translation->name : $this->name;
        }

        return $this->name;
    }

    public function getTranslatedDescriptionAttribute()
    {
        $languageCode = request()->header('Content-Language') ?? app()->getLocale();
        if (! empty($languageCode)) {
            // NOTE : This code can be done in Cache
            $language = Language::select(['id', 'code'])->where('code', $languageCode)->first();

            if (empty($language)) {
                return $this->description;
            }

            $languageId = $language->id;
            $translation = $this->translations->first(static function ($data) use ($languageId) {
                return $data->language_id == $languageId;
            });

            return ! empty($translation?->description) ? $translation->description : $this->description;
        }

        return $this->description;
    }

    public function parent()
    {
        return $this->belongsTo(Category::class, 'parent_category_id');
    }

    public function getFullPathAttribute()
    {
        $names = [];
        $current = $this;
        $visited = [];

        while ($current) {
            if (in_array($current->id, $visited, true)) {
                break; // prevent loop
            }
            $visited[] = $current->id;

            $names[] = $current->name;
            $current = $current->parent;
        }

        return implode(' > ', array_reverse($names));
    }

    public function getItemsGroupedByStatusAttribute()
    {
        $counts = [];

        // Count items in this category
        $items = $this->items()->get();
        foreach ($items as $item) {
            $counts[$item->status] = ($counts[$item->status] ?? 0) + 1;
        }

        // Include subcategories recursively
        foreach ($this->subcategories as $subcategory) {
            $subCounts = $subcategory->items_grouped_by_status;
            foreach ($subCounts as $status => $count) {
                $counts[$status] = ($counts[$status] ?? 0) + $count;
            }
        }

        return $counts;
    }

    public function getOtherItemsCountAttribute()
    {
        $totalItems = $this->items()->where('status', '!=', 'approved')->count();
        foreach ($this->subcategories as $subcategory) {
            $totalItems += $subcategory->other_items_count;
        }

        return $totalItems;
    }
}
