<?php
/**
 * DokuWiki Plugin niccadminmenu (Admin Component)
 *
 * Configuracion de permisos del menu de administracion
 *
 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
 */

use dokuwiki\Extension\AdminPlugin;

class admin_plugin_niccadminmenu extends AdminPlugin
{
    /** @var helper_plugin_niccadminmenu */
    protected $helper;

    /** @var string */
    protected $message = '';

    /** @var string */
    protected $messageType = '';

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

    /**
     * Orden en el menu
     */
    public function getMenuSort()
    {
        return 1;
    }

    /**
     * DokuWiki usa esto para el check por defecto (auth_isadmin).
     * El acceso para managers (SIE) se otorga via ADMINPLUGIN_ACCESS_CHECK
     * en action.php handleAccessCheck().
     */
    public function forAdminOnly()
    {
        return true;
    }

    /**
     * Texto del menu
     */
    public function getMenuText($language)
    {
        return $this->getLang('menu');
    }

    /**
     * Icono del menu
     */
    public function getMenuIcon()
    {
        return function_exists('bez_resolve_path') ? bez_resolve_path('lib/images/menu/settings.svg') : DOKU_INC . 'lib/images/menu/settings.svg';
    }

    /**
     * Manejar acciones
     */
    public function handle()
    {
        global $INPUT;

        // Verificar permiso: superuser o manager (SIE) pueden configurar
        if (!$this->helper) {
            $this->helper = plugin_load('helper', 'niccadminmenu');
        }
        $role = $this->helper ? $this->helper->getCurrentRole() : 'none';
        if ($role !== 'superuser' && $role !== 'manager') {
            return;
        }

        // Guardar permisos
        if ($INPUT->post->has('save_permissions') && checkSecurityToken()) {
            $this->savePermissions($INPUT->post->arr('perms'));
        }

        // Sincronizar plugins
        if ($INPUT->post->has('sync_plugins') && checkSecurityToken()) {
            $this->syncPlugins();
        }

        // Agregar nuevo item
        if ($INPUT->post->has('add_item') && checkSecurityToken()) {
            $this->addNewItem($INPUT->post->arr('new_item'));
        }
    }

    /**
     * Guardar permisos
     */
    protected function savePermissions($perms)
    {
        if (empty($perms)) {
            return;
        }

        $validRoles = ['superuser', 'admin', 'manager'];
        $count = 0;
        foreach ($perms as $itemId => $roles) {
            $itemId = (int)$itemId;
            if ($itemId <= 0) continue;
            foreach ($roles as $role => $permissions) {
                if (!in_array($role, $validRoles, true)) continue;
                $canView = !empty($permissions['view']) ? 1 : 0;
                $canExecute = !empty($permissions['execute']) ? 1 : 0;
                $this->helper->updatePermission($itemId, $role, $canView, $canExecute);
                $count++;
            }
        }

        $this->message = sprintf($this->getLang('permissions_saved'), $count);
        $this->messageType = 'success';
    }

    /**
     * Sincronizar plugins instalados
     */
    protected function syncPlugins()
    {
        $result = $this->helper->syncInstalledPlugins();

        $addedCount = count($result['added']);
        $missingCount = count($result['missing']);

        if ($addedCount > 0) {
            // Agregar los nuevos plugins encontrados
            $db = $this->helper->getDB();
            if ($db) {
                // Obtener categoria "otros" o crear una
                $res = $db->query("SELECT id FROM admin_menu_categories WHERE code = ?", 'tools');
                $row = $res ? $db->res2row($res) : null;
                $otherId = $row ? $row['id'] : null;

                foreach ($result['added'] as $plugin) {
                    $obj = plugin_load('admin', $plugin);
                    if ($obj) {
                        $this->helper->addMenuItem([
                            'category_id' => $otherId,
                            'code' => $plugin,
                            'plugin_name' => $plugin,
                            'name' => $obj->getMenuText($GLOBALS['conf']['lang']),
                            'description' => 'Plugin detectado automaticamente',
                            'icon' => 'puzzle',
                            'url' => '?do=admin&page=' . $plugin,
                            'sort_order' => 100
                        ]);
                    }
                }
            }
        }

        $this->message = sprintf($this->getLang('sync_complete'), $addedCount, $missingCount);
        $this->messageType = 'success';
    }

    /**
     * Agregar nuevo item
     */
    protected function addNewItem($data)
    {
        if (empty($data['code']) || empty($data['name']) || empty($data['category_id'])) {
            $this->message = $this->getLang('error_required_fields');
            $this->messageType = 'error';
            return;
        }

        // Sanitizar: code solo alfanumerico/guiones, category_id entero
        $data['code'] = preg_replace('/[^a-zA-Z0-9_\-]/', '', $data['code']);
        $data['category_id'] = (int)$data['category_id'];

        // Bloquear URLs peligrosas (javascript:, data:, vbscript:)
        if (!empty($data['url'])) {
            $urlLower = strtolower(trim($data['url']));
            if (preg_match('/^(javascript|data|vbscript)\s*:/i', $urlLower)) {
                $this->message = 'URL no permitida';
                $this->messageType = 'error';
                return;
            }
        }

        $result = $this->helper->addMenuItem($data);

        if ($result) {
            $this->message = $this->getLang('item_added');
            $this->messageType = 'success';
        } else {
            $this->message = $this->getLang('error_adding_item');
            $this->messageType = 'error';
        }
    }

    /**
     * Renderizar HTML
     */
    public function html()
    {
        global $ID;

        // Verificar permiso: superuser o manager (SIE) pueden configurar
        if (!$this->helper) {
            $this->helper = plugin_load('helper', 'niccadminmenu');
        }
        $role = $this->helper ? $this->helper->getCurrentRole() : 'none';
        if ($role !== 'superuser' && $role !== 'manager') {
            echo '<div class="error">' . $this->getLang('error_no_permission') . '</div>';
            return;
        }

        echo '<div id="niccadminmenu_config">';

        // Titulo
        echo '<h1>' . hsc($this->getLang('config_title')) . '</h1>';

        // Mensaje
        if ($this->message) {
            $class = $this->messageType === 'success' ? 'notify' : 'error';
            echo '<div class="' . $class . '"><p>' . hsc($this->message) . '</p></div>';
        }

        // Tabs
        echo '<div class="tabs">';
        echo '<ul>';
        echo '<li class="active"><a href="#tab-permissions">' . $this->getLang('tab_permissions') . '</a></li>';
        echo '<li><a href="#tab-sync">' . $this->getLang('tab_sync') . '</a></li>';
        echo '<li><a href="#tab-add">' . $this->getLang('tab_add_item') . '</a></li>';
        echo '</ul>';
        echo '</div>';

        // Tab: Permisos
        echo '<div id="tab-permissions" class="tab-content active">';
        $this->renderPermissionsTable();
        echo '</div>';

        // Tab: Sincronizar
        echo '<div id="tab-sync" class="tab-content">';
        $this->renderSyncForm();
        echo '</div>';

        // Tab: Agregar item
        echo '<div id="tab-add" class="tab-content">';
        $this->renderAddItemForm();
        echo '</div>';

        $this->printStyles();
        $this->printScripts();

        echo '</div>';
    }

    /**
     * Renderiza la tabla de permisos
     */
    protected function renderPermissionsTable()
    {
        global $ID;

        $items = $this->helper->getAllMenuItems();

        if (empty($items)) {
            echo '<p>' . $this->getLang('no_items') . '</p>';
            return;
        }

        echo '<form method="post" action="' . wl($ID, ['do' => 'admin', 'page' => 'niccadminmenu']) . '">';
        echo '<input type="hidden" name="sectok" value="' . getSecurityToken() . '" />';

        echo '<table class="inline permissions-table">';
        echo '<thead>';
        echo '<tr>';
        echo '<th>' . $this->getLang('th_module') . '</th>';
        echo '<th>' . $this->getLang('th_category') . '</th>';
        echo '<th colspan="2" class="center">Superuser</th>';
        echo '<th colspan="2" class="center">Admin</th>';
        echo '<th colspan="2" class="center">Manager</th>';
        echo '</tr>';
        echo '<tr class="subheader">';
        echo '<th></th>';
        echo '<th></th>';
        echo '<th class="center small">Ver</th>';
        echo '<th class="center small">Ejecutar</th>';
        echo '<th class="center small">Ver</th>';
        echo '<th class="center small">Ejecutar</th>';
        echo '<th class="center small">Ver</th>';
        echo '<th class="center small">Ejecutar</th>';
        echo '</tr>';
        echo '</thead>';
        echo '<tbody>';

        foreach ($items as $item) {
            $perms = $this->helper->getItemPermissions($item['id']);
            $isDangerous = (bool)$item['is_dangerous'];

            echo '<tr' . ($isDangerous ? ' class="dangerous"' : '') . '>';
            echo '<td><strong>' . hsc($item['name']) . '</strong>';
            if ($item['plugin_name']) {
                echo ' <small>(' . hsc($item['plugin_name']) . ')</small>';
            }
            if ($isDangerous) {
                echo ' <span class="badge-danger">!</span>';
            }
            echo '</td>';
            echo '<td>' . hsc($item['category_name']) . '</td>';

            // Permisos por rol
            foreach (['superuser', 'admin', 'manager'] as $role) {
                $canView = isset($perms[$role]['can_view']) ? $perms[$role]['can_view'] : false;
                $canExecute = isset($perms[$role]['can_execute']) ? $perms[$role]['can_execute'] : false;

                // Todos los roles son editables (superuser, admin, manager)
                {
                    $viewChecked = $canView ? 'checked' : '';
                    $execChecked = $canExecute ? 'checked' : '';

                    // Hidden 0 garantiza que el campo siempre llega al POST
                    $safeId = (int)$item['id'];
                    echo '<td class="center">';
                    echo '<input type="hidden" name="perms[' . $safeId . '][' . $role . '][view]" value="0">';
                    echo '<input type="checkbox" name="perms[' . $safeId . '][' . $role . '][view]" value="1" ' . $viewChecked . '>';
                    echo '</td>';
                    echo '<td class="center">';
                    echo '<input type="hidden" name="perms[' . $safeId . '][' . $role . '][execute]" value="0">';
                    echo '<input type="checkbox" name="perms[' . $safeId . '][' . $role . '][execute]" value="1" ' . $execChecked . '>';
                    echo '</td>';
                }
            }

            echo '</tr>';
        }

        echo '</tbody>';
        echo '</table>';

        echo '<p class="legend">';
        echo '<strong>Ver:</strong> El modulo aparece en el menu. ';
        echo '<strong>Ejecutar:</strong> El usuario puede acceder al modulo.';
        echo '</p>';

        echo '<button type="submit" name="save_permissions" class="btn btn-primary">';
        echo $this->getLang('btn_save');
        echo '</button>';

        echo '</form>';
    }

    /**
     * Renderiza el formulario de sincronizacion
     */
    protected function renderSyncForm()
    {
        global $ID;

        $result = $this->helper->syncInstalledPlugins();

        echo '<h2>' . $this->getLang('sync_title') . '</h2>';
        echo '<p>' . $this->getLang('sync_description') . '</p>';

        if (!empty($result['added'])) {
            echo '<div class="info">';
            echo '<strong>' . $this->getLang('sync_new_plugins') . ':</strong>';
            echo '<ul>';
            foreach ($result['added'] as $plugin) {
                echo '<li>' . hsc($plugin) . '</li>';
            }
            echo '</ul>';
            echo '</div>';
        }

        if (!empty($result['missing'])) {
            echo '<div class="notify">';
            echo '<strong>' . $this->getLang('sync_missing_plugins') . ':</strong>';
            echo '<ul>';
            foreach ($result['missing'] as $plugin) {
                echo '<li>' . hsc($plugin) . '</li>';
            }
            echo '</ul>';
            echo '</div>';
        }

        if (empty($result['added']) && empty($result['missing'])) {
            echo '<div class="success">';
            echo $this->getLang('sync_all_synced');
            echo '</div>';
        }

        echo '<form method="post" action="' . wl($ID, ['do' => 'admin', 'page' => 'niccadminmenu']) . '">';
        echo '<input type="hidden" name="sectok" value="' . getSecurityToken() . '" />';
        echo '<button type="submit" name="sync_plugins" class="btn btn-secondary">';
        echo $this->getLang('btn_sync');
        echo '</button>';
        echo '</form>';
    }

    /**
     * Renderiza el formulario para agregar item
     */
    protected function renderAddItemForm()
    {
        global $ID;

        $db = $this->helper->getDB();
        $categories = [];
        if ($db) {
            $res = $db->query('SELECT id, name FROM admin_menu_categories ORDER BY sort_order');
            if ($res) {
                $categories = $db->res2arr($res);
            }
        }

        echo '<h2>' . $this->getLang('add_item_title') . '</h2>';

        echo '<form method="post" action="' . wl($ID, ['do' => 'admin', 'page' => 'niccadminmenu']) . '">';
        echo '<input type="hidden" name="sectok" value="' . getSecurityToken() . '" />';

        echo '<div class="form-group">';
        echo '<label for="new_item_code">' . $this->getLang('field_code') . ' *</label>';
        echo '<input type="text" name="new_item[code]" id="new_item_code" required class="form-control">';
        echo '</div>';

        echo '<div class="form-group">';
        echo '<label for="new_item_name">' . $this->getLang('field_name') . ' *</label>';
        echo '<input type="text" name="new_item[name]" id="new_item_name" required class="form-control">';
        echo '</div>';

        echo '<div class="form-group">';
        echo '<label for="new_item_description">' . $this->getLang('field_description') . '</label>';
        echo '<input type="text" name="new_item[description]" id="new_item_description" class="form-control">';
        echo '</div>';

        echo '<div class="form-group">';
        echo '<label for="new_item_category">' . $this->getLang('field_category') . ' *</label>';
        echo '<select name="new_item[category_id]" id="new_item_category" required class="form-control">';
        foreach ($categories as $cat) {
            echo '<option value="' . (int)$cat['id'] . '">' . hsc($cat['name']) . '</option>';
        }
        echo '</select>';
        echo '</div>';

        echo '<div class="form-group">';
        echo '<label for="new_item_plugin">' . $this->getLang('field_plugin') . '</label>';
        echo '<input type="text" name="new_item[plugin_name]" id="new_item_plugin" class="form-control">';
        echo '<small>' . $this->getLang('field_plugin_hint') . '</small>';
        echo '</div>';

        echo '<div class="form-group">';
        echo '<label for="new_item_url">' . $this->getLang('field_url') . '</label>';
        echo '<input type="text" name="new_item[url]" id="new_item_url" class="form-control" placeholder="?do=admin&page=">';
        echo '</div>';

        echo '<div class="form-group">';
        echo '<label for="new_item_icon">' . $this->getLang('field_icon') . '</label>';
        echo '<select name="new_item[icon]" id="new_item_icon" class="form-control">';
        $icons = ['puzzle', 'settings', 'users', 'shield', 'database', 'calendar', 'file-text', 'folder', 'wrench', 'clock', 'hard-drive', 'trash-2'];
        foreach ($icons as $icon) {
            echo '<option value="' . $icon . '">' . $icon . '</option>';
        }
        echo '</select>';
        echo '</div>';

        echo '<div class="form-group checkbox">';
        echo '<label>';
        echo '<input type="checkbox" name="new_item[is_dangerous]" value="1">';
        echo ' ' . $this->getLang('field_is_dangerous');
        echo '</label>';
        echo '</div>';

        echo '<button type="submit" name="add_item" class="btn btn-primary">';
        echo $this->getLang('btn_add');
        echo '</button>';

        echo '</form>';
    }

    /**
     * Imprime estilos CSS
     */
    protected function printStyles()
    {
        echo '<style>
            #niccadminmenu_config {
                max-width: 1200px;
                margin: 0 auto;
                padding: 20px;
            }

            #niccadminmenu_config h1 {
                color: #1e293b;
                border-bottom: 2px solid #ec4899;
                padding-bottom: 10px;
                margin-bottom: 20px;
            }

            .tabs ul {
                list-style: none;
                padding: 0;
                margin: 0 0 20px 0;
                border-bottom: 2px solid #e2e8f0;
                display: flex;
            }

            .tabs ul li {
                margin: 0;
            }

            .tabs ul li a {
                display: block;
                padding: 10px 20px;
                text-decoration: none;
                color: #64748b;
                border-bottom: 2px solid transparent;
                margin-bottom: -2px;
                transition: all 0.2s ease;
            }

            .tabs ul li.active a,
            .tabs ul li a:hover {
                color: #ec4899;
                border-bottom-color: #ec4899;
            }

            .tab-content {
                display: none;
            }

            .tab-content.active {
                display: block;
            }

            .permissions-table {
                width: 100%;
                margin: 20px 0;
            }

            .permissions-table th {
                background: #f1f5f9;
                padding: 10px;
                text-align: left;
            }

            .permissions-table th.center,
            .permissions-table td.center {
                text-align: center;
            }

            .permissions-table th.small {
                font-size: 0.8em;
                font-weight: normal;
            }

            .permissions-table .subheader th {
                background: #f8fafc;
                font-size: 0.75em;
            }

            .permissions-table tr.dangerous {
                background: #fef2f2;
            }

            .permissions-table tr:hover {
                background: #f8fafc;
            }

            .permissions-table tr.dangerous:hover {
                background: #fee2e2;
            }

            .badge-danger {
                display: inline-block;
                background: #ef4444;
                color: white;
                padding: 2px 6px;
                border-radius: 4px;
                font-size: 0.7em;
                font-weight: bold;
            }

            .legend {
                color: #64748b;
                font-size: 0.9em;
                margin: 15px 0;
            }

            .form-group {
                margin-bottom: 15px;
            }

            .form-group label {
                display: block;
                margin-bottom: 5px;
                font-weight: 500;
            }

            .form-control {
                display: block;
                width: 100%;
                max-width: 400px;
                padding: 8px 12px;
                border: 1px solid #e2e8f0;
                border-radius: 6px;
                font-size: 1em;
            }

            .form-control:focus {
                outline: none;
                border-color: #ec4899;
                box-shadow: 0 0 0 3px rgba(236, 72, 153, 0.1);
            }

            .form-group small {
                display: block;
                color: #94a3b8;
                font-size: 0.85em;
                margin-top: 4px;
            }

            .form-group.checkbox label {
                display: inline-flex;
                align-items: center;
                gap: 8px;
                cursor: pointer;
            }

            .btn {
                display: inline-block;
                padding: 10px 20px;
                border: none;
                border-radius: 6px;
                font-size: 1em;
                font-weight: 500;
                cursor: pointer;
                transition: all 0.2s ease;
            }

            .btn-primary {
                background: #ec4899;
                color: white;
            }

            .btn-primary:hover {
                background: #db2777;
            }

            .btn-secondary {
                background: #64748b;
                color: white;
            }

            .btn-secondary:hover {
                background: #475569;
            }

            .info {
                background: #dbeafe;
                border: 1px solid #3b82f6;
                color: #1e40af;
                padding: 15px;
                border-radius: 6px;
                margin: 15px 0;
            }

            .success {
                background: #dcfce7;
                border: 1px solid #22c55e;
                color: #166534;
                padding: 15px;
                border-radius: 6px;
                margin: 15px 0;
            }

            .notify {
                background: #fef3c7;
                border: 1px solid #f59e0b;
                color: #92400e;
                padding: 15px;
                border-radius: 6px;
                margin: 15px 0;
            }

            .error {
                background: #fee2e2;
                border: 1px solid #ef4444;
                color: #991b1b;
                padding: 15px;
                border-radius: 6px;
                margin: 15px 0;
            }

            .info ul, .notify ul {
                margin: 10px 0 0 20px;
                padding: 0;
            }
        </style>';
    }

    /**
     * Imprime scripts JS
     */
    protected function printScripts()
    {
        echo '<script>
            document.addEventListener("DOMContentLoaded", function() {
                var tabs = document.querySelectorAll(".tabs ul li a");
                var contents = document.querySelectorAll(".tab-content");

                tabs.forEach(function(tab) {
                    tab.addEventListener("click", function(e) {
                        e.preventDefault();

                        // Remover active de todos
                        tabs.forEach(function(t) {
                            t.parentElement.classList.remove("active");
                        });
                        contents.forEach(function(c) {
                            c.classList.remove("active");
                        });

                        // Activar el clickeado
                        tab.parentElement.classList.add("active");
                        var target = document.querySelector(tab.getAttribute("href"));
                        if (target) {
                            target.classList.add("active");
                        }
                    });
                });
            });
        </script>';
    }
}
