<?php
/**
 * SIE ASESORIAS - Plugin Admin Menu (Helper Component)
 *
 * Logica de permisos y manejo del menu de administracion
 *
 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
 * @author  SIE ASESORIAS <soporte@sieasesorias.com>
 */

if (file_exists(DOKU_PLUGIN . 'bez/meta/path_helper.php')) require_once(DOKU_PLUGIN . 'bez/meta/path_helper.php');

class helper_plugin_niccadminmenu extends DokuWiki_Plugin
{
    /** @var helper_plugin_sqlite */
    protected $sqlite = null;

    /** @var bool */
    protected $dbInitialized = false;

    /** Niveles de rol - Superuser es el mas alto */
    const ROLE_SUPERUSER = 255;
    const ROLE_ADMIN = 128;
    const ROLE_MANAGER = 64;

    /** Iconos SVG */
    protected $icons = [];

    /**
     * Constructor
     */
    public function __construct()
    {
        $this->loadIcons();
    }

    /**
     * Obtiene la conexion a la base de datos
     *
     * @return helper_plugin_sqlite|null
     */
    public function getDB()
    {
        if ($this->dbInitialized) {
            return $this->sqlite;
        }

        $this->dbInitialized = true;

        /** @var helper_plugin_sqlite $sqlite */
        $sqlite = plugin_load('helper', 'sqlite');
        if (!$sqlite) {
            msg('El plugin SQLite es requerido para niccadminmenu', -1);
            return null;
        }

        if (!$sqlite->init('niccadminmenu', (function_exists('bez_plugin_base') ? bez_plugin_base() : DOKU_PLUGIN) . 'niccadminmenu/db/')) {
            return null;
        }
        $this->sqlite = $sqlite;

        // Auto-registrar items criticos que deben existir
        $this->ensureCriticalItems();

        return $this->sqlite;
    }

    /**
     * Verifica y crea items criticos del menu que deben existir.
     * Se ejecuta una sola vez por sesion al inicializar la BD.
     * Esto garantiza que items nuevos se registren automaticamente
     * en los 230+ sistemas sin intervencion manual.
     */
    protected function ensureCriticalItems()
    {
        $criticalItems = [
            [
                'code'         => 'repair_filelisting',
                'plugin_name'  => 'bezdbrepair',
                'name'         => 'Reparar Filelisting',
                'description'  => 'Corrige rutas de filelisting en paginas de control administrativo',
                'icon'         => 'wrench',
                'url'          => '?do=admin&page=bezdbrepair&action=filelisting_repair',
                'sort_order'   => 95,
                'category'     => 'tools',
                'fallback_cat' => 'nicc_modules',
                'requires_confirmation' => 1,
                'roles'        => ['manager' => [1,1], 'admin' => [1,1], 'superuser' => [1,1]]
            ],
            [
                'code'         => 'docmaster',
                'plugin_name'  => 'docmaster',
                'name'         => 'Listado Maestro de Documentos',
                'description'  => 'Gestor centralizado de documentos, formatos, versiones y vigencias',
                'icon'         => 'scroll-text',
                'url'          => '?do=admin&page=docmaster',
                'sort_order'   => 6,
                'category'     => 'nicc_modules',
                'fallback_cat' => 'tools',
                'requires_confirmation' => 0,
                'roles'        => ['manager' => [1,1], 'admin' => [1,1], 'superuser' => [1,1]]
            ],
        ];

        $db = $this->sqlite;
        if (!$db) return;

        foreach ($criticalItems as $item) {
            // Verificar si ya existe
            $res = $db->query('SELECT id FROM admin_menu_items WHERE code = ?', $item['code']);
            $row = $res ? $db->res2row($res) : null;

            if ($row) continue; // Ya existe, saltar

            // Buscar categoria
            $res = $db->query(
                'SELECT id FROM admin_menu_categories WHERE code = ?',
                $item['category']
            );
            $catRow = $res ? $db->res2row($res) : null;

            if (!$catRow && !empty($item['fallback_cat'])) {
                $res = $db->query(
                    'SELECT id FROM admin_menu_categories WHERE code = ?',
                    $item['fallback_cat']
                );
                $catRow = $res ? $db->res2row($res) : null;
            }

            if (!$catRow) continue; // Sin categoria, no insertar

            // Insertar item
            $db->query(
                'INSERT INTO admin_menu_items (category_id, code, plugin_name, name, description, icon, url, sort_order, is_active, is_dangerous, requires_confirmation) VALUES (?, ?, ?, ?, ?, ?, ?, ?, 1, 0, ?)',
                $catRow['id'],
                $item['code'],
                $item['plugin_name'],
                $item['name'],
                $item['description'],
                $item['icon'],
                $item['url'],
                $item['sort_order'],
                $item['requires_confirmation'] ?? 0
            );

            // Obtener ID del item insertado
            $res = $db->query('SELECT id FROM admin_menu_items WHERE code = ?', $item['code']);
            $newRow = $res ? $db->res2row($res) : null;

            if ($newRow && !empty($item['roles'])) {
                foreach ($item['roles'] as $role => $perms) {
                    $db->query(
                        'INSERT OR REPLACE INTO admin_menu_permissions (item_id, role, can_view, can_execute) VALUES (?, ?, ?, ?)',
                        $newRow['id'], $role, $perms[0], $perms[1]
                    );
                }
            }
        }
    }

    /**
     * Ejecuta una consulta y devuelve todos los resultados como array
     */
    protected function queryAll($sql, $params = [])
    {
        $db = $this->getDB();
        if (!$db) return [];

        $res = $db->query($sql, $params);
        if (!$res) return [];

        return $db->res2arr($res);
    }

    /**
     * Ejecuta una consulta y devuelve una sola fila
     */
    protected function queryRow($sql, $params = [])
    {
        $db = $this->getDB();
        if (!$db) return null;

        $res = $db->query($sql, $params);
        if (!$res) return null;

        return $db->res2row($res);
    }

    /**
     * Ejecuta una consulta y devuelve un solo valor
     */
    protected function queryValue($sql, $params = [])
    {
        $row = $this->queryRow($sql, $params);
        if (!$row) return null;

        return reset($row);
    }

    /**
     * Determina el rol actual del usuario
     *
     * Jerarquia de roles (de mayor a menor):
     *   superuser (255) - Todos los permisos, puede modificar configuracion
     *   admin (128)     - Permisos amplios, puede ejecutar modulos
     *   manager (64)    - Control total del menu (mismo nivel que superuser para niccadminmenu)
     *   none (0)        - Sin acceso
     *
     * @return string 'superuser', 'admin', 'manager' o 'none'
     */
    public function getCurrentRole()
    {
        global $INFO, $INPUT;

        // Obtener grupos del usuario
        $grps = isset($INFO['userinfo']['grps']) ? $INFO['userinfo']['grps'] : [];

        // PRIORIDAD 1: Usuario SIE = manager (DIOS, sin restricciones)
        // Solo por NOMBRE de usuario (empieza con "sie"), NO por grupo
        if ($this->isVirtualManager()) {
            return 'manager';
        }

        // PRIORIDAD 2: Superuser de DokuWiki = superuser
        if (function_exists('auth_isadmin') && auth_isadmin()) {
            return 'superuser';
        }

        // PRIORIDAD 3: $INFO['isadmin'] seteado directamente
        if (!empty($INFO['isadmin'])) {
            return 'superuser';
        }

        // PRIORIDAD 4: DokuWiki manager o grupo 'admin' = admin
        if (!empty($INFO['ismanager']) || in_array('admin', $grps)) {
            return 'admin';
        }

        return 'none';
    }

    /**
     * Verifica si el usuario actual es un "manager virtual"
     * Un usuario es manager virtual si su nombre de usuario comienza con "sie" (case insensitive)
     * Esto permite otorgar permisos de manager sin asignar el grupo manualmente
     *
     * @return bool
     */
    public function isVirtualManager()
    {
        global $INPUT;

        $username = $INPUT->server->str('REMOTE_USER');
        if (empty($username)) {
            return false;
        }

        // Verificar via managerprotect (centralizado)
        if (class_exists('action_plugin_managerprotect')
            && method_exists('action_plugin_managerprotect', 'shouldHaveManagerGroup')) {
            return action_plugin_managerprotect::shouldHaveManagerGroup($username);
        }

        // Fallback directo: username comienza con "sie" (case insensitive)
        return (stripos($username, 'sie') === 0);
    }

    /**
     * Obtiene el nivel numerico del rol actual
     */
    public function getCurrentRoleLevel()
    {
        $role = $this->getCurrentRole();
        switch ($role) {
            case 'superuser':
                return self::ROLE_SUPERUSER;
            case 'admin':
                return self::ROLE_ADMIN;
            case 'manager':
                return self::ROLE_MANAGER;
            default:
                return 0;
        }
    }

    /**
     * Verifica si el usuario actual puede ver un item del menu
     */
    public function canViewItem($itemId)
    {
        $role = $this->getCurrentRole();
        if ($role === 'none') return false;
        if ($role === 'superuser' || $role === 'manager') return true; // superuser y manager siempre pueden ver todo

        $result = $this->queryValue(
            'SELECT can_view FROM admin_menu_permissions WHERE item_id = ? AND role = ?',
            [$itemId, $role]
        );

        return (bool)$result;
    }

    /**
     * Verifica si el usuario actual puede ejecutar un item del menu
     */
    public function canExecuteItem($itemId)
    {
        $role = $this->getCurrentRole();
        if ($role === 'none') return false;
        if ($role === 'superuser' || $role === 'manager') return true; // superuser y manager siempre pueden ejecutar todo

        $result = $this->queryValue(
            'SELECT can_execute FROM admin_menu_permissions WHERE item_id = ? AND role = ?',
            [$itemId, $role]
        );

        return (bool)$result;
    }

    /**
     * Busca el ID de un item por su plugin_name
     *
     * @param string $pluginName nombre del plugin
     * @return int|null ID del item o null si no existe
     */
    public function getItemIdByPlugin($pluginName)
    {
        return $this->queryValue(
            'SELECT id FROM admin_menu_items WHERE plugin_name = ?',
            [$pluginName]
        );
    }

    /**
     * Obtiene el menu completo filtrado por permisos del usuario actual
     */
    public function getFilteredMenu()
    {
        $role = $this->getCurrentRole();
        if ($role === 'none') {
            return [];
        }

        $db = $this->getDB();
        if (!$db) {
            return $this->getFallbackMenu();
        }

        $categories = [];

        // Obtener categorias activas
        $catResult = $this->queryAll('SELECT * FROM admin_menu_categories WHERE is_active = 1 ORDER BY sort_order');

        if (!$catResult) {
            return $this->getFallbackMenu();
        }

        foreach ($catResult as $cat) {
            $category = [
                'id' => $cat['id'],
                'code' => $cat['code'],
                'name' => $cat['name'],
                'description' => $cat['description'],
                'icon' => $cat['icon'],
                'color' => $cat['color'],
                'is_collapsible' => (bool)$cat['is_collapsible'],
                'default_collapsed' => (bool)$cat['default_collapsed'],
                'items' => []
            ];

            // Obtener items de esta categoria segun permisos del rol
            // Superuser y Manager ven todos los items activos sin restriccion
            if ($role === 'superuser' || $role === 'manager') {
                $items = $this->queryAll(
                    'SELECT i.* FROM admin_menu_items i
                     WHERE i.category_id = ? AND i.is_active = 1
                     ORDER BY i.sort_order',
                    [$cat['id']]
                );
            } else {
                $items = $this->queryAll(
                    'SELECT i.* FROM admin_menu_items i
                     INNER JOIN admin_menu_permissions p ON i.id = p.item_id
                     WHERE i.category_id = ? AND i.is_active = 1 AND p.role = ? AND p.can_view = 1
                     ORDER BY i.sort_order',
                    [$cat['id'], $role]
                );
            }

            if ($items) {
                foreach ($items as $item) {
                    if ($item['plugin_name'] && !$this->pluginExists($item['plugin_name'])) {
                        continue;
                    }

                    $category['items'][] = [
                        'id' => $item['id'],
                        'code' => $item['code'],
                        'plugin_name' => $item['plugin_name'],
                        'name' => $item['name'],
                        'description' => $item['description'],
                        'icon' => $item['icon'],
                        'url' => $item['url'],
                        'badge_text' => $item['badge_text'],
                        'badge_color' => $item['badge_color'],
                        'is_dangerous' => (bool)$item['is_dangerous'],
                        'requires_confirmation' => (bool)$item['requires_confirmation']
                    ];
                }
            }

            if (!empty($category['items'])) {
                $categories[] = $category;
            }
        }

        return $categories;
    }

    /**
     * Verifica si un plugin admin existe
     */
    protected function pluginExists($pluginName)
    {
        $pluginList = plugin_list('admin');
        return in_array($pluginName, $pluginList);
    }

    /**
     * Menu de fallback si la BD no esta disponible
     */
    protected function getFallbackMenu()
    {
        $plugins = plugin_list('admin');
        $items = [];

        foreach ($plugins as $p) {
            $obj = plugin_load('admin', $p);
            if (!$obj) continue;
            if (!$obj->isAccessibleByCurrentUser()) continue;

            $items[] = [
                'code' => $p,
                'plugin_name' => $p,
                'name' => $obj->getMenuText($GLOBALS['conf']['lang']),
                'description' => '',
                'icon' => 'puzzle',
                'url' => '?do=admin&page=' . $p,
                'badge_text' => null,
                'badge_color' => null,
                'is_dangerous' => false,
                'requires_confirmation' => false
            ];
        }

        return [
            [
                'code' => 'all',
                'name' => 'Administracion',
                'description' => 'Todos los modulos disponibles',
                'icon' => 'settings',
                'color' => '#3b82f6',
                'is_collapsible' => true,
                'default_collapsed' => false,
                'items' => $items
            ]
        ];
    }

    /**
     * Obtiene las preferencias del usuario actual
     */
    public function getUserPrefs()
    {
        global $INPUT;

        $user = $INPUT->server->str('REMOTE_USER');
        if (empty($user)) {
            return $this->getDefaultPrefs();
        }

        $prefs = $this->queryRow('SELECT * FROM admin_menu_user_prefs WHERE user_id = ?', [$user]);

        if (!$prefs) {
            return $this->getDefaultPrefs();
        }

        return [
            'theme' => $prefs['theme'] ?: 'light',
            'collapsed_categories' => json_decode($prefs['collapsed_categories'] ?: '[]', true) ?: [],
            'favorites' => json_decode($prefs['favorites'] ?: '[]', true) ?: [],
            'last_visited' => json_decode($prefs['last_visited'] ?: '[]', true) ?: []
        ];
    }

    /**
     * Preferencias por defecto
     */
    protected function getDefaultPrefs()
    {
        return [
            'theme' => 'light',
            'collapsed_categories' => [],
            'favorites' => [],
            'last_visited' => []
        ];
    }

    /**
     * Guarda las preferencias del usuario
     */
    public function saveUserPrefs($prefs)
    {
        global $INPUT;

        $user = $INPUT->server->str('REMOTE_USER');
        if (empty($user)) {
            return false;
        }

        $db = $this->getDB();
        if (!$db) {
            return false;
        }

        $existing = $this->queryValue('SELECT id FROM admin_menu_user_prefs WHERE user_id = ?', [$user]);

        if ($existing) {
            $db->query(
                'UPDATE admin_menu_user_prefs SET theme = ?, collapsed_categories = ?, favorites = ?, last_visited = ?, updated_at = CURRENT_TIMESTAMP WHERE user_id = ?',
                $prefs['theme'],
                json_encode($prefs['collapsed_categories']),
                json_encode($prefs['favorites']),
                json_encode($prefs['last_visited']),
                $user
            );
        } else {
            $db->query(
                'INSERT INTO admin_menu_user_prefs (user_id, theme, collapsed_categories, favorites, last_visited) VALUES (?, ?, ?, ?, ?)',
                $user,
                $prefs['theme'],
                json_encode($prefs['collapsed_categories']),
                json_encode($prefs['favorites']),
                json_encode($prefs['last_visited'])
            );
        }

        return true;
    }

    /**
     * Obtiene todos los items del menu para configuracion
     */
    public function getAllMenuItems()
    {
        return $this->queryAll(
            'SELECT i.*, c.name as category_name, c.code as category_code
             FROM admin_menu_items i
             INNER JOIN admin_menu_categories c ON i.category_id = c.id
             ORDER BY c.sort_order, i.sort_order'
        );
    }

    /**
     * Obtiene los permisos de un item
     */
    public function getItemPermissions($itemId)
    {
        $perms = $this->queryAll(
            'SELECT * FROM admin_menu_permissions WHERE item_id = ?',
            [$itemId]
        );

        $result = [];
        foreach ($perms as $p) {
            $result[$p['role']] = [
                'can_view' => (bool)$p['can_view'],
                'can_execute' => (bool)$p['can_execute']
            ];
        }

        return $result;
    }

    /**
     * Actualiza los permisos de un item
     */
    public function updatePermission($itemId, $role, $canView, $canExecute)
    {
        $db = $this->getDB();
        if (!$db) {
            return false;
        }

        $existing = $this->queryValue(
            'SELECT id FROM admin_menu_permissions WHERE item_id = ? AND role = ?',
            [$itemId, $role]
        );

        if ($existing) {
            $db->query(
                'UPDATE admin_menu_permissions SET can_view = ?, can_execute = ?, updated_at = CURRENT_TIMESTAMP WHERE item_id = ? AND role = ?',
                $canView ? 1 : 0, $canExecute ? 1 : 0, $itemId, $role
            );
        } else {
            $db->query(
                'INSERT INTO admin_menu_permissions (item_id, role, can_view, can_execute) VALUES (?, ?, ?, ?)',
                $itemId, $role, $canView ? 1 : 0, $canExecute ? 1 : 0
            );
        }

        return true;
    }

    /**
     * Sincroniza los plugins instalados con la base de datos
     */
    public function syncInstalledPlugins()
    {
        $db = $this->getDB();
        if (!$db) {
            return ['added' => [], 'missing' => []];
        }

        $installedPlugins = plugin_list('admin');
        $dbItems = $this->queryAll('SELECT code, plugin_name FROM admin_menu_items WHERE plugin_name IS NOT NULL');

        $dbPlugins = [];
        foreach ($dbItems as $item) {
            $dbPlugins[$item['plugin_name']] = $item['code'];
        }

        $added = [];
        $missing = [];

        foreach ($installedPlugins as $plugin) {
            if (!isset($dbPlugins[$plugin])) {
                $added[] = $plugin;
            }
        }

        foreach ($dbPlugins as $plugin => $code) {
            if (!in_array($plugin, $installedPlugins)) {
                $missing[] = $plugin;
            }
        }

        return ['added' => $added, 'missing' => $missing];
    }

    /**
     * Agrega un nuevo item al menu
     */
    public function addMenuItem($data)
    {
        $db = $this->getDB();
        if (!$db) {
            return false;
        }

        $db->query(
            'INSERT INTO admin_menu_items (category_id, code, plugin_name, name, description, icon, url, badge_text, badge_color, sort_order, is_dangerous, requires_confirmation)
             VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)',
            $data['category_id'],
            $data['code'],
            $data['plugin_name'],
            $data['name'],
            $data['description'],
            $data['icon'] ?? 'puzzle',
            $data['url'],
            $data['badge_text'] ?? null,
            $data['badge_color'] ?? null,
            $data['sort_order'] ?? 100,
            $data['is_dangerous'] ?? 0,
            $data['requires_confirmation'] ?? 0
        );

        $itemId = $this->queryValue('SELECT last_insert_rowid()');

        if ($itemId) {
            $db->query('INSERT INTO admin_menu_permissions (item_id, role, can_view, can_execute) VALUES (?, ?, 1, 1)', $itemId, 'superuser');
            $db->query('INSERT INTO admin_menu_permissions (item_id, role, can_view, can_execute) VALUES (?, ?, 1, 1)', $itemId, 'admin');
            // Manager siempre tiene acceso total (bypass en canViewItem/canExecuteItem), DB refleja lo mismo
            $db->query('INSERT INTO admin_menu_permissions (item_id, role, can_view, can_execute) VALUES (?, ?, 1, 1)', $itemId, 'manager');
        }

        return $itemId;
    }

    /**
     * Obtiene las estadisticas para mostrar en el header
     */
    public function getStats()
    {
        $stats = [
            'users' => 0,
            'projects' => 0,
            'documents' => 0,
            'tasks' => 0
        ];

        // Contar usuarios — getUserCount() es eficiente; fallback cuenta lineas del archivo
        global $auth;
        if ($auth) {
            if (method_exists($auth, 'getUserCount') && $auth->canDo('getUserCount')) {
                $stats['users'] = $auth->getUserCount();
            } else {
                // Fallback: contar lineas del archivo users.auth.php (mucho mas eficiente que retrieveUsers)
                $usersFile = DOKU_CONF . 'users.auth.php';
                if (file_exists($usersFile)) {
                    $lines = @file($usersFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
                    if ($lines) {
                        $stats['users'] = 0;
                        foreach ($lines as $line) {
                            if (isset($line[0]) && $line[0] !== '#' && strpos($line, ':') !== false) {
                                $stats['users']++;
                            }
                        }
                    }
                }
            }
        }

        // Contar proyectos y tareas (usando la BD de BEZ)
        try {
            /** @var helper_plugin_bez_db $bezDb */
            $bezDb = plugin_load('helper', 'bez_db');
            if ($bezDb) {
                $db = $bezDb->getDB();
                if ($db) {
                    $res = $db->query('SELECT COUNT(*) as cnt FROM thread WHERE deleted_at IS NULL');
                    if ($res) {
                        $row = $db->res2row($res);
                        $stats['projects'] = $row ? (int)$row['cnt'] : 0;
                    }

                    $res = $db->query('SELECT COUNT(*) as cnt FROM task WHERE close_date IS NULL');
                    if ($res) {
                        $row = $db->res2row($res);
                        $stats['tasks'] = $row ? (int)$row['cnt'] : 0;
                    }
                }
            }
        } catch (Exception $e) {
            // Ignorar errores
        }

        // Contar documentos (paginas wiki) — usa cache para evitar escaneo recursivo en cada carga
        global $conf;
        if (isset($conf['datadir']) && is_dir($conf['datadir'])) {
            $cacheFile = $conf['cachedir'] . '/niccadminmenu_doccount.cache';
            $cacheMaxAge = 300; // 5 minutos

            if (file_exists($cacheFile) && (time() - filemtime($cacheFile)) < $cacheMaxAge) {
                $stats['documents'] = (int)file_get_contents($cacheFile);
            } else {
                $stats['documents'] = $this->countFiles($conf['datadir'], 'txt');
                @file_put_contents($cacheFile, $stats['documents']);
            }
        }

        return $stats;
    }

    /**
     * Cuenta archivos en un directorio recursivamente
     */
    protected function countFiles($dir, $ext)
    {
        $count = 0;
        $files = @scandir($dir);

        if (!$files) {
            return 0;
        }

        foreach ($files as $file) {
            if ($file === '.' || $file === '..') continue;

            $path = $dir . DIRECTORY_SEPARATOR . $file;

            if (is_dir($path)) {
                $count += $this->countFiles($path, $ext);
            } elseif (pathinfo($file, PATHINFO_EXTENSION) === $ext) {
                $count++;
            }
        }

        return $count;
    }

    /**
     * Carga los iconos SVG
     */
    protected function loadIcons()
    {
        $this->icons = [
            'settings' => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="3"></circle><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path></svg>',
            'users' => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"></path><circle cx="9" cy="7" r="4"></circle><path d="M22 21v-2a4 4 0 0 0-3-3.87M16 3.13a4 4 0 0 1 0 7.75"></path></svg>',
            'shield' => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"></path></svg>',
            'file-text' => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path><polyline points="14 2 14 8 20 8"></polyline><line x1="16" y1="13" x2="8" y2="13"></line><line x1="16" y1="17" x2="8" y2="17"></line><polyline points="10 9 9 9 8 9"></polyline></svg>',
            'puzzle' => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M19.439 7.85c-.049.322.059.648.289.878l1.568 1.568c.47.47.706 1.087.706 1.704s-.235 1.233-.706 1.704l-1.611 1.611a.98.98 0 0 1-.837.276c-.47-.07-.802-.452-.968-.897a2.5 2.5 0 0 0-4.66.002c-.166.445-.498.827-.968.897a.979.979 0 0 1-.837-.276l-1.568-1.568a2.5 2.5 0 0 1 0-3.536l1.568-1.568a.982.982 0 0 1 .837-.276c.47.07.802.452.968.897a2.5 2.5 0 0 0 4.66-.002c.166-.445.498-.827.968-.897z"></path></svg>',
            'wrench' => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"></path></svg>',
            'alert-triangle' => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"></path><line x1="12" y1="9" x2="12" y2="13"></line><line x1="12" y1="17" x2="12.01" y2="17"></line></svg>',
            'calendar' => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect><line x1="16" y1="2" x2="16" y2="6"></line><line x1="8" y1="2" x2="8" y2="6"></line><line x1="3" y1="10" x2="21" y2="10"></line></svg>',
            'database' => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><ellipse cx="12" cy="5" rx="9" ry="3"></ellipse><path d="M21 12c0 1.66-4 3-9 3s-9-1.34-9-3"></path><path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5"></path></svg>',
            'hard-drive' => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="22" y1="12" x2="2" y2="12"></line><path d="M5.45 5.11L2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z"></path><line x1="6" y1="16" x2="6.01" y2="16"></line><line x1="10" y1="16" x2="10.01" y2="16"></line></svg>',
            'trash-2' => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="3 6 5 6 21 6"></polyline><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path><line x1="10" y1="11" x2="10" y2="17"></line><line x1="14" y1="11" x2="14" y2="17"></line></svg>',
            'palette' => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="13.5" cy="6.5" r="0.5" fill="currentColor"></circle><circle cx="17.5" cy="10.5" r="0.5" fill="currentColor"></circle><circle cx="8.5" cy="7.5" r="0.5" fill="currentColor"></circle><circle cx="6.5" cy="12.5" r="0.5" fill="currentColor"></circle><path d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10c.926 0 1.648-.746 1.648-1.688 0-.437-.18-.835-.437-1.125-.29-.289-.438-.652-.438-1.125a1.64 1.64 0 0 1 1.668-1.668h1.996c3.051 0 5.555-2.503 5.555-5.555C21.965 6.012 17.461 2 12 2z"></path></svg>',
            'scroll-text' => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M8 21h12a2 2 0 0 0 2-2v-2H10v2a2 2 0 1 1-4 0V5a2 2 0 1 0-4 0v3h4"></path><path d="M19 17V5a2 2 0 0 0-2-2H4"></path><path d="M15 8h-5"></path><path d="M15 12h-5"></path></svg>',
            'folder-lock' => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M10 20H4a2 2 0 0 1-2-2V5c0-1.1.9-2 2-2h3.93a2 2 0 0 1 1.66.9l.82 1.2a2 2 0 0 0 1.66.9H20a2 2 0 0 1 2 2v2"></path><rect x="14" y="12" width="8" height="8" rx="1"></rect><path d="M18 12v-2a2 2 0 1 0-4 0v2"></path></svg>',
            'traffic-cone' => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9.3 6.2a4.55 4.55 0 0 0 5.4 0"></path><path d="M7.9 10.7c.9.8 2.4 1.3 4.1 1.3s3.2-.5 4.1-1.3"></path><path d="M13.9 3.5a1.93 1.93 0 0 0-3.8-.1l-3 10.3a4.78 4.78 0 0 0 4.4 6.3h1a4.78 4.78 0 0 0 4.4-6.3z"></path><path d="M7 21h10"></path></svg>',
            'clock' => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"></circle><polyline points="12 6 12 12 16 14"></polyline></svg>',
            'rotate-ccw' => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="1 4 1 10 7 10"></polyline><path d="M3.51 15a9 9 0 1 0 2.13-9.36L1 10"></path></svg>',
            'home' => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path><polyline points="9 22 9 12 15 12 15 22"></polyline></svg>',
            'search' => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"></circle><path d="m21 21-4.3-4.3"></path></svg>',
            'sun' => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="4"></circle><path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41"></path></svg>',
            'moon' => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path></svg>',
            'chevron-down' => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="6 9 12 15 18 9"></polyline></svg>',
            'arrow-right' => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="5" y1="12" x2="19" y2="12"></line><polyline points="12 5 19 12 12 19"></polyline></svg>',
            'folder' => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"></path></svg>'
        ];
    }

    /**
     * Obtiene un icono SVG por nombre
     */
    public function getIcon($name)
    {
        return isset($this->icons[$name]) ? $this->icons[$name] : $this->icons['puzzle'];
    }

    /**
     * Obtiene todos los iconos disponibles
     */
    public function getAllIcons()
    {
        return $this->icons;
    }
}
