<?php

namespace App\Middleware;

use App\Services\Database;

/**
 * Middleware de autenticación y autorización
 */
class AuthMiddleware
{
    private $database;

    public function __construct()
    {
        $this->database = Database::getInstance();
    }

    /**
     * Verificar si el usuario está autenticado
     */
    public function isAuthenticated(): bool
    {
        return isset($_SESSION['user']) && !empty($_SESSION['user']);
    }

    /**
     * Verificar si el usuario tiene un rol asignado
     */
    public function hasRole(): bool
    {
        if (!$this->isAuthenticated()) {
            return false;
        }

        $user = $_SESSION['user'] ?? null;
        if (!$user) {
            return false;
        }

        // Debug logging
        error_log('AuthMiddleware::hasRole() - User data: ' . json_encode([
            'user_id' => $user['id'] ?? 'null',
            'is_active' => $user['is_active'] ?? 'null',
            'is_active_type' => gettype($user['is_active'] ?? 'null'),
            'role_id' => $user['role_id'] ?? 'null',
            'role_id_type' => gettype($user['role_id'] ?? 'null')
        ]));

        $hasRoleId = isset($user['role_id']) && $user['role_id'] !== null && $user['role_id'] !== '';
        $isActive = !empty($user['is_active']) && ($user['is_active'] == 1 || $user['is_active'] === true || $user['is_active'] === 'true');

        error_log('AuthMiddleware::hasRole() - Check results: hasRoleId=' . ($hasRoleId ? 'true' : 'false') . ', isActive=' . ($isActive ? 'true' : 'false'));

        return $hasRoleId && $isActive;
    }

    /**
     * Verificar si el usuario es administrador
     */
    public function isAdmin(): bool
    {
        return $this->hasRole() && ($_SESSION['user']['is_admin'] ?? false);
    }

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

        $user = $_SESSION['user'];

        // Super admin tiene todos los permisos
        if ($user['role_name'] === 'super_admin') {
            return true;
        }

        // Verificar permisos específicos
        if (isset($user['permissions'])) {
            $permissions = json_decode($user['permissions'], true);
            return in_array($permission, $permissions) || in_array('all', $permissions);
        }

        return false;
    }

    /**
     * Requerir autenticación
     */
    public function requireAuth(string $redirectTo = '/login'): void
    {
        if (!$this->isAuthenticated()) {
            $this->redirect($redirectTo);
        }
    }

    /**
     * Requerir rol asignado
     */
    public function requireRole(string $redirectTo = '/pending'): void
    {
        $this->requireAuth();
        
        // Refrescar datos del usuario antes de verificar el rol
        if (isset($_SESSION['user']['id'])) {
            $this->refreshUserSession($_SESSION['user']['id']);
        }
        
        if (!$this->hasRole()) {
            error_log('AuthMiddleware::requireRole() - Role check failed, redirecting to: ' . $redirectTo);
            $this->redirect($redirectTo);
        }
    }

    /**
     * Requerir permisos de administrador
     */
    public function requireAdmin(string $redirectTo = '/dashboard'): void
    {
        $this->requireRole();
        
        if (!$this->isAdmin()) {
            $this->redirect($redirectTo);
        }
    }

    /**
     * Requerir permiso específico
     */
    public function requirePermission(string $permission, string $redirectTo = '/dashboard'): void
    {
        $this->requireRole();
        
        if (!$this->hasPermission($permission)) {
            $this->redirect($redirectTo);
        }
    }

    /**
     * Middleware para rutas que requieren rol
     */
    public function handleRoleRequired(): void
    {
        if (!$this->isAuthenticated()) {
            $this->redirect('/login');
        }
        
        if (!$this->hasRole()) {
            $this->redirect('/pending');
        }
    }

    /**
     * Middleware para rutas de administración
     */
    public function handleAdminRequired(): void
    {
        $this->handleRoleRequired();
        
        if (!$this->isAdmin()) {
            http_response_code(403);
            $this->showError('No tienes permisos para acceder a esta sección.');
        }
    }

    /**
     * Obtener usuario actual
     */
    public function getCurrentUser(): ?array
    {
        return $_SESSION['user'] ?? null;
    }

    /**
     * Actualizar datos del usuario en sesión
     */
    public function refreshUserSession(int $userId): bool
    {
        try {
            $user = $this->database->fetchOne(
                'SELECT u.*, r.name as role_name, r.display_name as role_display_name, 
                        r.is_admin, r.permissions, r.is_active as role_active
                FROM users u 
                LEFT JOIN roles r ON u.role_id = r.id 
                WHERE u.id = ?',
                [$userId]
            );

            if ($user) {
                $_SESSION['user'] = $user;
                error_log('AuthMiddleware::refreshUserSession() - Updated session with: ' . json_encode([
                    'user_id' => $user['id'],
                    'is_active' => $user['is_active'],
                    'role_id' => $user['role_id'],
                    'role_name' => $user['role_name'] ?? 'null'
                ]));
                return true;
            }

            error_log('AuthMiddleware::refreshUserSession() - User not found for ID: ' . $userId);
            return false;
        } catch (\Exception $e) {
            error_log('AuthMiddleware::refreshUserSession() - Error: ' . $e->getMessage());
            return false;
        }
    }

    /**
     * Limpiar sesión
     */
    public function logout(): void
    {
        session_destroy();
        session_start();
    }

    /**
     * Redireccionar
     */
    private function redirect(string $url): void
    {
        header("Location: $url");
        exit;
    }

    /**
     * Mostrar error de permisos
     */
    private function showError(string $message): void
    {
        echo json_encode([
            'error' => true,
            'message' => $message
        ]);
        exit;
    }

    /**
     * Generar token CSRF
     */
    public function generateCsrfToken(): string
    {
        if (!isset($_SESSION['csrf_token'])) {
            $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
        }
        return $_SESSION['csrf_token'];
    }

    /**
     * Verificar token CSRF
     */
    public function verifyCsrfToken(string $token): bool
    {
        return isset($_SESSION['csrf_token']) && hash_equals($_SESSION['csrf_token'], $token);
    }
}