<?php

namespace App\Models;

use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;

class User extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable;

    // Siempre leer de la BD principal (siser), independientemente del módulo activo.
    // Esto garantiza que la autenticación funcione al cambiar entre Tecnología y Mantenimiento.
    protected $connection = 'pgsql';

    /**
     * The attributes that are mass assignable.
     *
     * @var array<int, string>
     */
    protected $fillable = [
        'cedula',
        'username',
        'name',
        'apellido',
        'email',
        'password',
        'cargo',
        'departamento_id',
        'area_trabajo_id',
        'gerencia_id',
    ];

    /**
     * The attributes that should be hidden for serialization.
     *
     * @var array<int, string>
     */
    protected $hidden = [
        'password',
        'remember_token',
    ];

    /**
     * Get the attributes that should be cast.
     *
     * @return array<string, string>
     */
    protected function casts(): array
    {
        return [
            'email_verified_at' => 'datetime',
            'password' => 'hashed',
        ];
    }

    public function departamento()
    {
        return $this->belongsTo(Departamento::class, 'departamento_id');
    }

    public function gerenciaRel()
    {
        return $this->belongsTo(Gerencia::class, 'gerencia_id');
    }

    /**
     * Acceso rápido a la gerencia del usuario: directa si la tiene,
     * o a través de su departamento (para técnicos).
     */
    public function getGerenciaAttribute()
    {
        return $this->gerenciaRel ?? optional($this->departamento)->gerencia;
    }

    public function areaTrabajo()
    {
        return $this->belongsTo(AreaTrabajo::class, 'area_trabajo_id');
    }

    public function solicitudes()
    {
        return $this->hasMany(Solicitud::class, 'usuario_id');
    }

    /**
     * Verifica si el usuario tiene un cargo específico de un arreglo de roles.
     */
    public function isRole(array $roles): bool
    {
        $normalizedRoles = array_map(function($role) {
            return mb_strtolower($role, 'UTF-8');
        }, $roles);
        return in_array(mb_strtolower($this->cargo, 'UTF-8'), $normalizedRoles);
    }

    /**
     * Solo para administradores puros (acceso a modulo admin).
     */
    public function isAdmin(): bool
    {
        return $this->isRole(['admin', 'administrador']);
    }

    /**
     * Nivel gerencial (ve graficas, etc).
     */
    public function isLiderOrAdmin(): bool
    {
        return $this->isRole(['admin', 'administrador', 'lider', 'jefe de área']);
    }

    /**
     * Quienes pueden asignar tickets y forzar cierres.
     */
    public function canManageTickets(): bool
    {
        return $this->isRole(['admin', 'administrador', 'lider', 'jefe de área']);
    }

    /**
     * Quienes pueden acceder a Recepción de Solicitud.
     */
    public function canReceiveTickets(): bool
    {
        return $this->isRole(['admin', 'administrador', 'lider', 'jefe de área', 'técnico']);
    }

    /**
     * Quienes pueden ser listados como analistas.
     */
    public function canBeAssignedTickets(): bool
    {
        return $this->isRole(['admin', 'administrador', 'técnico', 'jefe de área']);
    }

    /**
     * Verifica si el usuario pertenece a la Gerencia de Mantenimiento.
     * Usa el código de gerencia 'GMANT' (en seeder) o '4400' (en base de datos real).
     * Los administradores siempre tienen acceso.
     */
    public function perteneceAGerenciaMantenimiento(): bool
    {
        if ($this->isAdmin()) {
            return true;
        }

        // Verificar gerencia directa o a través del departamento (accessor 'gerencia')
        $gerencia = $this->gerencia;
        return $gerencia && in_array($gerencia->codigo, ['GMANT', '4400']);
    }

    /**
     * Verifica si el usuario pertenece a una Gerencia de Tecnología.
     * Comprueba que la gerencia del usuario esté bajo la Dirección de Tecnología (DTIC).
     * Los administradores siempre tienen acceso.
     */
    public function perteneceAGerenciaTecnologia(): bool
    {
        if ($this->isAdmin()) {
            return true;
        }

        // Verificar que la gerencia del usuario pertenezca a la Dirección de Tecnología (DTIC)
        $gerencia = $this->gerencia;
        return $gerencia && $gerencia->direccion && $gerencia->direccion->codigo === 'DTIC';
    }

    /**
     * Verifica si el usuario puede gestionar tickets (recepción, ejecución, cierre)
     * en el módulo activo.
     *
     * - Tecnología: requiere pertenecer a una gerencia bajo la Dirección de Tecnología (DTIC).
     * - Mantenimiento: requiere pertenecer a la Gerencia de Mantenimiento (GMANT).
     *
     * NOTA: Crear solicitudes y conformar las propias NO pasan por este método;
     * esas acciones están abiertas para todos los usuarios en cualquier módulo.
     */
    public function canOperateInCurrentModule(): bool
    {
        $modulo = session('modulo_activo', 'tecnologia');

        if ($modulo === 'mantenimiento') {
            return $this->perteneceAGerenciaMantenimiento();
        }

        // Módulo Tecnología: requiere pertenecer a la Dirección de Tecnología (DTIC)
        return $this->perteneceAGerenciaTecnologia();
    }
}
