<?php

namespace App\Models\Permission;

use Dipper\Foundation\Core\Model;
use Illuminate\Support\Collection;
use App\Exceptions\NotExistException;
use App\Models\Permission\Traits\HasRoles;
use Dipper\Foundation\Nestedset\NodeTrait;
use App\Domains\Permission\Services\PermissionService;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use App\Models\Permission\Traits\RefreshesPermissionCache;

/**
 * 权限
 *
 * @property int $id
 * @property string $name 标识
 * @property string $title 名称
 * @property string $description 描述
 * @property string $path 路径
 * @property string $icon 图标
 * @property int $type 类型 0:页面 1:接口
 * @property int $status 状态 0:关闭 1:启用
 * @property int $open 打开方式: 0:iframe方式 1打开新窗口 2:弹出窗口 3:vue组件
 * @property int $height 页面高度
 * @property int $width 页面宽度
 * @property int $displayorder 排序
 * @property int $_lft
 * @property int $_rgt
 * @property int $parent_id
 * @property \Illuminate\Support\Carbon|null $created_at
 * @property \Illuminate\Support\Carbon|null $updated_at
 * @property-read \Dipper\Foundation\Nestedset\Collection|\App\Models\Permission\Permission[] $children
 * @property-read \App\Models\Permission\Permission $parent
 * @property-read \Dipper\Foundation\Nestedset\Collection|\App\Models\Permission\Permission[] $permissions
 * @property-read \Dipper\Foundation\Nestedset\Collection|\App\Models\Permission\Role[] $roles
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Permission\Permission d()
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Permission\Permission newModelQuery()
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Permission\Permission newQuery()
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Permission\Permission permission($permissions)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Permission\Permission query()
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Permission\Permission whereCreatedAt($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Permission\Permission whereDescription($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Permission\Permission whereDisplayorder($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Permission\Permission whereHeight($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Permission\Permission whereIcon($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Permission\Permission whereId($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Permission\Permission whereLft($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Permission\Permission whereName($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Permission\Permission whereOpen($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Permission\Permission whereParentId($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Permission\Permission wherePath($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Permission\Permission whereRgt($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Permission\Permission whereStatus($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Permission\Permission whereTitle($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Permission\Permission whereType($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Permission\Permission whereUpdatedAt($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Permission\Permission whereWidth($value)
 * @mixin \Eloquent
 */
class Permission extends Model
{
    use NodeTrait, HasRoles, RefreshesPermissionCache;

    protected $table = 'permissions';

    protected $fillable = ['id', 'parent_id', 'name', 'title', 'description', 'path', 'icon', 'type', 'status', 'open','height','width', 'displayorder'];

    /**
     * Get the hidden attributes for the model.
     *
     * @return array
     */
    public function getHidden()
    {
        return [$this->getLftName(), $this->getRgtName()];
    }

    /**
     * A permission can be applied to roles.
     */
    public function roles(): BelongsToMany
    {
        return $this->belongsToMany(Role::class, 'role_has_permissions');
    }

    /**
     * Find a permission by its name.
     *
     * @param string $name
     *
     * @throws NotExistException
     *
     * @return Permission
     */
    public static function findByName(string $name): Permission
    {
        $permission = static::getPermissions()->filter(function ($permission) use ($name) {
            return $permission->name === $name;
        })->first();

        if (!$permission) {
            throw new NotExistException('权限不存在');
        }

        return $permission;
    }


    /**
    * Find a permission by its id.
    *
    * @param int $id
    *
    * @throws NotExistException
    *
    * @return Permission
    */
    public static function findById(int $id): Permission
    {
        $permission = static::getPermissions()->filter(function ($permission) use ($id) {
            return $permission->id === $id;
        })->first();

        if (! $permission) {
            throw new NotExistException('权限不存在');
        }

        return $permission;
    }

    /**
     * Get the current cached permissions.
     */
    protected static function getPermissions(): Collection
    {
        return app(PermissionService::class)->getPermissions();
    }
}
