<?php

namespace Modules\User\Models;

use Catch\Base\CatchModel as Model;
use Illuminate\Auth\Authenticatable;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Laravel\Sanctum\HasApiTokens;
use Modules\Channel\Exceptions\ChannelBusinessException;
use Modules\Common\Errors\Errors;
use Modules\Common\Repository\Options\Modules;
use Modules\User\Models\Traits\UserRelations;

/**
 * @property int $id
 * @property string $username
 * @property string $email
 * @property string $avatar
 * @property string $password
 * @property int $creator_id
 * @property int $status
 * @property string $login_ip
 * @property int $login_at
 * @property int $created_at
 * @property int $updated_at
 * @property string $remember_token
 */
class User extends Model implements AuthenticatableContract
{
    use Authenticatable, UserRelations, HasApiTokens;

    protected $fillable = [
        'id', 'username', 'email', 'avatar', 'password', 'remember_token', 'creator_id',
        'status', 'department_id', 'login_ip', 'login_at', 'created_at', 'updated_at', 'deleted_at',
        'remark'
    ];

    /**
     * @var array|string[]
     */
    public array $searchable = [
        'username' => 'like',
        'email' => 'like',
        'status' => '='
    ];

    /**
     * @var string
     */
    protected $table = 'users';

    protected array $fields = ['id', 'username', 'email', 'avatar',  'creator_id', 'status', 'department_id', 'created_at'];

    /**
     * @var array|string[]
     */
    protected array $form = ['username', 'email', 'password', 'department_id'];

    /**
     * @var array|string[]
     */
    protected array $formRelations = ['roles', 'jobs'];

    /**
     * password
     *
     * @return Attribute
     */
    protected function password(): Attribute
    {
        return new Attribute(
            // get: fn($value) => '',
            set: fn ($value) => bcrypt($value),
        );
    }

    /**
     * is super admin
     *
     * @return bool
     */
    public function isSuperAdmin(): bool
    {
        return $this->{$this->primaryKey} == config('catch.super_admin');
    }

    /**
     * update
     * @param $id
     * @param array $data
     * @return mixed
     */
    public function updateBy($id, array $data): mixed
    {
        if(getProp($data,'password')){
            User::query()->where('id',$id)->update(['password' => bcrypt($data['password'])]);
            unset($data['password']);
        }
        return parent::updateBy($id, $data);
    }

    /**
     * 如果$showApp为空那么就不展示所有isApp为true的模块
     * 否则展示所有isApp为false以及showApp对应的name的模块
     * @param string $showApp
     */

    public function showPermissions($showApp = '') {
        $appModules = Modules::getAppModules();
        if(!is_null($appModules)) {
            $hiddenAppModuleNames = $appModules->reject(function ($module) use ($showApp) {
                return $showApp == $module['name'];
            })->pluck('name');
        } else {
            $hiddenAppModuleNames = collect();
        }
        $enablePermissions = $this->getAttribute('permissions')->reject(function ($permission) use ($hiddenAppModuleNames){
            return $hiddenAppModuleNames->contains($permission['module']);
        })->values()->all();
        $this->setAttribute('permissions', $enablePermissions);
    }

    /**
     * 保证邮箱没有被使用
     * @param $email
     */
    public function emailUnique($email) {
        $user = $this->where([
            'email' => $email,
            'deleted_at' => 0,
        ])->first();
        if($user) {
            ChannelBusinessException::throwError(Errors::EMAIL_EXISTS);
        }
    }
}