<?php

namespace App\Models;

use App\Helpers\StringHelper;
use App\Models\Category;
use App\Models\Image;
use App\Models\Meeting;
use App\Models\PostTranslation;
use Cog\Contracts\Love\Reactable\Models\Reactable as ReactableInterface;
use Cog\Laravel\Love\Reactable\Models\Traits\Reactable;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Laravel\Scout\Searchable;
use Spatie\MediaLibrary\HasMedia;
use Spatie\MediaLibrary\InteractsWithMedia;
use Spatie\MediaLibrary\MediaCollections\Models\Media;
use Znck\Eloquent\Traits\BelongsToThrough;


class Post extends Model implements HasMedia, ReactableInterface
{
    use HasFactory;
    use BelongsToThrough;
    use InteractsWithMedia;
    use SoftDeletes;
    use Searchable; // laravel/scout with ElasticSearch
    use Reactable; // cybercog/laravel-love



    protected $fillable = ['postable_id', 'postable_type',  'category_id', 'author_id', 'author_model'];

    /**
     * Get the index name for the model.
     *
     * @return string
     */
    public function searchableAs()
    {
        return 'posts_index';
    }


    /**
     * Convert the this model to a searchable array.
     *
     * @return array
     */
    public function toSearchableArray()
    {
        return [
            'id' => $this->id,
            'category_id' => $this->category_id,

            'postable' => [
                'id' => $this->postable ? $this->postable->id : '',
                'name' => $this->postable ? $this->postable->name : '',
            ],

            'post_translations' => $this->translations->mapWithKeys(function ($translation) {
                // mapWithKeys() as translations is a collection
                return [
                    'title_' . $translation->locale => $translation->title,
                    'excerpt_' . $translation->locale => $translation->excerpt,
                    'content_' . $translation->locale => $translation->content,
                    // Add publication fields
                    'from_' . $translation->locale => $translation->from,
                    'till_' . $translation->locale => $translation->till,
                    'deleted_at_' . $translation->locale => $translation->deleted_at,
                    'status_' . $translation->locale => $translation->status,
                ];
            })->toArray(),

            'post_category' => $this->category ? [
                'id' => $this->category->id,
                'names' => $this->category->translations->mapWithKeys(function ($translation) {
                    // Include the locale in the field name for categories
                    return ['name_' . $translation->locale => StringHelper::DutchTitleCase($translation->name)];
                })->toArray(),
            ] : [],
        ];
    }



    /**
     * Get the creator of the post (i.e. user or organization).
     *
     * @return void
     */
    public function postable()
    {
        return $this->morphTo();
    }

    /**
     * Get the author of the post (polymorphic: User, Organization, or Bank).
     *
     * @return void
     */
    public function author()
    {
        return $this->morphTo('author', 'author_model', 'author_id');
    }


    /**
     * Get the related translations of the post
     * One-to-many relationship
     * @return void
     */
    public function translations()
    {
        return $this->hasMany(PostTranslation::class);
    }


    /**
     * Get the related category of the post
     *
     * @return void
     */
    public function category()
    {
        return $this->belongsTo(Category::class);
    }



    /**
     * Get the related images of the posts
     *
     * @return void
     */
    public function images()
    {
        return $this->morphToMany(Image::class, 'imageable');
    }


    public static function last()
    {
        return static::all()->last();
    }


    /**
     * Spatie Media Library media conversions
     * When updated you can use:
     * php artisan media-library:regenerate
     * to regenerate media disk and database of all media stored (make sure you restart the queue worker first)
     *
     * @param  mixed $media
     * @return void
     */
    public function registerMediaConversions(Media $media = null): void
    {
        $this->addMediaConversion('favicon')    //1:1
            ->focalCrop(32, 32, 50, 50)
            ->optimize()
            ->format('gif')
            ->performOnCollections('posts');

        $this->addMediaConversion('logo')   //1:1
            ->focalCrop(160, 160, 50, 50)
            ->optimize()
            ->format('webp')
            ->performOnCollections('posts');

        $this->addMediaConversion('thumbnail')  // 1:1
            ->focalCrop(150, 150, 50, 50)
            ->optimize()
            ->format('webp')
            ->performOnCollections('posts');

        $this->addMediaConversion('blog')   //3:2
            ->focalCrop(1200, 630, 50, 50)
            ->withResponsiveImages()
            ->optimize()
            ->format('webp')
            ->performOnCollections('posts');

        $this->addMediaConversion('hero')   //16:9
            ->focalCrop(3840, 2160, 50, 50)
            ->withResponsiveImages()
            ->optimize()
            ->format('webp')
            ->performOnCollections('posts');

        $this->addMediaConversion('half_hero') //16:4.5 panoramic
            ->focalCrop(3840, 1080, 50, 50)
            ->format('webp')
            ->performOnCollections('posts');

        $this->addMediaConversion('4_3')    //4:3
            ->focalCrop(3072, 2304, 50, 50)
            ->withResponsiveImages()
            ->optimize()
            ->format('webp')
            ->performOnCollections('posts');

        $this->addMediaConversion('email')    // For email newsletters - resizes without cropping
            ->width(800)
            ->optimize()
            ->format('jpg')
            ->quality(85)
            ->performOnCollections('posts');

    }

    public function registerMediaCollection(): void
    {
        $this->addMediaCollection('posts')
            ->useDisk('media')
            ->singleFile();
    }


    /**
     * Get the related meeting of the post
     * One-to-one relation
     *
     * @return void
     */
    public function meeting()
    {
        return $this->hasOne(Meeting::class);
    }

    /**
     * Get the count of 'like' reactions for this post
     *
     * @return int
     */
    public function getLikeCountAttribute()
    {
        // Check if post is registered as reactant before getting reactions
        if (!$this->isRegisteredAsLoveReactant()) {
            return 0;
        }

        // Get the reactant facade
        $reactantFacade = $this->viaLoveReactant();

        // Get the reaction counter for 'Like' type
        $reactionCounter = $reactantFacade->getReactionCounterOfType('Like');

        if (!$reactionCounter) {
            return 0;
        }

        // Return the total count from all users
        return $reactionCounter->getCount();
    }


}
