<?php

/** @noinspection LaravelUnknownEloquentFactoryInspection */

namespace DefStudio\GameEngine\Models;

use Spatie\MediaLibrary\HasMedia;
use Illuminate\Database\Eloquent\Model;
use DefStudio\GameEngine\Enums\MediaCollection;
use DefStudio\GameEngine\Attributes\ParentScope;
use Illuminate\Database\Eloquent\Casts\AsArrayObject;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use DefStudio\GameEngine\Models\Contracts\FitsInScope;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use DefStudio\GameEngine\Database\Factories\TaskFactory;
use DefStudio\GameEngine\Decorators\Tasks\TaskDecorator;
use DefStudio\GameEngine\Models\Concerns\BelongsToScope;
use DefStudio\GameEngine\Models\Concerns\HasStorytellings;
use DefStudio\GameEngine\Models\Contracts\WithStorytelling;

/**
 * @property int $id
 * @property string $title
 * @property class-string<TaskDecorator> $type
 * @property array<string, mixed> $configuration
 * @property-read Mission $mission
 *
 * @method static TaskFactory factory(array|callable|int|null $count = null, array|callable $state = [])
 */
class Task extends Model implements HasMedia, WithStorytelling, FitsInScope
{
    use HasFactory;
    use Concerns\HasMedia{
        registerMediaCollections as __registerMediaCollections;
    }
    use HasStorytellings;
    use BelongsToScope;

    public bool $registerMediaConversionsUsingModelInstance = true;

    protected $fillable = [
        'title',
        'type',
    ];

    protected $casts = [
        'configuration' => AsArrayObject::class,
        'order' => 'integer',
    ];

    protected $attributes = [
        'configuration' => '{}',
    ];

    protected array $media_collections = [
        MediaCollection::assets,
    ];

    public function getTable()
    {
        return config('game-engine.tasks.table', parent::getTable());
    }

    protected static function newFactory(): TaskFactory
    {
        return TaskFactory::new();
    }

    /**
     * @return BelongsTo<Mission, Task>
     */
    #[ParentScope(Mission::class)]
    public function mission(): BelongsTo
    {
        return $this->belongsTo(game_engine()->missionClass(), 'mission_id');
    }

    public function decorate(): TaskDecorator
    {
        return $this->type::build($this);
    }

    public function registerMediaCollections(): void
    {
        $this->decorate()->__registerMediaCollections();
    }
}
