<?php

namespace App\Models;

use App\Traits\Auditable;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;

class Usuario extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable, Auditable;

    /**
     * Tabla asociada
     */
    protected $table = 'usuarios';

    /**
     * Clave primaria
     */
    protected $primaryKey = 'usu_id';

    /**
     * Sin timestamps automáticos de Laravel
     */
    public $timestamps = false;

    /**
     * Campos asignables masivamente
     */
    protected $fillable = [
        'usu_nombre',
        'usu_apellido',
        'usu_cedula',
        'usu_fecha_nac',
        'usu_cod_tc',
        'usu_usuario',
        'usu_clave',
        'password_laravel',
        'per_id',
        'usu_estado',
        'usu_email',
        'fecha_ingreso',
        'id_sotickets',
        'usu_ultimo_login',
        'usu_intentos_fallidos',
        'usu_bloqueado_hasta',
        'usu_cambio_password',
        'usu_token_recuperacion',
        'usu_token_expira',
    ];

    /**
     * Campos ocultos en serialización
     */
    protected $hidden = [
        'usu_clave',
        'password_laravel',
        'usu_token_recuperacion',
        'remember_token',
    ];

    /**
     * Casting de atributos
     */
    protected function casts(): array
    {
        return [
            'usu_fecha_nac' => 'date',
            'fecha_ingreso' => 'date',
            'usu_ultimo_login' => 'datetime',
            'usu_bloqueado_hasta' => 'datetime',
            'usu_token_expira' => 'datetime',
            'usu_cambio_password' => 'boolean',
            'usu_estado' => 'integer',
            'usu_intentos_fallidos' => 'integer',
        ];
    }

    /**
     * Campo de password para Sanctum
     */
    public function getAuthPassword(): string
    {
        return $this->password_laravel;
    }

    /**
     * Identificador para Sanctum
     */
    public function getAuthIdentifierName(): string
    {
        return 'usu_id';
    }

    /**
     * Relación con Perfil
     */
    public function perfil()
    {
        return $this->belongsTo(Perfil::class, 'per_id', 'per_id');
    }

    /**
     * Obtener el rol del usuario (a través del perfil)
     */
    public function getRolAttribute(): ?SysRol
    {
        return $this->perfil?->rol;
    }

    /**
     * Obtener el rol_id directamente
     */
    public function getRolIdAttribute(): ?int
    {
        return $this->perfil?->rol_id;
    }

    /**
     * Obtener el código del rol
     */
    public function getRolCodigoAttribute(): ?string
    {
        return $this->perfil?->rol?->rol_codigo;
    }

    /**
     * Verificar si el usuario tiene un permiso específico
     */
    public function tienePermiso(string $codigoPermiso): bool
    {
        if (!$this->perfil) {
            return false;
        }

        return $this->perfil->tienePermiso($codigoPermiso);
    }

    /**
     * Verificar si el usuario tiene acceso total (SISTEMAS o ADMINISTRADOR)
     */
    public function tieneAccesoTotal(): bool
    {
        $rolesConAccesoTotal = ['SISTEMAS', 'ADMINISTRADOR'];
        return in_array($this->rol_codigo, $rolesConAccesoTotal);
    }

    /**
     * Relación con Empresas
     */
    public function empresas()
    {
        return $this->belongsToMany(
            Empresa::class,
            'usuario_empresa',
            'usu_id',
            'emp_id'
        );
    }

    /**
     * Nombre completo
     */
    public function getNombreCompletoAttribute(): string
    {
        return "{$this->usu_nombre} {$this->usu_apellido}";
    }

    /**
     * Verificar si está bloqueado
     */
    public function estaBloqueado(): bool
    {
        if ($this->usu_bloqueado_hasta === null) {
            return false;
        }
        return now()->lt($this->usu_bloqueado_hasta);
    }

    /**
     * Incrementar intentos fallidos
     */
    public function incrementarIntentosFallidos(): void
    {
        $this->usu_intentos_fallidos++;

        // Bloquear después de 5 intentos
        if ($this->usu_intentos_fallidos >= 5) {
            $this->usu_bloqueado_hasta = now()->addMinutes(15);
        }

        $this->save();
    }

    /**
     * Resetear intentos fallidos
     */
    public function resetearIntentosFallidos(): void
    {
        $this->usu_intentos_fallidos = 0;
        $this->usu_bloqueado_hasta = null;
        $this->save();
    }

    /**
     * Registrar login exitoso
     */
    public function registrarLogin(): void
    {
        $this->usu_ultimo_login = now();
        $this->resetearIntentosFallidos();
    }

    /**
     * Verificar si tiene acceso web
     */
    public function tieneAccesoWeb(): bool
    {
        return $this->perfil && $this->perfil->per_acceso_web == 1;
    }

    /**
     * Verificar si tiene acceso app
     */
    public function tieneAccesoApp(): bool
    {
        return $this->perfil && $this->perfil->per_acceso_app == 1;
    }

    /**
     * Scope para buscar por nombre o cédula
     */
    public function scopeBuscar($query, string $termino)
    {
        return $query->where(function ($q) use ($termino) {
            $q->where('usu_nombre', 'LIKE', "%{$termino}%")
                ->orWhere('usu_apellido', 'LIKE', "%{$termino}%")
                ->orWhere('usu_cedula', 'LIKE', "%{$termino}%")
                ->orWhere('usu_email', 'LIKE', "%{$termino}%");
        });
    }

    /**
     * Scope para filtrar por perfil
     */
    public function scopePorPerfil($query, int $perfilId)
    {
        return $query->where('per_id', $perfilId);
    }
}
