<?php
/**
 * DokuWiki Plugin niccadminmenu (Action Component)
 *
 * Intercepta la accion admin y muestra el nuevo menu moderno
 *
 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
 */

use dokuwiki\Extension\ActionPlugin;
use dokuwiki\Extension\EventHandler;
use dokuwiki\Extension\Event;

class action_plugin_niccadminmenu extends ActionPlugin
{
    /** @var helper_plugin_niccadminmenu */
    protected $helper;

    /**
     * Constructor
     */
    public function __construct()
    {
        $this->helper = plugin_load('helper', 'niccadminmenu');
    }

    /**
     * Registrar eventos
     */
    public function register(EventHandler $controller)
    {
        // Inyectar permisos de manager para usuarios SIE antes del procesamiento de acciones
        // Esto permite que usuarios SIE accedan a ?do=admin cuando $conf['superuser'] != '@sie'
        $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'handleActPreprocess', []);

        // Interceptar el renderizado del contenido admin
        $controller->register_hook('TPL_ACT_RENDER', 'BEFORE', $this, 'handleAdminRender', []);

        // Agregar CSS/JS al header
        $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'addHeaderAssets', []);

        // Nota: el detector de uploads grandes esta en script.js (se carga automaticamente)

        // Manejar peticiones AJAX
        $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'handleAjax', []);

        // Interceptar verificacion de acceso a plugins admin
        // Permite que usuarios con rol niccadminmenu (manager/admin/superuser) accedan
        $controller->register_hook('ADMINPLUGIN_ACCESS_CHECK', 'AFTER', $this, 'handleAccessCheck', []);
    }

    /**
     * Inyecta $INFO['ismanager'] para usuarios SIE que no son superuser de DokuWiki.
     * Cuando $conf['superuser'] = '@admin' (no '@sie'), los usuarios SIE pierden
     * el flag isadmin/ismanager de DokuWiki. Este handler lo restaura para que
     * DokuWiki permita acceso a ?do=admin.
     *
     * NOTA: ACTION_ACT_PREPROCESS se dispara muy temprano. $INFO puede no estar
     * poblado aun, por eso usamos auth_isadmin()/auth_ismanager() (que funcionan
     * independientemente de $INFO) y leemos el username directamente de $_SERVER.
     */
    public function handleActPreprocess(Event $event, $param)
    {
        global $INFO;

        // Solo actuar si el usuario intenta acceder al admin
        if ($event->data !== 'admin') {
            return;
        }

        // Si ya es admin o manager en DokuWiki nativo, no hacer nada
        // Usamos las funciones auth_* que NO dependen de $INFO
        if (function_exists('auth_isadmin') && auth_isadmin()) {
            return;
        }
        if (function_exists('auth_ismanager') && auth_ismanager()) {
            return;
        }

        // Obtener username directamente (no depende de $INFO)
        $username = isset($_SERVER['REMOTE_USER']) ? $_SERVER['REMOTE_USER'] : '';
        if (empty($username)) {
            return;
        }

        // Verificar si es un usuario SIE (virtual manager)
        $isSie = false;

        // Intentar via managerprotect (centralizado)
        if (class_exists('action_plugin_managerprotect')
            && method_exists('action_plugin_managerprotect', 'shouldHaveManagerGroup')) {
            $isSie = action_plugin_managerprotect::shouldHaveManagerGroup($username);
        } else {
            // Fallback: username comienza con "sie" (case insensitive)
            $isSie = (stripos($username, 'sie') === 0);
        }

        // Verificar si es usuario del grupo 'admin' (via auth backend)
        $isAdminGroup = false;
        if (!$isSie) {
            global $auth;
            if ($auth) {
                $userd = $auth->getUserData($username);
                if ($userd && isset($userd['grps']) && is_array($userd['grps'])) {
                    $isAdminGroup = in_array('admin', $userd['grps']);
                }
            }
        }

        // Inyectar ismanager para usuarios SIE o grupo admin
        if ($isSie || $isAdminGroup) {
            if (!is_array($INFO)) {
                $INFO = [];
            }
            $INFO['ismanager'] = true;
        }
    }

    /**
     * Otorga acceso a plugins admin segun el sistema de roles de niccadminmenu
     * Resuelve el error "For admins only" para usuarios con roles validos
     */
    public function handleAccessCheck(Event $event, $param)
    {
        // Si ya tiene acceso, no hacer nada
        if ($event->data['hasAccess']) {
            return;
        }

        // Verificar si el usuario tiene un rol valido en niccadminmenu
        if (!$this->helper) {
            $this->helper = plugin_load('helper', 'niccadminmenu');
        }
        if (!$this->helper) {
            return;
        }

        $role = $this->helper->getCurrentRole();
        if ($role === 'none') {
            return;
        }

        // Superuser y manager tienen acceso total
        if ($role === 'superuser' || $role === 'manager') {
            $event->data['hasAccess'] = true;
            return;
        }

        // Admin: verificar permisos especificos del item si es posible
        if ($role === 'admin' && isset($event->data['instance']) && is_object($event->data['instance'])) {
            $pluginName = $event->data['instance']->getPluginName();
            $itemId = $this->helper->getItemIdByPlugin($pluginName);
            if ($itemId && $this->helper->canExecuteItem($itemId)) {
                $event->data['hasAccess'] = true;
            } elseif (!$itemId) {
                // Plugin no registrado en niccadminmenu, otorgar acceso a admins
                $event->data['hasAccess'] = true;
            }
        }
    }

    /**
     * Intercepta el renderizado de la pagina admin
     */
    public function handleAdminRender(Event $event, $param)
    {
        global $ACT, $INPUT;

        // Solo interceptar cuando es admin sin pagina especifica
        if ($ACT !== 'admin') {
            return;
        }

        // Si hay una pagina especifica, dejar que DokuWiki la maneje
        $page = $INPUT->str('page', '');
        if (!empty($page)) {
            return;
        }

        // Verificar acceso usando el sistema centralizado de roles
        if (!$this->helper) {
            $this->helper = plugin_load('helper', 'niccadminmenu');
        }
        if (!$this->helper) {
            return;
        }

        $role = $this->helper->getCurrentRole();
        if ($role === 'none') {
            return;
        }

        // Prevenir el renderizado por defecto
        $event->preventDefault();

        // Renderizar nuestro menu personalizado
        $this->renderAdminMenu();
    }

    /**
     * Renderiza el menu de administracion moderno
     */
    protected function renderAdminMenu()
    {
        global $INFO, $INPUT, $conf;

        $role = $this->helper->getCurrentRole();
        $menu = $this->helper->getFilteredMenu();
        $prefs = $this->helper->getUserPrefs();
        $stats = $this->helper->getStats();

        $user = $INPUT->server->str('REMOTE_USER');
        $userName = isset($INFO['userinfo']['name']) ? $INFO['userinfo']['name'] : $user;

        $roleLabels = [
            'superuser' => 'Superusuario',
            'admin' => 'Administrador',
            'manager' => 'Manager'
        ];
        $roleLabel = isset($roleLabels[$role]) ? $roleLabels[$role] : $role;

        // Superuser y manager (SIE) pueden configurar el menu
        $canConfigure = ($role === 'superuser' || $role === 'manager');

        ?>
        <div class="nicc-admin-container" data-theme="<?php echo hsc($prefs['theme']); ?>">
            <!-- Header -->
            <header class="nicc-admin-header">
                <div class="header-left">
                    <div class="logo">
                        <?php echo $this->helper->getIcon('home'); ?>
                        <span class="logo-text">NICC <span class="logo-admin">Admin</span></span>
                    </div>
                </div>

                <div class="header-center">
                    <div class="search-box">
                        <?php echo $this->helper->getIcon('search'); ?>
                        <input type="text" id="nicc-admin-search" placeholder="Buscar modulo..." autocomplete="off">
                        <kbd class="search-shortcut">Ctrl+K</kbd>
                    </div>
                </div>

                <div class="header-right">
                    <div class="user-info">
                        <span class="user-role" data-role="<?php echo hsc($role); ?>"><?php echo hsc($roleLabel); ?></span>
                        <span class="user-name"><?php echo hsc($userName); ?></span>
                    </div>
                    <?php if ($canConfigure): ?>
                    <button class="btn-icon" id="btn-settings" title="Configurar menu">
                        <?php echo $this->helper->getIcon('settings'); ?>
                    </button>
                    <?php endif; ?>
                    <button class="btn-icon" id="btn-theme" title="Cambiar tema">
                        <span class="icon-sun"><?php echo $this->helper->getIcon('sun'); ?></span>
                        <span class="icon-moon"><?php echo $this->helper->getIcon('moon'); ?></span>
                    </button>
                </div>
            </header>

            <!-- Main Content -->
            <main class="nicc-admin-main">
                <!-- Quick Stats -->
                <section class="quick-stats">
                    <div class="stat-card" style="--accent: #8b5cf6;">
                        <div class="stat-icon">
                            <?php echo $this->helper->getIcon('users'); ?>
                        </div>
                        <div class="stat-content">
                            <span class="stat-value"><?php echo number_format($stats['users']); ?></span>
                            <span class="stat-label">Usuarios activos</span>
                        </div>
                    </div>
                    <div class="stat-card" style="--accent: #10b981;">
                        <div class="stat-icon">
                            <?php echo $this->helper->getIcon('folder'); ?>
                        </div>
                        <div class="stat-content">
                            <span class="stat-value"><?php echo number_format($stats['projects']); ?></span>
                            <span class="stat-label">Proyectos</span>
                        </div>
                    </div>
                    <div class="stat-card" style="--accent: #f59e0b;">
                        <div class="stat-icon">
                            <?php echo $this->helper->getIcon('file-text'); ?>
                        </div>
                        <div class="stat-content">
                            <span class="stat-value"><?php echo number_format($stats['documents']); ?></span>
                            <span class="stat-label">Documentos</span>
                        </div>
                    </div>
                    <div class="stat-card" style="--accent: #ec4899;">
                        <div class="stat-icon">
                            <?php echo $this->helper->getIcon('clock'); ?>
                        </div>
                        <div class="stat-content">
                            <span class="stat-value"><?php echo number_format($stats['tasks']); ?></span>
                            <span class="stat-label">Tareas pendientes</span>
                        </div>
                    </div>
                </section>

                <!-- Menu Categories -->
                <div class="menu-categories" id="menu-categories">
                    <?php foreach ($menu as $category): ?>
                    <?php
                        $isCollapsed = in_array($category['code'], $prefs['collapsed_categories']);
                        $collapsedClass = $isCollapsed ? 'collapsed' : '';
                    ?>
                    <div class="category <?php echo $collapsedClass; ?>"
                         data-category="<?php echo hsc($category['code']); ?>"
                         style="--category-color: <?php echo hsc($category['color']); ?>">
                        <div class="category-header">
                            <div class="category-title">
                                <div class="category-icon">
                                    <?php echo $this->helper->getIcon($category['icon']); ?>
                                </div>
                                <span class="category-name"><?php echo hsc($category['name']); ?></span>
                                <span class="category-count"><?php echo count($category['items']); ?> modulos</span>
                            </div>
                            <div class="category-toggle">
                                <?php echo $this->helper->getIcon('chevron-down'); ?>
                            </div>
                        </div>
                        <div class="category-content">
                            <?php foreach ($category['items'] as $item): ?>
                            <?php
                                $dangerousClass = $item['is_dangerous'] ? 'is-dangerous' : '';
                                $itemColor = $item['is_dangerous'] ? '#ef4444' : $category['color'];
                            ?>
                            <a href="<?php echo hsc($item['url']); ?>"
                               class="menu-item <?php echo $dangerousClass; ?>"
                               style="--item-color: <?php echo hsc($itemColor); ?>"
                               data-code="<?php echo hsc($item['code']); ?>">
                                <div class="menu-item-header">
                                    <div class="menu-item-icon">
                                        <?php echo $this->helper->getIcon($item['icon']); ?>
                                    </div>
                                    <?php if ($item['badge_text']): ?>
                                    <span class="menu-item-badge" style="--badge-color: <?php echo hsc($item['badge_color'] ?: '#10b981'); ?>">
                                        <?php echo hsc($item['badge_text']); ?>
                                    </span>
                                    <?php endif; ?>
                                </div>
                                <span class="menu-item-name"><?php echo hsc($item['name']); ?></span>
                                <span class="menu-item-description"><?php echo hsc($item['description']); ?></span>
                                <div class="menu-item-arrow">
                                    <?php echo $this->helper->getIcon('arrow-right'); ?>
                                </div>
                            </a>
                            <?php endforeach; ?>
                        </div>
                    </div>
                    <?php endforeach; ?>
                </div>
            </main>

            <!-- Footer -->
            <footer class="nicc-admin-footer">
                <div class="footer-left">
                    <span>NICC v8.0</span>
                </div>
                <div class="footer-right">
                    <?php if ($canConfigure): ?>
                    <a href="?do=admin&page=niccadminmenu" class="footer-link" id="btn-config-menu">
                        <?php echo $this->helper->getIcon('settings'); ?>
                        Configurar Menu
                    </a>
                    <?php endif; ?>
                </div>
            </footer>
        </div>

        <?php if ($canConfigure): ?>
        <!-- Modal de Configuracion -->
        <div class="modal-overlay" id="modal-permissions">
            <div class="modal">
                <div class="modal-header">
                    <h2>Configurar Permisos del Menu</h2>
                    <button class="btn-close" id="btn-close-modal">&times;</button>
                </div>
                <div class="modal-body">
                    <p>Para configurar los permisos del menu, ve a <a href="?do=admin&page=niccadminmenu">Administracion &gt; Configurar Menu NICC</a></p>
                </div>
            </div>
        </div>
        <?php endif; ?>

        <script>
        (function() {
            // Inicializar tema
            var container = document.querySelector('.nicc-admin-container');
            var savedTheme = localStorage.getItem('nicc-admin-theme');
            if (savedTheme) {
                container.setAttribute('data-theme', savedTheme);
            }

            // Toggle tema
            var btnTheme = document.getElementById('btn-theme');
            if (btnTheme) {
                btnTheme.addEventListener('click', function() {
                    var current = container.getAttribute('data-theme');
                    var newTheme = current === 'light' ? 'dark' : 'light';
                    container.setAttribute('data-theme', newTheme);
                    localStorage.setItem('nicc-admin-theme', newTheme);

                    // Guardar en servidor
                    var xhr = new XMLHttpRequest();
                    xhr.open('POST', DOKU_BASE + 'lib/exe/ajax.php', true);
                    xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
                    xhr.send('call=niccadminmenu_save_prefs&theme=' + newTheme + '&sectok=' + JSINFO.sectok);
                });
            }

            // Busqueda
            var searchInput = document.getElementById('nicc-admin-search');
            if (searchInput) {
                document.addEventListener('keydown', function(e) {
                    if ((e.ctrlKey || e.metaKey) && e.key === 'k') {
                        e.preventDefault();
                        searchInput.focus();
                    }
                    if (e.key === 'Escape') {
                        searchInput.blur();
                        searchInput.value = '';
                        filterMenuItems('');
                    }
                });

                searchInput.addEventListener('input', function(e) {
                    filterMenuItems(e.target.value);
                });
            }

            function filterMenuItems(query) {
                var items = document.querySelectorAll('.menu-item');
                var categories = document.querySelectorAll('.category');
                var normalizedQuery = query.toLowerCase().trim();

                if (!normalizedQuery) {
                    items.forEach(function(item) { item.style.display = ''; });
                    categories.forEach(function(cat) {
                        cat.style.display = '';
                    });
                    return;
                }

                categories.forEach(function(category) {
                    var categoryItems = category.querySelectorAll('.menu-item');
                    var hasVisibleItems = false;

                    categoryItems.forEach(function(item) {
                        var name = item.querySelector('.menu-item-name').textContent.toLowerCase();
                        var desc = item.querySelector('.menu-item-description').textContent.toLowerCase();
                        var matches = name.indexOf(normalizedQuery) !== -1 || desc.indexOf(normalizedQuery) !== -1;

                        item.style.display = matches ? '' : 'none';
                        if (matches) hasVisibleItems = true;
                    });

                    category.style.display = hasVisibleItems ? '' : 'none';
                    if (hasVisibleItems) category.classList.remove('collapsed');
                });
            }

            // Colapsar categorias
            document.querySelectorAll('.category-header').forEach(function(header) {
                header.addEventListener('click', function() {
                    var category = header.closest('.category');
                    category.classList.toggle('collapsed');
                    saveCollapsedState();
                });
            });

            function saveCollapsedState() {
                var collapsed = [];
                document.querySelectorAll('.category.collapsed').forEach(function(cat) {
                    collapsed.push(cat.dataset.category);
                });
                localStorage.setItem('nicc-admin-collapsed', JSON.stringify(collapsed));

                // Guardar en servidor
                var xhr = new XMLHttpRequest();
                xhr.open('POST', DOKU_BASE + 'lib/exe/ajax.php', true);
                xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
                xhr.send('call=niccadminmenu_save_prefs&collapsed=' + encodeURIComponent(JSON.stringify(collapsed)) + '&sectok=' + JSINFO.sectok);
            }

            // Modal
            var modal = document.getElementById('modal-permissions');
            var btnSettings = document.getElementById('btn-settings');
            var btnClose = document.getElementById('btn-close-modal');

            if (btnSettings && modal) {
                btnSettings.addEventListener('click', function(e) {
                    e.preventDefault();
                    modal.classList.add('active');
                });
            }

            if (btnClose && modal) {
                btnClose.addEventListener('click', function() {
                    modal.classList.remove('active');
                });

                modal.addEventListener('click', function(e) {
                    if (e.target === modal) {
                        modal.classList.remove('active');
                    }
                });
            }
        })();
        </script>
        <?php
    }

    /**
     * Agrega CSS/JS al header
     */
    public function addHeaderAssets(Event $event, $param)
    {
        global $ACT, $INPUT;

        // Solo en pagina admin sin pagina especifica
        if ($ACT !== 'admin') {
            return;
        }

        $page = $INPUT->str('page', '');
        if (!empty($page)) {
            return;
        }

        // Agregar CSS
        $event->data['link'][] = [
            'type' => 'text/css',
            'rel' => 'stylesheet',
            'href' => DOKU_BASE . 'lib/plugins/niccadminmenu/style.css'
        ];

        // Agregar fuentes (carga asincrona no-bloqueante via media="print")
        $event->data['link'][] = [
            'rel' => 'preconnect',
            'href' => 'https://fonts.googleapis.com'
        ];
        $event->data['link'][] = [
            'rel' => 'preconnect',
            'href' => 'https://fonts.gstatic.com',
            'crossorigin' => 'anonymous'
        ];
        // Carga consolidada: DM Sans + Playfair Display + JetBrains Mono
        // (evita duplicados en bez/tpl y otros templates)
        $event->data['link'][] = [
            'rel'    => 'stylesheet',
            'href'   => 'https://fonts.googleapis.com/css2?family=DM+Sans:wght@300;400;500;600;700&family=Playfair+Display:wght@600;700&family=JetBrains+Mono:wght@400;500&display=swap',
            'media'  => 'print',
            'onload' => "this.media='all'"
        ];
    }

    /**
     * Maneja peticiones AJAX
     */
    public function handleAjax(Event $event, $param)
    {
        if ($event->data !== 'niccadminmenu_save_prefs') {
            return;
        }

        $event->preventDefault();
        $event->stopPropagation();

        global $INPUT;

        // Verificar token de seguridad
        if (!checkSecurityToken()) {
            header('Content-Type: application/json');
            echo json_encode(['success' => false, 'error' => 'Invalid token']);
            return;
        }

        // Verificar que el usuario tenga un rol valido
        if (!$this->helper) {
            $this->helper = plugin_load('helper', 'niccadminmenu');
        }
        if (!$this->helper) {
            header('Content-Type: application/json');
            echo json_encode(['success' => false, 'error' => 'Helper not available']);
            return;
        }
        if ($this->helper->getCurrentRole() === 'none') {
            header('Content-Type: application/json');
            echo json_encode(['success' => false, 'error' => 'No permission']);
            return;
        }

        $prefs = $this->helper->getUserPrefs();

        if ($INPUT->has('theme')) {
            $theme = $INPUT->str('theme');
            // Validar valor de tema contra whitelist
            if (in_array($theme, ['light', 'dark'], true)) {
                $prefs['theme'] = $theme;
            }
        }

        if ($INPUT->has('collapsed')) {
            $prefs['collapsed_categories'] = json_decode($INPUT->str('collapsed'), true) ?: [];
        }

        $result = $this->helper->saveUserPrefs($prefs);

        header('Content-Type: application/json');
        echo json_encode(['success' => $result]);
    }

}
