<?php

namespace App\Models;

use Cviebrock\EloquentSluggable\Sluggable;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Facades\Cache;
use Morilog\Jalali\Jalalian;

class Brand extends Model
{
    use HasFactory, Sluggable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array<int, string>
     */
    protected $fillable = [
        'user_id',
        'edited_by',

        'uuid',
        'title',
        'title_en',
        'website',
        'slug',
        'content',
        'banner',
        'logo',

        'seo_title',
        'seo_description',
        'seo_keywords',
        'seo_canonical',

        'view_count',
        'status',
    ];

    protected $casts = [
        'user_id' => 'integer',
        'edited_by' => 'integer',
        'view_count' => 'integer',
    ];

    /**
     * additional data
     */
    protected $appends = [
        'get_banner',
        'get_logo',
        'products_count',
        'get_seo_keywords',
        'get_categories',
        'get_formatted_view_count',
        'jalali_created_at',
        'jalali_updated_at',

        'simple_safe',
        'safe',
    ];

    public function getGetLogoAttribute()
    {
        $logo = asset('img/temp/pre-load-brand.png');
        if ($this->logo != null) {
            $file = Cache::remember('files_' . $this->logo, now()->addMonth(), function () {
                return File::find($this->logo);
            });
            if ($file != null && $file->type == "image") {
                $logo = asset($file->url);
            }
        }
        return $logo;
    }

    public function getGetBannerAttribute()
    {
        $banner = null;
        if ($this->banner != null) {
            $file = Cache::remember('files_' . $this->banner, now()->addMonth(), function () {
                return File::find($this->banner);
            });
            if ($file != null && $file->type == "image") {
                $banner = asset($file->url);
            }
        }
        return $banner;
    }

    public function getProductsCountAttribute()
    {
        return $this->products()->where('status', 'publish')->count();
    }

    public function getGetSeoKeywordsAttribute()
    {
        $seo_keywords = [];
        foreach (($this->seo_keywords != null ? json_decode($this->seo_keywords) : []) as $keywords) {
            $seo_keywords[] = $keywords->value;
        }

        return implode(',', $seo_keywords);
    }

    public function getGetCategoriesAttribute()
    {
        $brandId = $this->id;

        return ProductCategory::where('status', 'publish')->whereHas('products', function ($query) use ($brandId) {
            $query->where('brand_id', $brandId);
        })->get()->map(fn($category) => [
            'safe' => $category->safe
        ]);
    }

    public function getGetFormattedViewCountAttribute()
    {
        return number_format($this->view_count);
    }

    public function getJalaliCreatedAtAttribute()
    {
        $date = [
            Jalalian::forge($this->created_at)->format('%d %B %Y'),
            Jalalian::forge($this->created_at)->format('Y/m/d'),
            Jalalian::forge($this->created_at)->format('H:i - Y/m/d'),
            Jalalian::forge($this->created_at)->ago(),
            Jalalian::forge($this->created_at)->getTimestamp(),
        ];
        return $date;
    }

    public function getJalaliUpdatedAtAttribute()
    {
        $date = [
            Jalalian::forge($this->updated_at)->format('%d %B %Y'),
            Jalalian::forge($this->updated_at)->format('Y/m/d'),
            Jalalian::forge($this->updated_at)->format('H:i - Y/m/d'),
            Jalalian::forge($this->updated_at)->ago(),
            Jalalian::forge($this->updated_at)->getTimestamp(),
        ];
        return $date;
    }

    public function getSimpleSafeAttribute()
    {
        return [
            'id' => $this->id,
            'uuid' => $this->uuid,
            'title' => $this->title,
            'title_en' => $this->title_en,
            'website' => $this->website,
            'slug' => $this->slug,
            'get_logo' => $this->get_logo,
            'status' => $this->status,
            'jalali_created_at' => $this->jalali_created_at,
            'jalali_updated_at' => $this->jalali_updated_at,
        ];
    }

    public function getSafeAttribute()
    {
        return [
            'id' => $this->id,
            'uuid' => $this->uuid,
            'title' => $this->title,
            'title_en' => $this->title_en,
            'website' => $this->website,
            'slug' => $this->slug,
            'content' => $this->content,
            'get_banner' => $this->get_banner,
            'get_logo' => $this->get_logo,
            'seo_title' => $this->seo_title,
            'seo_description' => $this->seo_description,
            'seo_keywords' => $this->seo_keywords,
            'get_seo_keywords' => $this->get_seo_keywords,
            'seo_canonical' => $this->seo_canonical,
            'status' => $this->status,
            'products_count' => $this->products_count,
            'get_categories' => $this->get_categories,
            'jalali_created_at' => $this->jalali_created_at,
            'jalali_updated_at' => $this->jalali_updated_at,
        ];
    }
    /** end append */

    /**
     * Return the sluggable configuration array for this model.
     *
     * @return array
     */
    public function sluggable(): array
    {
        return [
            'slug' => [
                'source' => 'title'
            ]
        ];
    }

    /**
     * Get the route key for the model.
     *
     * @return string
     */
    public function getRouteKeyName()
    {
        return 'slug';
    }

    /**
     * remove cache data in update
     */
    protected static function boot()
    {
        parent::boot();

        static::saved(function ($brand) {
            if (array_key_exists('view_count', $brand->getDirty())) return;

            Cache::forget('brands');

            Cache::forget('product_simple_brand_' . $brand->id);
        });

        static::deleted(function ($brand) {
            Cache::forget('brands');

            Cache::forget('product_simple_brand_' . $brand->id);
        });
    }

    /* relationships **************/
    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class);
    }

    public function editedBy(): BelongsTo
    {
        return $this->belongsTo(User::class, 'edited_by');
    }

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

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