<?php

/** @noinspection LaravelUnknownEloquentFactoryInspection */

namespace DefStudio\GameEngine\Models;

use Spatie\MediaLibrary\HasMedia;
use DefStudio\GameEngine\Enums\Feature;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Collection;
use DefStudio\GameEngine\Enums\MediaCollection;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Database\Eloquent\Casts\AsArrayObject;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use DefStudio\GameEngine\Models\Contracts\AwardsDefiner;
use DefStudio\GameEngine\Database\Factories\AwardFactory;

/**
 * @property int $id
 * @property string $name
 * @property string|null $description
 * @property array $configuration
 * @property string|null $scope_type
 * @property string|null $scope_id
 * @property int|null $parent_id
 * @property-read self|null $parent
 * @property-read Collection<int, self> $children
 * @property-read (AwardsDefiner&Model)|null $scope
 */
class Award extends Model implements HasMedia
{
    use HasFactory;
    use Concerns\HasMedia;

    protected $fillable = [
        'name',
        'description',
    ];

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

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

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

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

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

    /**
     * @return BelongsTo<self, self>
     */
    public function parent(): BelongsTo
    {
        Feature::awards_hierarchy->enforce();

        return $this->belongsTo(game_engine()->awardClass(), 'parent_id');
    }

    /**
     * @return HasMany<self>
     */
    public function children(): HasMany
    {
        Feature::awards_hierarchy->enforce();

        return $this->hasMany(game_engine()->awardClass(), 'parent_id');
    }

    /**
     * @return MorphTo<Model, Award>
     */
    public function scope(): MorphTo
    {
        return $this->morphTo();
    }
}
