<?php

namespace App\Models\Ecommerce\Channel;

use App\Events\Ecommerce\Channel\ChannelActiveStateChanged;
use App\Models\Ecommerce\Product\Inventory\Inventory;
use App\Models\Ecommerce\Product\Product\Product;
use App\Models\User;
use App\Repositories\Ecommerce\Channel\ChannelRepository;
use App\Repositories\System\Cache\CacheRepository;
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\Database\Eloquent\Relations\MorphTo;
use Illuminate\Database\Eloquent\Relations\MorphToMany;
use Laravel\Nova\Nova;
use Spatie\EloquentSortable\Sortable;
use Spatie\EloquentSortable\SortableTrait;
use Spatie\Image\Manipulations;
use Spatie\MediaLibrary\HasMedia;
use Spatie\MediaLibrary\InteractsWithMedia;
use Spatie\MediaLibrary\MediaCollections\Models\Media;
use Spatie\Sluggable\HasSlug;
use Spatie\Sluggable\SlugOptions;

class Channel extends Model implements HasMedia, Sortable
{
    use HasFactory;
    use HasSlug;
    use InteractsWithMedia;
    use SortableTrait;

    /**
     * The attributes that are mass assignable.
     *
     * @var array<int, string>
     */
    protected $fillable = [
        'id',
        'name',
        'slug',
        'description',
        'timezone',
        'url',
        'sort_order',
        'is_default',
        'is_visible',
        'channelables_type',
        'channelables_id',
    ];

    /**
     * Sortable attributes
     *
     * @var array<string, mixed>
     */
    public $sortable = [
        'order_column_name' => 'sort_order',
        'sort_when_creating' => true,
    ];

    /**
     * The "booted" method of the model.
     */
    protected static function booted(): void
    {
        static::created(function (Channel $channel) {
            CacheRepository::forget(ChannelRepository::CHANNEL_CACHE_NAME_FOR_NOVA);
        });

        static::updated(function (Channel $channel) {
            if ($channel->wasChanged('is_visible')) {
                ChannelActiveStateChanged::dispatch($channel);

                CacheRepository::forget(ChannelRepository::CHANNEL_CACHE_NAME_FOR_NOVA);
            }
        });

        static::deleted(function (Channel $channel) {
            CacheRepository::forget(ChannelRepository::CHANNEL_CACHE_NAME_FOR_NOVA);
        });
    }

    /**
     * Get the options for generating the slug.
     */
    public function getSlugOptions(): SlugOptions
    {
        return SlugOptions::create()
            ->generateSlugsFrom('name')
            ->saveSlugsTo('slug');
    }

    /**
     * Media collections
     */
    public function registerMediaCollections(): void
    {
        $this->addMediaCollection('uploads')
            ->singleFile()
            ->useFallbackUrl(
                sprintf('%s/logo-space.png', config('app.url'))
            );
    }

    /**
     * Media conversations
     */
    public function registerMediaConversions(?Media $media = null): void
    {
        $this->addMediaConversion('thumb150x150')
            ->fit(Manipulations::FIT_CONTAIN, 150, 150);

        $this->addMediaConversion('thumb200x200')
            ->fit(Manipulations::FIT_CONTAIN, 200, 200);

        $this->addMediaConversion('thumb400x400')
            ->fit(Manipulations::FIT_CONTAIN, 400, 400);

        $this->addMediaConversion('thumb720x720')
            ->fit(Manipulations::FIT_CONTAIN, 720, 720);

        $this->addMediaConversion('thumb800x800')
            ->fit(Manipulations::FIT_CONTAIN, 800, 800);

        $this->addMediaConversion('thumb1200x1200')
            ->fit(Manipulations::FIT_CONTAIN, 1200, 1200);

        $this->addMediaConversion('thumb288x431')
            ->fit(Manipulations::FIT_CONTAIN, 288, 431);

        $this->addMediaConversion('thumb270x350')
            ->fit(Manipulations::FIT_CONTAIN, 270, 350);
    }

    /**
     * Channel thumbnail
     */
    public function thumbnail(string $size = '200x200'): string
    {
        return $this->getFirstMediaUrl('uploads', 'thumb'.$size);
    }

    /**
     * Get the parent channelables model.
     */
    public function channelables(): MorphTo
    {
        return $this->morphTo();
    }

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

    /**
     * Default tmpost inventory
     */
    public static function tmpostDefault(): static
    {
        return static::where('slug', 'tmpost')->first();
    }

    /**
     * Channels inventories
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    // public function inventories(): HasMany
    // {
    //     return $this->hasMany(Inventory::class);
    // }

    /**
     * Products
     */
    public function products(): MorphToMany
    {
        return $this->morphToMany(Product::class, 'productable', 'product_has_relations');
    }

    /**
     * Show products link
     */
    public function productsPage(): string
    {
        return route('web.entrepreneurs.show', ['entrepreneur' => $this->slug]);
    }

    /**
     * Image
     */
    public function image(): string
    {
        return $this->getFirstMediaUrl('main');
    }

    /**
     * Channels inventories
     */
    public function inventories(): HasMany
    {
        return $this->hasMany(Inventory::class);
    }

    /**
     * Nova detail page
     */
    public function novaDetailPage(): string
    {
        return Nova::url('/resources/channels/'.$this->id);
    }
}
