<?php

namespace App\Models;

use App\Exceptions\ValidationException;
use App\Notifications\MailResetPasswordNotification;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
use OwenIt\Auditing\Auditable;
use OwenIt\Auditing\Contracts\Auditable as AuditableContract;
use Spatie\Permission\Traits\HasRoles;

class User extends Authenticatable implements AuditableContract
{
    use Notifiable, SoftDeletes, HasRoles {
        assignRole as parentAssignRole;
    }
    use Auditable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'email', 'password',
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];

    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];

    protected $auditStrict = true;

    public function sendPasswordResetNotification($token)
    {
        $this->notify(new MailResetPasswordNotification($token));
    }

    public function assignRole($role)
    {
        $assinable = Role::assignable()->get();

        if ($this->hasRole($role)) {
            throw new ValidationException("Usuário já possui perfil $role");
        }

        if (!$assinable->whereIn('name', $role)->count()) {
            throw new ValidationException("Perfil $role não pode ser atribuído");
        }

        $this->parentAssignRole([$role]);
    }

    public function scopeComRole($query, $role)
    {
        return $query->whereHas('roles', function ($q) use ($role) {
            if (is_array($role)) {
                return $q->whereIn('name', $role);
            }

            return $q->where('name', $role);
        });
    }

    public function scopeSearch($query, $busca = '')
    {
        if ($busca) {
            return $query->where(function ($query) use ($busca) {
                $query->where('name', 'ilike', "%{$busca}%")
                ->orWhere('email', 'ilike', "%{$busca}%")
                ->orderBy('name', 'asc');
            });
        }

        return $query
                ->orderBy('name', 'asc');
    }

    public function funcionario()
    {
        return $this->hasOne(Funcionario::class);
    }

    public function prestador()
    {
        return $this->hasOne(PrestadorServico::class);
    }
}
