<?php

/** @noinspection LaravelUnknownEloquentFactoryInspection */

namespace DefStudio\GameEngine\Models;

use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Collection;
use DefStudio\GameEngine\Attributes\ParentScope;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use DefStudio\GameEngine\Models\Contracts\FitsInScope;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use DefStudio\GameEngine\Models\Concerns\DefinesAwards;
use DefStudio\GameEngine\Models\Concerns\BelongsToScope;
use DefStudio\GameEngine\Models\Contracts\AwardsDefiner;
use DefStudio\GameEngine\Database\Factories\StoryFactory;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use DefStudio\GameEngine\Models\Concerns\HasStorytellings;
use DefStudio\GameEngine\Models\Contracts\WithStorytelling;
use DefStudio\GameEngine\Models\Concerns\CanCheckRelationships;

/**
 * @property int $id
 * @property string $title
 * @property string $description
 * @property Carbon|null $published_at
 * @property int $organization_id
 * @property-read Organization $organization
 * @property-read Collection<int, Team> $teams
 * @property-read Collection<int, Map> $maps
 *
 * @method static StoryFactory factory(array|callable|int|null $count = null, array|callable $state = [])
 */
class Story extends Model implements WithStorytelling, AwardsDefiner, FitsInScope
{
    use HasFactory;
    use CanCheckRelationships;
    use HasStorytellings;
    use DefinesAwards;
    use BelongsToScope;

    protected $fillable = [
        'title',
        'description',
        'published_at',
    ];

    protected $casts = [
        'published_at' => 'datetime',
    ];

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

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

    /**
     * @return BelongsTo<Organization, Story>
     */
    #[ParentScope(Organization::class)]
    public function organization(): BelongsTo
    {
        return $this->belongsTo(\game_engine()->organizationClass());
    }

    /**
     * @return BelongsToMany<Team>
     */
    public function teams(): BelongsToMany
    {
        return $this->belongsToMany(\game_engine()->teamClass());
    }

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

    public function award_scope_label(): string
    {
        return __('Story: :story_title', ['story_title' => $this->title]);
    }
}
