<?php

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

class action_plugin_niccstyleconfig extends ActionPlugin {

    private static $accessKey = 'Colores2026';

    public function register(\Doku_Event_Handler $controller) {
        $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'handleAjax');
    }

    public function handleAjax(Event $event) {
        $call = $event->data;
        $prefix = 'plugin_niccstyleconfig_';
        if (strpos($call, $prefix) !== 0) return;

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

        // Limpiar cualquier output previo (msg() de DokuWiki puede emitir HTML)
        while (ob_get_level()) ob_end_clean();

        global $INPUT;
        header('Content-Type: application/json; charset=utf-8');

        // Capturar output para que msg() no corrompa el JSON
        ob_start();

        // Auth check
        if (!auth_isadmin()) {
            echo json_encode(['ok' => false, 'error' => 'Acceso denegado']);
            return;
        }

        // Password check (from POST or GET)
        $key = $INPUT->str('stylekey', '');
        if ($key !== self::$accessKey) {
            echo json_encode(['ok' => false, 'error' => 'Clave invalida']);
            return;
        }

        // CSRF for POST
        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            if (!checkSecurityToken()) {
                echo json_encode(['ok' => false, 'error' => 'Token de seguridad invalido']);
                return;
            }
        }

        // Release session for heavy ops
        session_write_close();

        /** @var helper_plugin_niccstyleconfig $helper */
        $helper = plugin_load('helper', 'niccstyleconfig');
        if (!$helper) {
            echo json_encode(['ok' => false, 'error' => 'Helper no disponible']);
            return;
        }

        $action = substr($call, strlen($prefix));

        switch ($action) {
            // ── Systems ──
            case 'scan':
                $result = $helper->scanServerSystems();
                echo json_encode(['ok' => $result['error'] === null, 'error' => $result['error'], 'systems' => $result['systems'], 'count' => count($result['systems'])]);
                break;

            case 'systems':
                $systems = $helper->getCachedSystems();
                $cacheDate = $helper->getCacheDate();
                // Enrich with group assignments
                foreach ($systems as &$s) {
                    $a = $helper->getSystemAssignments($s['system_name']);
                    $s['group_origin'] = !empty($a['as_origin']) ? $a['as_origin'][0]['label'] : '';
                    $s['group_dest'] = !empty($a['as_destination']) ? $a['as_destination'][0]['label'] : '';
                }
                unset($s); // release reference
                echo json_encode(['ok' => true, 'systems' => $systems, 'count' => count($systems), 'cache_date' => $cacheDate]);
                break;

            // ── Groups ──
            case 'group_list':
                $groups = $helper->getAllGroups();
                echo json_encode(['ok' => true, 'groups' => $groups]);
                break;

            case 'group_save':
                $id = $INPUT->int('id', 0);
                $label = trim($INPUT->str('label', ''));
                $color = $INPUT->str('color', '#3b82f6');
                $desc = $INPUT->str('description', '');
                $active = $INPUT->int('is_active', 1);

                if ($label === '') {
                    echo json_encode(['ok' => false, 'error' => 'La etiqueta es obligatoria']);
                    break;
                }
                // Sanitize label
                $label = preg_replace('/[^a-zA-Z0-9áéíóúñÁÉÍÓÚÑ _\-]/', '', $label);
                if ($label === '') {
                    echo json_encode(['ok' => false, 'error' => 'Etiqueta invalida']);
                    break;
                }
                // Validate color is a safe hex value (prevent CSS injection)
                if (!preg_match('/^#[0-9a-fA-F]{3,8}$/', $color)) {
                    $color = '#3b82f6';
                }

                if ($id > 0) {
                    $ok = $helper->updateGroup($id, $label, $color, $desc, $active);
                    echo json_encode(['ok' => $ok, 'error' => $ok ? null : 'No se pudo actualizar (etiqueta duplicada?)']);
                } else {
                    $result = $helper->createGroup($label, $color, $desc);
                    if (is_array($result)) {
                        $reasons = [
                            'db_unavailable' => 'Base de datos no disponible. Verifique plugin sqlite.',
                            'empty_label' => 'La etiqueta quedo vacia despues de sanitizar.',
                            'duplicate' => 'Ya existe un grupo con esa etiqueta.',
                            'insert_failed' => 'Error al insertar en la base de datos.',
                        ];
                        $ok = !empty($result['ok']);
                        $error = $ok ? null : ($reasons[$result['reason']] ?? 'Error desconocido: ' . ($result['reason'] ?? ''));
                        echo json_encode(['ok' => $ok, 'error' => $error]);
                    } else {
                        echo json_encode(['ok' => (bool)$result, 'error' => $result ? null : 'Error desconocido']);
                    }
                }
                break;

            case 'group_del':
                $id = $INPUT->int('id', 0);
                if ($id <= 0) {
                    echo json_encode(['ok' => false, 'error' => 'ID invalido']);
                    break;
                }
                $ok = $helper->deleteGroup($id);
                echo json_encode(['ok' => $ok]);
                break;

            case 'group_toggle':
                $id = $INPUT->int('id', 0);
                $active = $INPUT->int('is_active', 0);
                $ok = $helper->toggleGroupActive($id, $active);
                echo json_encode(['ok' => $ok]);
                break;

            // ── Assignments ──
            case 'set_origin':
                $groupId = $INPUT->int('group_id', 0);
                $systemName = $INPUT->str('system_name', '');
                if (!$groupId || !$systemName) {
                    echo json_encode(['ok' => false, 'error' => 'Parametros faltantes']);
                    break;
                }
                $cached = $helper->queryRow('SELECT * FROM style_systems_cache WHERE system_name = ?', [$systemName]);
                if (!$cached) {
                    echo json_encode(['ok' => false, 'error' => 'Sistema no encontrado en cache']);
                    break;
                }
                $ok = $helper->setOrigin($groupId, $cached['system_name'], $cached['system_path'], $cached['system_title'], $cached['template']);
                echo json_encode(['ok' => $ok]);
                break;

            case 'add_dest':
                $groupId = $INPUT->int('group_id', 0);
                $systemNames = $INPUT->arr('system_names', []);
                if (!$groupId || empty($systemNames)) {
                    echo json_encode(['ok' => false, 'error' => 'Parametros faltantes']);
                    break;
                }
                $added = $helper->addDestinations($groupId, $systemNames);
                echo json_encode(['ok' => true, 'added' => $added]);
                break;

            case 'rem_dest':
                $groupId = $INPUT->int('group_id', 0);
                $systemName = $INPUT->str('system_name', '');
                if (!$groupId || !$systemName) {
                    echo json_encode(['ok' => false, 'error' => 'Parametros faltantes']);
                    break;
                }
                $ok = $helper->removeDestination($groupId, $systemName);
                echo json_encode(['ok' => $ok]);
                break;

            case 'assignments':
                $groupId = $INPUT->int('group_id', 0);
                if (!$groupId) {
                    echo json_encode(['ok' => false, 'error' => 'group_id requerido']);
                    break;
                }
                $origin = $helper->getOrigin($groupId);
                $destinations = $helper->getDestinations($groupId);
                echo json_encode(['ok' => true, 'origin' => $origin, 'destinations' => $destinations]);
                break;

            // ── Preview ──
            case 'preview':
                $systemName = $INPUT->str('system_name', '');
                $template = $INPUT->str('template', '20cones');
                if (!$helper->isValidTemplate($template)) {
                    echo json_encode(['ok' => false, 'error' => 'Template invalido']);
                    break;
                }
                $cached = $helper->queryRow('SELECT * FROM style_systems_cache WHERE system_name = ?', [$systemName]);
                if (!$cached) {
                    echo json_encode(['ok' => false, 'error' => 'Sistema no encontrado']);
                    break;
                }
                $colors = $helper->getColorPreview($cached['system_path'], $template);
                $content = $helper->readStyleIni($cached['system_path'], $template);
                echo json_encode(['ok' => true, 'colors' => $colors, 'content' => $content]);
                break;

            // ── Apply ──
            case 'apply':
                $groupId = $INPUT->int('group_id', 0);
                if (!$groupId) {
                    echo json_encode(['ok' => false, 'error' => 'group_id requerido']);
                    break;
                }
                $result = $helper->applyGroup($groupId);
                echo json_encode($result);
                break;

            case 'apply_all':
                $results = $helper->applyAllActive();
                echo json_encode(['ok' => true, 'results' => $results]);
                break;

            // ── Backups / Rollback ──
            case 'backups':
                $systemName = $INPUT->str('system_name', '');
                $backups = $helper->getBackups($systemName ?: null, 50);
                echo json_encode(['ok' => true, 'backups' => $backups]);
                break;

            case 'rollback':
                $backupId = $INPUT->int('backup_id', 0);
                if (!$backupId) {
                    echo json_encode(['ok' => false, 'error' => 'backup_id requerido']);
                    break;
                }
                $result = $helper->rollbackSystem($backupId);
                echo json_encode($result);
                break;

            // ── Logs ──
            case 'logs':
                $logs = $helper->getLogs(100);
                echo json_encode(['ok' => true, 'logs' => $logs]);
                break;

            default:
                echo json_encode(['ok' => false, 'error' => 'Accion desconocida: ' . $action]);
        }
    }
}
