<?php
/**
 * Utilidades JWT para autenticación
 * Basado en Firebase PHP-JWT
 */

require_once __DIR__ . '/../../vendor/autoload.php';
require_once __DIR__ . '/../database/connection.php';

use Firebase\JWT\JWT;
use Firebase\JWT\Key;

class JWTAuth {
    private static $secret;
    private static $algorithm = 'HS256';
    private static $expiration = 3600; // 1 hora por defecto
    private static $userData = null; // Para almacenar los datos del usuario autenticado

    private static function init() {
        if (self::$secret === null) {
            self::$secret = $_ENV['JWT_SECRET'] ?? getenv('JWT_SECRET');
            $algo = $_ENV['JWT_ALGORITHM'] ?? getenv('JWT_ALGORITHM');
            $exp = $_ENV['JWT_EXPIRATION'] ?? getenv('JWT_EXPIRATION');
            
            if ($algo) self::$algorithm = $algo;
            if ($exp) self::$expiration = (int)$exp;
        }
    }
    
    /**
     * Generar un token JWT
     */
    public static function generateToken($userId, $username, $rol, $idioma = 'es', $permisos = []) {
        self::init();
        
        $issuedAt = time();
        $expire = $issuedAt + self::$expiration;
        
        $payload = [
            'iat' => $issuedAt,
            'exp' => $expire,
            'iss' => $_ENV['APP_URL'] ?? getenv('APP_URL'),
            'data' => [
                'userId' => $userId,
                'username' => $username,
                'rol' => $rol,
                'idioma' => $idioma,
                'permissions' => $permisos // Cambiado a 'permissions' para consistencia
            ]
        ];
        
        return JWT::encode($payload, self::$secret, self::$algorithm);
    }
    
    /**
     * Validar y decodificar un token JWT
     */
    public static function validateToken($token) {
        self::init();
        
        try {
            $decoded = JWT::decode($token, new Key(self::$secret, self::$algorithm));
            return [
                'valid' => true,
                'data' => $decoded->data
            ];
        } catch (Exception $e) {
            return [
                'valid' => false,
                'error' => $e->getMessage()
            ];
        }
    }
    
    /**
     * Refrescar un token JWT
     */
    public static function refreshToken($token) {
        $result = self::validateToken($token);
        
        if (!$result['valid']) {
            return null;
        }
        
        $data = $result['data'];
        return self::generateToken(
            $data->userId,
            $data->username,
            $data->rol,
            $data->idioma,
            (array)$data->permissions // Cambiado a 'permissions'
        );
    }
    
    /**
     * Extraer el token del header Authorization
     */
    public static function getTokenFromHeader() {
        // Compatibilidad con todos los entornos PHP
        if (function_exists('getallheaders')) {
            $headers = getallheaders();
        } else {
            $headers = [];
            foreach ($_SERVER as $name => $value) {
                if (substr($name, 0, 5) == 'HTTP_') {
                    $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value;
                }
            }
        }
        
        if (isset($headers['Authorization'])) {
            $matches = [];
            if (preg_match('/Bearer\s+(.*)$/i', $headers['Authorization'], $matches)) {
                return $matches[1];
            }
        }
        
        return null;
    }
    
    /**
     * Middleware de autenticación
     * Retorna los datos del usuario si el token es válido, o false si no
     */
    public static function authenticate() {
        if (self::$userData !== null) {
            return self::$userData; // Ya autenticado
        }

        // Intentar obtener el token del header
        $token = self::getTokenFromHeader();
        
        // Si no está en el header, buscar en cookie
        if (!$token && isset($_COOKIE['auth_token'])) {
            $token = $_COOKIE['auth_token'];
        }
        
        if (!$token) {
            return false;
        }
        
        $result = self::validateToken($token);
        
        if (!$result['valid']) {
            return false;
        }
        
        self::$userData = $result['data'];
        return self::$userData;
    }

    /**
     * Obtener los datos del usuario autenticado.
     * Asume que authenticate() o requireAuth() ya han sido llamados.
     */
    public static function getUserData() {
        return self::$userData;
    }
    
    /**
     * Middleware que requiere autenticación
     * Redirige al login si no está autenticado
     */
    public static function requireAuth($redirectTo = '/login.php') {
        $userData = self::authenticate();
        
        if (!$userData) {
            header('Location: ' . $redirectTo);
            exit;
        }
        
        return $userData;
    }
    
    /**
     * Cargar los permisos de un usuario desde la base de datos
     */
    public static function loadUserPermissions($userId) {
        try {
            $db = getDB();
            
            $stmt = $db->prepare("
                SELECT p.nombre
                FROM permisos p
                INNER JOIN usuarios_permisos up ON p.id = up.permiso_id
                WHERE up.usuario_id = ?
            ");
            
            $stmt->execute([$userId]);
            $permisos = $stmt->fetchAll(PDO::FETCH_COLUMN);
            
            return $permisos;
            
        } catch (PDOException $e) {
            error_log("Error cargando permisos: " . $e->getMessage());
            return [];
        }
    }
}

