<?php

// Configurar manejo de errores para devolver JSON
error_reporting(E_ALL);
ini_set('display_errors', 0); // No mostrar errores en HTML

// Aumentar tiempo de ejecución para verificación por ping (puede tardar varios minutos)
set_time_limit(300); // 5 minutos

// Handler global de errores
set_error_handler(function ($errno, $errstr, $errfile, $errline) {
    throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
});

// Handler global de excepciones no capturadas
set_exception_handler(function ($exception) {
    header('Content-Type: application/json');
    echo json_encode([
        'success' => false,
        'message' => 'Error fatal: ' . $exception->getMessage(),
        'file' => $exception->getFile(),
        'line' => $exception->getLine()
    ]);
    exit;
});

chdir(__DIR__);

require_once __DIR__ . '/vendor/autoload.php';
require_once __DIR__ . '/src/IpSearchService.php';
require_once __DIR__ . '/src/PingService.php';
require_once __DIR__ . '/src/CrmService.php';
require_once __DIR__ . '/src/IpValidator.php';
require_once __DIR__ . '/src/ApiHandlers.php';
require_once __DIR__ . '/src/AdminRangeHelper.php';

use Ubnt\UcrmPluginSdk\Service\PluginLogManager;
use Ubnt\UcrmPluginSdk\Service\PluginConfigManager;
use Ubnt\UcrmPluginSdk\Service\UcrmApi;
use Ubnt\UcrmPluginSdk\Service\UcrmSecurity;
use SiipAvailableIps\IpSearchService;
use SiipAvailableIps\PingService;
use GuzzleHttp\Client;

// Manejo de errores para el handler de configuración avanzada
error_reporting(E_ALL);
ini_set('display_errors', 1);

// Handler para guardar configuración avanzada
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['save_advanced_config'])) {
    try {
        $jsonData = $_POST['save_advanced_config'];

        // Validar JSON
        $validation = \SiipAvailableIps\AdminRangeHelper::validateConfigJson($jsonData);
        if (!$validation['valid']) {
            die('Error: ' . $validation['error']);
        }

        // Guardar en config.json directamente (el SDK no tiene método save)
        $configFile = __DIR__ . '/data/config.json';
        if (!file_exists($configFile)) {
            // Si no existe, intentar crearlo con estructura básica
            $config = [];
        } else {
            $config = json_decode(file_get_contents($configFile), true);
            if (!is_array($config)) {
                $config = [];
            }
        }

        $config['customAdminRangesJson'] = $jsonData;

        if (file_put_contents($configFile, json_encode($config, JSON_PRETTY_PRINT)) === false) {
            throw new Exception("No se pudo escribir en el archivo de configuración: $configFile");
        }

        // Redirigir con mensaje de éxito
        header('Location: ?success=1');
        exit;
    } catch (Exception $e) {
        die('Error al guardar configuración: ' . $e->getMessage());
    }
}

// Get UCRM log manager
$log = PluginLogManager::create();

// Log TODAS las peticiones
$log->appendLog('=== NUEVA PETICIÓN ===');
$log->appendLog('Método: ' . $_SERVER['REQUEST_METHOD']);
$log->appendLog('POST data: ' . json_encode($_POST));
$log->appendLog('GET data: ' . json_encode($_GET));
$log->appendLog('Content-Type: ' . ($_SERVER['CONTENT_TYPE'] ?? 'no definido'));
$log->appendLog('User Agent: ' . ($_SERVER['HTTP_USER_AGENT'] ?? 'no definido'));

$configManager = PluginConfigManager::create();
$config = $configManager->loadConfig();

// 0. NMS Authentication Proxy — Permite login sin sesión UCRM activa
$ipServer = $config['ipserver'] ?? 'localhost';
$nmsBaseUrl = "https://{$ipServer}/nms/api/v2.1";

// 0a. NMS Login (POST username + password)
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_GET['action']) && $_GET['action'] === 'nms_login') {
    header('Content-Type: application/json');
    $input = json_decode(file_get_contents('php://input'), true);
    $username = $input['username'] ?? '';
    $password = $input['password'] ?? '';

    if (!$username || !$password) {
        http_response_code(400);
        echo json_encode(['error' => 'Se requieren usuario y contraseña.']);
        exit;
    }

    try {
        $nmsClient = new Client(['verify' => false, 'http_errors' => false]);
        $resp = $nmsClient->post("{$nmsBaseUrl}/user/login", [
            'json' => ['username' => $username, 'password' => $password],
            'headers' => ['Content-Type' => 'application/json'],
        ]);

        $statusCode = $resp->getStatusCode();
        $body = json_decode($resp->getBody()->getContents(), true);
        $authToken = $resp->getHeaderLine('x-auth-token');

        if ($statusCode === 200 && $authToken) {
            $log->appendLog("INFO: NMS Login OK for user: {$username} (role: " . ($body['role'] ?? 'unknown') . ")");
            echo json_encode([
                'success' => true,
                'token' => $authToken,
                'user' => $body,
            ]);
        } elseif ($statusCode === 201) {
            $log->appendLog("INFO: NMS Login requires 2FA for user: {$username}");
            http_response_code(201);
            echo json_encode([
                'requires2FA' => true,
                'twoFactorToken' => $body,
            ]);
        } else {
            $log->appendLog("WARN: NMS Login failed for user: {$username} (HTTP {$statusCode})");
            http_response_code($statusCode ?: 401);
            echo json_encode(['error' => $body['message'] ?? 'Credenciales inválidas.', 'statusCode' => $statusCode]);
        }
    } catch (\Exception $e) {
        $log->appendLog("ERROR: NMS Login exception: " . $e->getMessage());
        http_response_code(500);
        echo json_encode(['error' => 'Error de conexión con el servidor UISP.']);
    }
    exit;
}

// 0b. NMS TOTP Login (POST token + totpCode for 2FA step 2)
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_GET['action']) && $_GET['action'] === 'nms_login_totp') {
    header('Content-Type: application/json');
    $input = json_decode(file_get_contents('php://input'), true);

    try {
        $nmsClient = new Client(['verify' => false, 'http_errors' => false]);
        $resp = $nmsClient->post("{$nmsBaseUrl}/user/login/totpauth", [
            'json' => $input,
            'headers' => ['Content-Type' => 'application/json'],
        ]);

        $statusCode = $resp->getStatusCode();
        $body = json_decode($resp->getBody()->getContents(), true);
        $authToken = $resp->getHeaderLine('x-auth-token');

        if ($statusCode === 200 && $authToken) {
            $log->appendLog("INFO: NMS 2FA Login OK for user: " . ($body['username'] ?? 'unknown'));
            echo json_encode(['success' => true, 'token' => $authToken, 'user' => $body]);
        } else {
            http_response_code($statusCode ?: 401);
            echo json_encode(['error' => $body['message'] ?? 'Código TOTP inválido.']);
        }
    } catch (\Exception $e) {
        http_response_code(500);
        echo json_encode(['error' => 'Error de conexión con el servidor UISP.']);
    }
    exit;
}

// 0c. NMS Verify Session (GET with x-auth-token header)
if ($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['action']) && $_GET['action'] === 'nms_verify_session') {
    header('Content-Type: application/json');
    $token = $_SERVER['HTTP_X_AUTH_TOKEN'] ?? '';

    if (!$token) {
        http_response_code(401);
        echo json_encode(['error' => 'No token provided.']);
        exit;
    }

    try {
        $nmsClient = new Client(['verify' => false, 'http_errors' => false]);
        $resp = $nmsClient->get("{$nmsBaseUrl}/user", [
            'headers' => ['x-auth-token' => $token],
        ]);

        $statusCode = $resp->getStatusCode();
        $body = json_decode($resp->getBody()->getContents(), true);

        if ($statusCode === 200) {
            echo json_encode(['success' => true, 'user' => $body]);
        } else {
            http_response_code(401);
            echo json_encode(['error' => 'Sesión inválida o expirada.']);
        }
    } catch (\Exception $e) {
        http_response_code(500);
        echo json_encode(['error' => 'Error verificando sesión.']);
    }
    exit;
}


// ============================================================================
// API REST - Manejar peticiones JSON (Postman, Webhooks, etc.)
// ============================================================================
$contentType = $_SERVER['CONTENT_TYPE'] ?? '';
$isJsonRequest = stripos($contentType, 'application/json') !== false;

if ($isJsonRequest && $_SERVER['REQUEST_METHOD'] === 'POST') {
    $log->appendLog('>>> Petición API JSON detectada');

    $rawInput = file_get_contents('php://input');
    $log->appendLog('Raw input length: ' . strlen($rawInput) . ' bytes');

    $jsonData = json_decode($rawInput, true);

    if (json_last_error() !== JSON_ERROR_NONE) {
        $log->appendLog('ERROR: JSON inválido - ' . json_last_error_msg());
        header('Content-Type: application/json');
        echo json_encode([
            'success' => false,
            'error' => 'Invalid JSON',
            'message' => json_last_error_msg()
        ]);
        exit;
    }

    $log->appendLog('JSON parseado correctamente: ' . json_encode($jsonData));

    // Procesar petición API
    handleApiRequest($jsonData, $log);
    exit;
}

// ============================================================================
// FRONTEND HTML - Manejar peticiones AJAX del formulario
// ============================================================================
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'search') {
    $log->appendLog('>>> Entrando al handler de búsqueda AJAX');

    try {
        // Obtener configuración del plugin desde data/config.json
        $configManager = PluginConfigManager::create();
        $config = $configManager->loadConfig();

        $log->appendLog('Configuración cargada: ' . json_encode([
            'ipserver' => $config['ipserver'] ?? 'NO CONFIGURADO',
            'hasUnmsToken' => !empty($config['unmsApiToken']),
            'hasApiToken' => !empty($config['apitoken'])
        ]));

        // Validar que exista la configuración necesaria
        if (empty($config['ipserver'])) {
            $log->appendLog('ERROR: No se ha configurado ipserver');
            header('Content-Type: application/json');
            echo json_encode([
                'success' => false,
                'message' => 'El plugin no está configurado correctamente. Falta la dirección del servidor.'
            ]);
            exit;
        }

        if (empty($config['unmsApiToken'])) {
            $log->appendLog('ERROR: No se ha configurado unmsApiToken');
            header('Content-Type: application/json');
            echo json_encode([
                'success' => false,
                'message' => 'El plugin no está configurado correctamente. Falta el token de API de UNMS.'
            ]);
            exit;
        }

        $segmento = $_POST['segment'] ?? '';
        // NOTA: Ignoramos verify_ping aquí porque ahora se hace progresivamente desde el frontend
        // Pero lo logueamos para saber la intención del usuario
        $verifyPingIntention = isset($_POST['verify_ping']) && $_POST['verify_ping'] === 'true';

        $log->appendLog("Buscando IPs en segmento: $segmento (Búsqueda inicial rápida)");

        // URL de la API de UISP - Usar HTTPS

        // URL de la API de UISP - Usar HTTPS
        $apiUrl = "https://{$config['ipserver']}/nms/api/v2.1/devices/ips?suspended=true&management=true&includeObsolete=true";
        $apiToken = $config['unmsApiToken'];

        $log->appendLog("URL de API: $apiUrl");

        // Crear instancia del servicio y buscar IPs (SIN ping, el ping se hace después)
        // IMPORTANTE: Pasar $config completo para que tenga acceso a apitoken e ipserver para CRM
        $ipService = new IpSearchService($apiUrl, $apiToken, $log, $config);
        $resultado = $ipService->buscarIpsDisponibles($segmento, false);

        $log->appendLog('Resultado de búsqueda: ' . json_encode([
            'success' => $resultado['success'],
            'ipsDisponibles' => count($resultado['data'] ?? []),
            'ipsEnUso' => count($resultado['used'] ?? [])
        ]));

        header('Content-Type: application/json');
        echo json_encode($resultado);
    } catch (Exception $e) {
        $log->appendLog('EXCEPCIÓN en búsqueda de IPs: ' . $e->getMessage() . ' | Trace: ' . $e->getTraceAsString());
        header('Content-Type: application/json');
        echo json_encode([
            'success' => false,
            'message' => 'Error al procesar la solicitud: ' . $e->getMessage(),
            'error_file' => $e->getFile(),
            'error_line' => $e->getLine()
        ]);
    } catch (Error $e) {
        $log->appendLog('ERROR FATAL en búsqueda de IPs: ' . $e->getMessage() . ' | Trace: ' . $e->getTraceAsString());
        header('Content-Type: application/json');
        echo json_encode([
            'success' => false,
            'message' => 'Error fatal: ' . $e->getMessage(),
            'error_file' => $e->getFile(),
            'error_line' => $e->getLine()
        ]);
    }

    $log->appendLog('<<< Finalizando handler de búsqueda AJAX');
    exit;
} else if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'verify_batch') {
    $log->appendLog('>>> Entrando al handler de verificación por lotes (verify_batch)');

    try {
        $ips = $_POST['ips'] ?? [];
        if (!is_array($ips)) {
            $ips = json_decode($ips, true);
        }

        if (empty($ips)) {
            echo json_encode(['success' => true, 'results' => []]);
            exit;
        }

        $log->appendLog('Verificando lote de ' . count($ips) . ' IPs');

        // Crear instancia de PingService
        $pingService = new PingService($log, 1, count($ips));

        if (!$pingService->isAvailable()) {
            echo json_encode([
                'success' => false,
                'message' => 'Comando ping no disponible'
            ]);
            exit;
        }

        // Hacer ping
        $pingResults = $pingService->pingMultipleIps($ips);
        $processed = $pingService->processPingResults($pingResults);

        // Retornar resultados
        // responding = IPs que responden (ocupadas/conflicto)
        // not_responding = IPs que no responden (disponibles)
        echo json_encode([
            'success' => true,
            'responding' => $processed['responding'],
            'not_responding' => $processed['not_responding']
        ]);
    } catch (Throwable $e) {
        $log->appendLog('ERROR en verify_batch: ' . $e->getMessage());
        echo json_encode(['success' => false, 'message' => $e->getMessage()]);
    } catch (Exception $e) {
        $log->appendLog('ERROR en verify_batch: ' . $e->getMessage());
        echo json_encode(['success' => false, 'message' => $e->getMessage()]);
    }
    exit;
} else if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'validate') {
    // Handler para validación individual de IP con búsqueda de sitios
    header('Content-Type: application/json');

    try {
        $ip = $_POST['ip'] ?? '';

        if (empty($ip)) {
            echo json_encode(['success' => false, 'error' => 'Missing IP']);
            exit;
        }

        // Cargar configuración
        $configManager = \Ubnt\UcrmPluginSdk\Service\PluginConfigManager::create();
        $config = $configManager->loadConfig();

        // Crear instancia del validador
        $baseUrl = 'https://' . $config['ipserver'];
        $ipValidator = new \SiipAvailableIps\IpValidator(
            $baseUrl,
            $config['unmsApiToken'],
            $log
        );

        // Validar si la IP está en uso
        $isInUse = $ipValidator->isIpInUse($ip);

        echo json_encode([
            'success' => true,
            'ip' => $ip,
            'in_use' => $isInUse,
            'available' => !$isInUse
        ]);
    } catch (Exception $e) {
        $log->appendLog('Error en validación: ' . $e->getMessage());
        echo json_encode([
            'success' => false,
            'error' => $e->getMessage()
        ]);
    }
    exit;
} else if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $log->appendLog('Petición POST recibida pero sin action=search o action no válida');
    $log->appendLog('Action recibida: ' . ($_POST['action'] ?? 'NO DEFINIDA'));
}

// Log de acceso público
$log->appendLog('Acceso a la interfaz pública de búsqueda de IPs');

// Cargar configuración para verificar si ping está habilitado
$configManager = PluginConfigManager::create();
$config = $configManager->loadConfig();
$pingEnabled = !empty($config['enablePingVerification']) && ($config['enablePingVerification'] === true || $config['enablePingVerification'] === '1');

// Obteniendo el usuario activo y comprobando si necesita login
$security = UcrmSecurity::create();
$currentUser = $security->getUser();
$systemUserId = $currentUser ? $currentUser->userId : null;
$needsLogin = ($systemUserId === null);
if ($systemUserId) {
    $log->appendLog("INFO: Active User ID: $systemUserId");
} else {
    $log->appendLog("WARN: No active user found — login screen will be shown.");
}

?>
<!DOCTYPE html>
<html lang="es" data-theme="dark">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script>
        // Auth: detectar si se necesita login
        const NEEDS_LOGIN = <?php echo json_encode($needsLogin); ?>;
        // Inyectar ID de usuario del sistema (si lo hay)
        let SYSTEM_USER_ID = <?php echo json_encode($systemUserId); ?>;
        const CONFIG_IP_SERVER = <?php echo json_encode($config['ipserver'] ?? ''); ?>;
    </script>
    <title>Buscador de IPs Disponibles - SIIP</title>
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        /* Tema Oscuro (por defecto) */
        [data-theme="dark"] {
            --primary-gradient: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            --secondary-gradient: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
            --success-gradient: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
            --dark-bg: #0f0f23;
            --card-bg: rgba(255, 255, 255, 0.05);
            --card-border: rgba(255, 255, 255, 0.1);
            --text-primary: #ffffff;
            --text-secondary: #a0aec0;
            --shadow-lg: 0 20px 60px rgba(0, 0, 0, 0.3);
            --shadow-xl: 0 25px 80px rgba(0, 0, 0, 0.4);
        }

        /* Tema Claro */
        [data-theme="light"] {
            --primary-gradient: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            --secondary-gradient: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
            --success-gradient: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
            --dark-bg: #f7fafc;
            --card-bg: rgba(255, 255, 255, 0.95);
            --card-border: rgba(0, 0, 0, 0.1);
            --text-primary: #1a202c;
            --text-secondary: #4a5568;
            --shadow-lg: 0 10px 40px rgba(0, 0, 0, 0.08);
            --shadow-xl: 0 15px 50px rgba(0, 0, 0, 0.12);
        }

        body {
            font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
            background: var(--dark-bg);
            color: var(--text-primary);
            min-height: 100vh;
            display: flex;
            align-items: center;
            justify-content: center;
            padding: 20px;
            background-image:
                radial-gradient(circle at 20% 50%, rgba(102, 126, 234, 0.15) 0%, transparent 50%),
                radial-gradient(circle at 80% 80%, rgba(245, 87, 108, 0.15) 0%, transparent 50%);
            background-attachment: fixed;
            transition: background 0.3s ease, color 0.3s ease;
        }

        .container {
            width: 100%;
            max-width: 1200px;
            animation: fadeInUp 0.6s ease-out;
        }

        @keyframes fadeInUp {
            from {
                opacity: 0;
                transform: translateY(30px);
            }

            to {
                opacity: 1;
                transform: translateY(0);
            }
        }

        .header {
            text-align: center;
            margin-bottom: 40px;
        }

        .logo {
            width: 80px;
            height: 80px;
            margin: 0 auto 20px;
            background: var(--primary-gradient);
            border-radius: 20px;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 40px;
            box-shadow: var(--shadow-lg);
            animation: pulse 2s ease-in-out infinite;
        }

        @keyframes pulse {

            0%,
            100% {
                transform: scale(1);
            }

            50% {
                transform: scale(1.05);
            }
        }

        h1 {
            font-size: 2.5rem;
            font-weight: 700;
            background: linear-gradient(135deg, #667eea 0%, #f5576c 100%);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            background-clip: text;
            margin-bottom: 10px;
        }

        .subtitle {
            color: var(--text-secondary);
            font-size: 1.1rem;
            font-weight: 400;
        }

        .card {
            background: var(--card-bg);
            backdrop-filter: blur(20px);
            border: 1px solid var(--card-border);
            border-radius: 24px;
            padding: 40px;
            box-shadow: var(--shadow-xl);
            margin-bottom: 30px;
            transition: transform 0.3s ease, box-shadow 0.3s ease;
        }

        .card:hover {
            transform: translateY(-5px);
            box-shadow: 0 30px 90px rgba(0, 0, 0, 0.5);
        }

        .search-form {
            display: flex;
            gap: 15px;
            margin-bottom: 30px;
            flex-wrap: wrap;
            align-items: flex-end;
        }

        .input-group {
            flex: 1;
            min-width: 250px;
        }

        label {
            display: block;
            margin-bottom: 8px;
            font-weight: 500;
            font-size: 0.9rem;
            color: var(--text-secondary);
        }

        .input-wrapper {
            position: relative;
        }

        .input-prefix {
            position: absolute;
            left: 20px;
            top: 50%;
            transform: translateY(-50%);
            color: var(--text-secondary);
            font-weight: 500;
            pointer-events: none;
        }

        input[type="text"] {
            width: 100%;
            padding: 16px 20px 16px 90px;
            background: rgba(255, 255, 255, 0.05);
            border: 2px solid var(--card-border);
            border-radius: 12px;
            color: var(--text-primary);
            font-size: 1rem;
            font-family: 'Inter', sans-serif;
            transition: all 0.3s ease;
        }

        input[type="text"]:focus {
            outline: none;
            border-color: #667eea;
            background: rgba(255, 255, 255, 0.08);
            box-shadow: 0 0 0 4px rgba(102, 126, 234, 0.1);
        }

        .btn {
            padding: 16px 32px;
            border: none;
            border-radius: 12px;
            font-size: 1rem;
            font-weight: 600;
            cursor: pointer;
            transition: all 0.3s ease;
            font-family: 'Inter', sans-serif;
            display: inline-flex;
            align-items: center;
            gap: 10px;
            align-self: flex-end;
        }

        .btn-primary {
            background: var(--primary-gradient);
            color: white;
            box-shadow: 0 10px 30px rgba(102, 126, 234, 0.3);
        }

        .btn-primary:hover {
            transform: translateY(-2px);
            box-shadow: 0 15px 40px rgba(102, 126, 234, 0.4);
        }

        .btn-primary:active {
            transform: translateY(0);
        }

        .btn-primary:disabled {
            opacity: 0.6;
            cursor: not-allowed;
            transform: none;
        }

        .btn-cancel {
            background: rgba(245, 87, 108, 0.2);
            border: 1px solid rgba(245, 87, 108, 0.4);
            color: #f5576c;
            margin-top: 15px;
        }

        .btn-cancel:hover {
            background: rgba(245, 87, 108, 0.3);
            border-color: rgba(245, 87, 108, 0.6);
            transform: translateY(-2px);
        }

        .loading {
            display: none;
            text-align: center;
            padding: 20px;
        }

        .loading.active {
            display: block;
        }

        .spinner {
            width: 50px;
            height: 50px;
            margin: 0 auto 15px;
            border: 4px solid rgba(255, 255, 255, 0.1);
            border-top-color: #667eea;
            border-radius: 50%;
            animation: spin 1s linear infinite;
        }

        @keyframes spin {
            to {
                transform: rotate(360deg);
            }
        }

        .results {
            display: none;
        }

        .results.active {
            display: block;
            animation: fadeInUp 0.5s ease-out;
        }

        .stats {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
            gap: 20px;
            margin-bottom: 30px;
        }

        .stat-card {
            background: rgba(255, 255, 255, 0.03);
            border: 1px solid var(--card-border);
            border-radius: 16px;
            padding: 20px;
            text-align: center;
        }

        .stat-value {
            font-size: 2.5rem;
            font-weight: 700;
            background: var(--success-gradient);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            background-clip: text;
            margin-bottom: 5px;
        }

        .stat-label {
            color: var(--text-secondary);
            font-size: 0.9rem;
        }

        .table-container {
            overflow-x: auto;
            border-radius: 16px;
            background: rgba(255, 255, 255, 0.02);
            border: 1px solid var(--card-border);
        }

        table {
            width: 100%;
            border-collapse: collapse;
        }

        thead {
            background: rgba(255, 255, 255, 0.05);
        }

        th {
            padding: 16px;
            text-align: left;
            font-weight: 600;
            color: var(--text-secondary);
            font-size: 0.85rem;
            text-transform: uppercase;
            letter-spacing: 0.5px;
        }

        td {
            padding: 16px;
            border-top: 1px solid var(--card-border);
        }

        tbody tr {
            transition: background 0.2s ease;
        }

        tbody tr:hover {
            background: rgba(255, 255, 255, 0.03);
        }

        .ip-address {
            font-family: 'Courier New', monospace;
            font-weight: 900;
            font-size: 1.7rem;
            color: #2095fbff;
        }

        .ip-cell-mobile {
            display: flex;
            align-items: center;
            gap: 12px;
        }

        .btn-copy {
            padding: 8px 16px;
            background: rgba(102, 126, 234, 0.2);
            border: 1px solid rgba(102, 126, 234, 0.3);
            border-radius: 8px;
            color: #667eea;
            font-size: 0.85rem;
            font-weight: 600;
            cursor: pointer;
            transition: all 0.2s ease;
        }

        .btn-copy:hover {
            background: rgba(102, 126, 234, 0.3);
            border-color: rgba(102, 126, 234, 0.5);
            transform: scale(1.05);
        }

        .btn-copy.copied {
            background: rgba(79, 172, 254, 0.2);
            border-color: rgba(79, 172, 254, 0.3);
            color: #4facfe;
        }

        .alert {
            padding: 16px 20px;
            border-radius: 12px;
            margin-bottom: 20px;
            display: flex;
            align-items: center;
            gap: 12px;
            animation: fadeInUp 0.4s ease-out;
        }

        .alert-error {
            background: rgba(245, 87, 108, 0.1);
            border: 1px solid rgba(245, 87, 108, 0.3);
            color: #f5576c;
        }

        .alert-success {
            background: rgba(79, 172, 254, 0.1);
            border: 1px solid rgba(79, 172, 254, 0.3);
            color: #4facfe;
        }

        .alert-info {
            background: rgba(79, 209, 197, 0.1);
            border: 1px solid rgba(79, 209, 197, 0.3);
            color: #4fd1c5;
        }

        .alert-warning {
            background: rgba(255, 193, 7, 0.1);
            border: 1px solid rgba(255, 193, 7, 0.3);
            color: #ffc107;
        }

        .ip-type-badge {
            padding: 6px 12px;
            border-radius: 6px;
            font-size: 0.8rem;
            font-weight: 600;
            display: inline-block;
            text-align: center;
        }

        .ip-type-admin {
            background: rgba(245, 87, 108, 0.2);
            border: 1px solid rgba(245, 87, 108, 0.4);
            color: #ff6b6b;
        }

        .ip-type-client {
            background: rgba(79, 209, 197, 0.2);
            border: 1px solid rgba(79, 209, 197, 0.4);
            color: #4fd1c5;
        }

        .footer {
            text-align: center;
            color: var(--text-secondary);
            font-size: 0.9rem;
            margin-top: 40px;
        }

        .footer a {
            color: #667eea;
            text-decoration: none;
            transition: color 0.2s ease;
        }

        .footer a:hover {
            color: #f5576c;
        }

        @media (max-width: 768px) {
            h1 {
                font-size: 2rem;
            }

            .card {
                padding: 25px;
            }

            .search-form {
                flex-direction: column;
            }

            .btn {
                width: 100%;
                justify-content: center;
            }

            .stats {
                grid-template-columns: 1fr;
            }

            /* Optimizaciones para tabla en móvil */
            th,
            td {
                padding: 10px 6px;
                font-size: 0.8rem;
            }

            /* Ocultar columnas # en móvil */
            th:first-child,
            td:first-child {
                display: none;
            }

            /* Contenedor de IP con badge debajo */
            .ip-cell-mobile {
                flex-direction: column;
                gap: 6px;
                align-items: flex-start;
            }

            .ip-address {
                font-size: 0.85rem;
            }

            .ip-type-badge {
                font-size: 0.65rem;
                padding: 3px 8px;
                align-self: flex-start;
            }

            .status-badge {
                font-size: 0.7rem;
                padding: 4px 8px;
                white-space: normal;
                line-height: 1.3;
            }

            .btn-copy {
                padding: 8px 12px;
                font-size: 0.75rem;
            }

            /* Hacer la tabla más compacta */
            .table-container {
                font-size: 0.85rem;
            }

            /* Ajustar anchos de columnas en móvil (3 columnas) */
            th:nth-child(2),
            td:nth-child(2) {
                /* Dirección IP + Tipo */
                width: 40%;
            }

            th:nth-child(4),
            td:nth-child(4) {
                /* Estado */
                width: 35%;
            }

            th:nth-child(5),
            td:nth-child(5) {
                /* Acción */
                width: 25%;
            }
        }

        .status-badge {
            padding: 6px 12px;
            border-radius: 6px;
            font-size: 0.8rem;
            font-weight: 600;
            display: inline-flex;
            align-items: center;
            gap: 6px;
        }

        .status-pending {
            background: rgba(255, 255, 255, 0.1);
            color: var(--text-secondary);
        }

        .status-verifying {
            background: rgba(102, 126, 234, 0.2);
            color: #667eea;
            animation: pulse 1.5s infinite;
        }

        .status-available {
            background: rgba(79, 209, 197, 0.2);
            color: #4fd1c5;
            border: 1px solid rgba(79, 209, 197, 0.4);
        }

        .status-conflict {
            background: rgba(245, 87, 108, 0.2);
            color: #ff6b6b;
            border: 1px solid rgba(245, 87, 108, 0.4);
        }

        .status-unknown {
            background: rgba(160, 174, 192, 0.2);
            color: #a0aec0;
            border: 1px solid rgba(160, 174, 192, 0.4);
        }

        .status-floating {
            background: rgba(255, 165, 0, 0.2);
            color: #ffa500;
            border: 1px solid rgba(255, 165, 0, 0.4);
        }

        .ip-type-floating {
            background: rgba(255, 165, 0, 0.2);
            border: 1px solid rgba(255, 165, 0, 0.4);
            color: #ffa500;
        }

        tr.hidden-row {
            display: none;
        }

        .checkbox-label {
            display: flex;
            align-items: center;
            gap: 10px;
            cursor: pointer;
            margin-bottom: 0;
            padding-top: 28px;
        }

        @media (max-width: 768px) {
            .checkbox-label {
                padding-top: 0;
                margin-top: 10px;
            }

            .input-group {
                width: 100%;
            }
        }

        /* Botón de cambio de tema */
        .theme-toggle {
            position: fixed;
            top: 20px;
            right: 20px;
            width: 50px;
            height: 50px;
            border-radius: 50%;
            background: var(--card-bg);
            border: 2px solid var(--card-border);
            color: var(--text-primary);
            font-size: 1.5rem;
            cursor: pointer;
            display: flex;
            align-items: center;
            justify-content: center;
            transition: all 0.3s ease;
            box-shadow: var(--shadow-lg);
            z-index: 1000;
        }

        .theme-toggle:hover {
            transform: scale(1.1) rotate(15deg);
            box-shadow: var(--shadow-xl);
        }

        @media (max-width: 768px) {
            .theme-toggle {
                width: 45px;
                height: 45px;
                font-size: 1.3rem;
                top: 15px;
                right: 15px;
            }
        }

        /* Botón de configuración avanzada */
        .config-toggle {
            position: fixed;
            top: 20px;
            right: 20px;
            width: 50px;
            height: 50px;
            border-radius: 50%;
            background: var(--card-bg);
            border: 2px solid var(--card-border);
            color: var(--text-primary);
            font-size: 1.5rem;
            cursor: pointer;
            display: flex;
            align-items: center;
            justify-content: center;
            transition: all 0.3s ease;
            box-shadow: var(--shadow-lg);
            z-index: 1001;
        }

        .config-toggle:hover {
            transform: scale(1.1) rotate(90deg);
            box-shadow: var(--shadow-xl);
        }

        /* Ajustar posición del botón de tema */
        .theme-toggle {
            top: 80px;
            /* Debajo del botón de configuración */
        }

        /* Modal de contraseña */
        .modal {
            display: none;
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.8);
            z-index: 2000;
            align-items: center;
            justify-content: center;
        }

        .modal-content {
            background: var(--card-bg);
            border: 2px solid var(--card-border);
            border-radius: 16px;
            padding: 40px;
            max-width: 400px;
            width: 90%;
            box-shadow: var(--shadow-xl);
            text-align: center;
        }

        .modal-content h3 {
            margin-bottom: 10px;
            color: var(--text-primary);
        }

        .modal-content p {
            color: var(--text-secondary);
            margin-bottom: 20px;
        }

        .modal-input {
            width: 100%;
            padding: 12px;
            border: 2px solid var(--card-border);
            border-radius: 8px;
            background: rgba(255, 255, 255, 0.05);
            color: var(--text-primary);
            font-size: 1rem;
            margin-bottom: 20px;
        }

        .modal-actions {
            display: flex;
            gap: 10px;
            justify-content: center;
        }

        /* Editor Visual */
        .advanced-editor {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: var(--dark-bg);
            z-index: 1500;
            overflow-y: auto;
            padding: 20px;
        }

        .editor-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 30px;
            padding: 20px;
            background: var(--card-bg);
            border: 1px solid var(--card-border);
            border-radius: 16px;
        }

        .editor-header h2 {
            margin: 0;
            color: var(--text-primary);
        }

        .editor-content {
            max-width: 1200px;
            margin: 0 auto;
        }

        .add-segment-form {
            padding: 20px 0;
        }

        .form-row {
            display: flex;
            gap: 20px;
            margin-bottom: 20px;
        }

        .range-input-group {
            display: flex;
            align-items: center;
            gap: 10px;
            margin-bottom: 10px;
        }

        .range-input-group input {
            width: 100px;
            padding: 8px;
            border: 2px solid var(--card-border);
            border-radius: 8px;
            background: rgba(255, 255, 255, 0.05);
            color: var(--text-primary);
        }

        .range-input-group span {
            color: var(--text-secondary);
        }

        .btn-small {
            padding: 6px 12px;
            font-size: 0.85rem;
            background: rgba(102, 126, 234, 0.2);
            border: 1px solid rgba(102, 126, 234, 0.3);
            border-radius: 8px;
            color: #667eea;
            cursor: pointer;
            transition: all 0.2s ease;
        }

        .btn-small:hover {
            background: rgba(102, 126, 234, 0.3);
            transform: translateY(-2px);
        }

        .editor-actions {
            display: flex;
            gap: 15px;
            justify-content: center;
            margin-top: 30px;
        }

        @media (max-width: 768px) {
            .config-toggle {
                width: 45px;
                height: 45px;
                font-size: 1.3rem;
                top: 15px;
                right: 15px;
            }

            .theme-toggle {
                top: 70px;
            }

            .modal-content {
                padding: 30px 20px;
            }

            .editor-header {
                flex-direction: column;
                gap: 15px;
            }

            .form-row {
                flex-direction: column;
            }

            .range-input-group {
                flex-wrap: wrap;
            }
        }

        /* ── Login Overlay ─────────────────────────────────────── */
        #loginOverlay {
            position: fixed;
            inset: 0;
            z-index: 99999;
            display: flex;
            align-items: center;
            justify-content: center;
            background-color: #050308;
            background-image:
                radial-gradient(at 0% 0%, rgba(127, 13, 242, 0.15) 0px, transparent 50%),
                radial-gradient(at 100% 100%, rgba(127, 13, 242, 0.1) 0px, transparent 50%),
                radial-gradient(at 50% 50%, rgba(20, 10, 30, 1) 0px, transparent 80%);
            font-family: 'Inter', sans-serif;
            transition: opacity 0.5s ease, visibility 0.5s ease;
        }

        #loginOverlay.hidden {
            opacity: 0;
            visibility: hidden;
            pointer-events: none;
        }

        .login-card {
            width: 440px;
            max-width: 92vw;
            background: rgba(25, 16, 34, 0.4);
            backdrop-filter: blur(24px);
            -webkit-backdrop-filter: blur(24px);
            border: 1px solid rgba(127, 13, 242, 0.2);
            border-radius: 20px;
            padding: 48px 40px 40px;
            box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.8);
            text-align: center;
            animation: loginSlideIn 0.6s cubic-bezier(0.16, 1, 0.3, 1) both;
        }

        @keyframes loginSlideIn {
            from {
                opacity: 0;
                transform: translateY(30px) scale(0.96);
            }

            to {
                opacity: 1;
                transform: translateY(0) scale(1);
            }
        }

        .login-logo {
            width: 80px;
            height: 80px;
            object-fit: contain;
            margin-bottom: 20px;
            filter: drop-shadow(0 4px 20px rgba(127, 13, 242, 0.4));
        }

        .login-title {
            color: #f8fafc;
            font-size: 1.6rem;
            font-weight: 800;
            margin: 0 0 4px;
            letter-spacing: -0.02em;
        }

        .login-subtitle {
            color: #94a3b8;
            font-size: 0.85rem;
            margin: 0 0 32px;
            font-weight: 500;
        }

        .login-field {
            position: relative;
            margin-bottom: 20px;
            text-align: left;
        }

        .login-field label {
            display: block;
            color: rgba(127, 13, 242, 0.8);
            font-size: 0.72rem;
            font-weight: 700;
            text-transform: uppercase;
            letter-spacing: 0.1em;
            margin-bottom: 8px;
            margin-left: 4px;
        }

        .login-field input {
            width: 100%;
            padding: 14px 16px;
            background: rgba(255, 255, 255, 0.05);
            border: 1px solid rgba(255, 255, 255, 0.1);
            border-radius: 9999px;
            color: #f1f5f9;
            font-size: 0.95rem;
            font-family: 'Inter', sans-serif;
            outline: none;
            transition: all 0.3s ease;
            box-sizing: border-box;
        }

        .login-field input:focus {
            border-color: rgba(127, 13, 242, 0.6);
            box-shadow: 0 0 15px rgba(127, 13, 242, 0.3);
            background: rgba(255, 255, 255, 0.08);
        }

        .login-field input::placeholder {
            color: #64748b;
        }

        .login-btn {
            width: 100%;
            padding: 14px;
            background: linear-gradient(135deg, #7f0df2 0%, #a855f7 100%);
            color: white;
            border: none;
            border-radius: 9999px;
            font-size: 0.9rem;
            text-transform: uppercase;
            letter-spacing: 0.05em;
            font-weight: 700;
            font-family: 'Inter', sans-serif;
            cursor: pointer;
            transition: transform 0.15s, box-shadow 0.25s;
            margin-top: 12px;
            box-shadow: 0 4px 15px rgba(127, 13, 242, 0.3);
        }

        .login-btn:hover:not(:disabled) {
            transform: translateY(-2px);
            box-shadow: 0 8px 25px rgba(127, 13, 242, 0.5);
        }

        .login-btn:active:not(:disabled) {
            transform: translateY(0);
        }

        .login-btn:disabled {
            opacity: 0.6;
            cursor: not-allowed;
            background: rgba(127, 13, 242, 0.5);
            box-shadow: none;
        }

        .login-error {
            background: rgba(239, 68, 68, 0.12);
            border: 1px solid rgba(239, 68, 68, 0.25);
            color: #fca5a5;
            padding: 10px 14px;
            border-radius: 10px;
            font-size: 0.85rem;
            margin-bottom: 16px;
            display: none;
        }

        .login-error.visible {
            display: block;
        }

        .login-spinner {
            display: inline-block;
            width: 18px;
            height: 18px;
            border: 2px solid rgba(255, 255, 255, 0.3);
            border-top-color: white;
            border-radius: 50%;
            animation: loginSpin 0.6s linear infinite;
            vertical-align: middle;
            margin-right: 6px;
        }

        @keyframes loginSpin {
            to {
                transform: rotate(360deg);
            }
        }

        #loginTotpSection {
            display: none;
        }

        #loginTotpSection.visible {
            display: block;
        }

        .login-footer {
            margin-top: 24px;
            color: #475569;
            font-size: 0.72rem;
        }

        .login-footer a {
            color: #6366f1;
            text-decoration: none;
        }

        /* Particles background */
        .login-particles {
            position: absolute;
            inset: 0;
            overflow: hidden;
            pointer-events: none;
        }

        .login-particles span {
            position: absolute;
            width: 4px;
            height: 4px;
            background: rgba(99, 102, 241, 0.3);
            border-radius: 50%;
            animation: loginFloat 12s infinite ease-in-out;
        }

        @keyframes loginFloat {

            0%,
            100% {
                transform: translateY(0) translateX(0);
                opacity: 0;
            }

            10% {
                opacity: 1;
            }

            90% {
                opacity: 1;
            }

            50% {
                transform: translateY(-400px) translateX(100px);
            }
        }

        .login-theme-btn {
            position: absolute;
            top: 24px;
            right: 24px;
            z-index: 10000;
            width: 60px;
            height: 32px;
            border-radius: 30px;
            background: rgba(15, 23, 42, 0.5);
            border: 1px solid rgba(255, 255, 255, 0.1);
            backdrop-filter: blur(16px);
            -webkit-backdrop-filter: blur(16px);
            cursor: pointer;
            box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.3);
            display: flex;
            align-items: center;
            padding: 0;
            outline: none !important;
            transition: all 0.4s ease;
        }

        .login-theme-btn:focus {
            outline: none !important;
        }

        .login-theme-btn:hover {
            background: rgba(15, 23, 42, 0.7);
        }

        .login-theme-btn .theme-icon {
            position: absolute;
            left: 4px;
            width: 24px;
            height: 24px;
            border-radius: 50%;
            background: #1e293b;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 0.85rem;
            box-shadow: 0 2px 5px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.1);
            transition: transform 0.5s cubic-bezier(0.34, 1.56, 0.64, 1), background 0.4s ease;
            transform: translateX(0);
            flex-shrink: 0;
        }

        .login-theme-btn .theme-text {
            display: none !important;
        }

        [data-theme="light"] #loginOverlay {
            background-color: #f7f5f8;
            background-image:
                radial-gradient(at 0% 0%, rgba(127, 13, 242, 0.08) 0px, transparent 50%),
                radial-gradient(at 100% 100%, rgba(127, 13, 242, 0.05) 0px, transparent 50%),
                radial-gradient(at 50% 50%, rgba(255, 255, 255, 1) 0px, transparent 80%);
        }

        [data-theme="light"] .login-card {
            background: rgba(255, 255, 255, 0.7);
            border: 1px solid rgba(127, 13, 242, 0.15);
            box-shadow: 0 24px 80px rgba(127, 13, 242, 0.05), 0 0 0 1px rgba(0, 0, 0, 0.05);
        }

        [data-theme="light"] .login-title {
            color: #0f172a;
        }

        [data-theme="light"] .login-theme-btn {
            background: rgba(127, 13, 242, 0.15);
            border-color: rgba(127, 13, 242, 0.2);
            box-shadow: inset 0 2px 6px rgba(127, 13, 242, 0.1);
        }

        [data-theme="light"] .login-theme-btn:hover {
            background: rgba(127, 13, 242, 0.25);
        }

        [data-theme="light"] .login-theme-btn .theme-icon {
            transform: translateX(28px);
            background: #ffffff;
            box-shadow: 0 2px 5px rgba(127, 13, 242, 0.3), inset 0 -1px 0 rgba(0, 0, 0, 0.05);
        }

        [data-theme="light"] .login-subtitle,
        [data-theme="light"] .login-field label,
        [data-theme="light"] .login-footer {
            color: #475569;
        }

        [data-theme="light"] .login-field input {
            background: rgba(255, 255, 255, 0.5);
            border: 1px solid rgba(127, 13, 242, 0.2);
            color: #0f172a;
        }

        [data-theme="light"] .login-field input:focus {
            border-color: rgba(127, 13, 242, 0.5);
            box-shadow: 0 0 15px rgba(127, 13, 242, 0.15);
            background: rgba(255, 255, 255, 0.8);
        }

        [data-theme="light"] .login-field input::placeholder {
            color: #94a3b8;
        }

        [data-theme="light"] .login-particles span {
            background: rgba(127, 13, 242, 0.3);
        }
    </style>
</head>

<body data-theme="dark">

    <!-- ━━━ Login Overlay ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -->
    <div id="loginOverlay">
        <button id="loginThemeToggleBtn" class="theme-toggle login-theme-btn">
            <span id="loginThemeIcon" class="theme-icon">☀️</span>
            <span id="loginThemeText" class="theme-text">Modo Claro</span>
        </button>
        <div class="login-particles" id="loginParticles"></div>
        <div class="login-card">
            <h2 class="login-title">SIIP Available IPs</h2>
            <p class="login-subtitle">Inicia sesión con tu cuenta de UISP</p>

            <div class="login-error" id="loginError"></div>

            <!-- Formulario principal -->
            <div id="loginFormSection">
                <div class="login-field group">
                    <label for="loginUsername">Usuario</label>
                    <div class="relative flex items-center rounded-full border border-white/10 bg-white/5 transition-all duration-300">
                        <input type="text" id="loginUsername" placeholder="Ingresa tu usuario" autocomplete="username" autofocus>
                    </div>
                </div>
                <div class="login-field group">
                    <label for="loginPassword">Contraseña</label>
                    <div class="relative flex items-center rounded-full border border-white/10 bg-white/5 transition-all duration-300">
                        <input type="password" id="loginPassword" placeholder="Ingresa tu contraseña" autocomplete="current-password">
                    </div>
                </div>
                <button class="login-btn btn-gradient" id="loginBtn" onclick="handleLogin()">Iniciar Sesión</button>
            </div>

            <!-- Sección 2FA (oculta por defecto) -->
            <div id="loginTotpSection">
                <div class="login-field group">
                    <label for="loginTotpCode">Código de autenticación (2FA)</label>
                    <div class="relative flex items-center rounded-full border border-white/10 bg-white/5 transition-all duration-300">
                        <input type="text" id="loginTotpCode" placeholder="Código de 6 dígitos" maxlength="6" inputmode="numeric" autocomplete="one-time-code">
                    </div>
                </div>
                <button class="login-btn btn-gradient" id="loginTotpBtn" onclick="handleTotpLogin()">Verificar Código</button>
            </div>

            <div class="login-footer">
                Acceso restringido a administradores UISP · SIIP © <?php echo date('Y'); ?>
            </div>
        </div>
    </div>

    <!-- MAIN APP WRAPPER (To hide when login overlay is active) -->
    <div id="mainAppContent">
        <!-- Botón de configuración avanzada -->
        <button id="advancedConfigBtn" class="config-toggle" title="Configuración avanzada">
            <span>⚙️</span>
        </button>

        <!-- Botón de cambio de tema -->
        <button id="themeToggle" class="theme-toggle" title="Cambiar tema">
            <span id="themeIcon">🌙</span>
        </button>

        <!-- Modal de contraseña -->
        <div id="passwordModal" class="modal" style="display: none;">
            <div class="modal-content">
                <h3>🔒 Acceso Restringido</h3>
                <p>Ingresa la contraseña de administrador para acceder a la configuración avanzada</p>
                <input type="password" id="adminPasswordInput" class="modal-input" placeholder="Contraseña" />
                <div class="modal-actions">
                    <button class="btn btn-primary" onclick="validatePassword()">Acceder</button>
                    <button class="btn" onclick="closePasswordModal()">Cancelar</button>
                </div>
            </div>
        </div>

        <!-- Editor Visual de Configuración Avanzada -->
        <div id="advancedEditor" class="advanced-editor" style="display: none;">
            <div class="editor-header">
                <h2>⚙️ Editor de Rangos Administrativos por Segmento</h2>
                <button class="btn" onclick="returnToMain()">← Volver</button>
            </div>

            <div class="editor-content">
                <!-- Formulario para agregar segmento -->
                <div class="card">
                    <h3>Agregar Nuevo Segmento</h3>
                    <div class="add-segment-form">
                        <div class="form-row">
                            <div class="input-group">
                                <label>Segmento</label>
                                <input type="number" id="newSegment" placeholder="ej: 18" min="0" max="255" />
                            </div>
                        </div>

                        <h4>Rangos Iniciales (IPs al inicio del segmento)</h4>
                        <div id="initialRangesContainer">
                            <div class="range-input-group">
                                <input type="number" class="range-start" placeholder="Desde" min="1" max="254" />
                                <span>hasta</span>
                                <input type="number" class="range-end" placeholder="Hasta" min="1" max="254" />
                                <button class="btn-small" onclick="addInitialRange()">+ Agregar Rango</button>
                            </div>
                        </div>

                        <h4>Rangos Finales (IPs al final del segmento)</h4>
                        <div id="finalRangesContainer">
                            <div class="range-input-group">
                                <input type="number" class="range-start" placeholder="Desde" min="1" max="254" />
                                <span>hasta</span>
                                <input type="number" class="range-end" placeholder="Hasta" min="1" max="254" value="254" />
                                <button class="btn-small" onclick="addFinalRange()">+ Agregar Rango</button>
                            </div>
                        </div>

                        <button class="btn btn-primary" onclick="addSegmentToTable()">✅ Agregar Segmento</button>
                    </div>
                </div>

                <!-- Tabla de segmentos configurados -->
                <div class="card">
                    <h3>Segmentos Configurados</h3>
                    <div class="table-container">
                        <table>
                            <thead>
                                <tr>
                                    <th>Segmento</th>
                                    <th>Rangos Iniciales</th>
                                    <th>Rangos Finales</th>
                                    <th>Acciones</th>
                                </tr>
                            </thead>
                            <tbody id="segmentsTableBody">
                                <!-- Filas dinámicas -->
                            </tbody>
                        </table>
                    </div>
                </div>

                <div class="editor-actions">
                    <button class="btn btn-primary" onclick="saveConfiguration()">💾 Guardar Configuración</button>
                    <button class="btn" onclick="returnToMain()">Cancelar</button>
                </div>
            </div>
        </div>

        <div class="container">
            <div class="header">
                <div class="logo">🌐</div>
                <h1>Buscador de IPs Disponibles</h1>
                <p class="subtitle">Sistema de gestión de direcciones IP para UISP</p>
                <?php if (isset($_GET['success']) && $_GET['success'] == '1'): ?>
                    <div style="background: rgba(79, 209, 197, 0.2); border: 1px solid rgba(79, 209, 197, 0.4); color: #4fd1c5; padding: 15px; border-radius: 12px; margin-top: 20px; text-align: center;">
                        ✅ Configuración avanzada guardada exitosamente
                    </div>
                <?php endif; ?>
            </div>

            <div class="card">
                <div style="display: flex; justify-content: flex-end; margin-bottom: 20px;">
                    <?php if (strpos($_SERVER['REQUEST_URI'], '_plugins') !== false): ?>
                        <button class="btn btn-secondary" style="color: #ef4444; border-color: rgba(239, 68, 68, 0.3); background: rgba(239, 68, 68, 0.05);" onclick="handleLogout()">
                            <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="vertical-align:middle; margin-right:6px;">
                                <path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"></path>
                                <polyline points="16 17 21 12 16 7"></polyline>
                                <line x1="21" y1="12" x2="9" y2="12"></line>
                            </svg>
                            Cerrar Sesión
                        </button>
                    <?php endif; ?>
                </div>
                <form class="search-form" id="searchForm">
                    <div class="input-group">
                        <label for="segment">Segmento de Red</label>
                        <div class="input-wrapper">
                            <span class="input-prefix">172.16.</span>
                            <input
                                type="text"
                                id="segment"
                                name="segment"
                                placeholder="0-255"
                                required
                                pattern="[0-9]{1,3}"
                                maxlength="3">
                        </div>
                    </div>
                    <?php if ($pingEnabled): ?>
                        <div style="display: flex; flex-direction: column; gap: 2px; flex: 0 0 auto; justify-content: flex-end;">
                            <div class="input-group" style="flex: 0 0 auto; min-width: auto; margin-bottom: 0;">
                                <label class="checkbox-label" style="margin-bottom: 0;">
                                    <input type="checkbox" id="verifyPing" name="verify_ping" style="width: auto; padding: 0; margin: 0;" checked>
                                    <span style="color: var(--text-secondary); font-size: 0.9rem;">🔍 Verificar con ping</span>
                                </label>
                            </div>
                            <div class="input-group" style="flex: 0 0 auto; min-width: auto; margin-bottom: 0;">
                                <label class="checkbox-label" style="margin-bottom: 0;">
                                    <input type="checkbox" id="hideAdmin" name="hide_admin" style="width: auto; padding: 0; margin: 0;" checked>
                                    <span style="color: var(--text-secondary); font-size: 0.9rem;">👁️ Ocultar IP's de Administración</span>
                                </label>
                            </div>
                        </div>
                        <div class="input-group" id="pingLimitContainer" style="flex: 0 0 auto; min-width: 150px;">
                            <label for="pingLimit">Límite de IPs</label>
                            <select id="pingLimit" name="ping_limit" style="width: 100%; padding: 16px; background: rgba(255, 255, 255, 0.05); border: 2px solid var(--card-border); border-radius: 12px; color: var(--text-primary); font-size: 1rem;">
                                <option value="0">Todas (Lento)</option>
                                <option value="5" selected>5 IPs (Rápido)</option>
                                <option value="10">10 IPs</option>
                                <option value="20">20 IPs</option>
                            </select>
                        </div>
                    <?php endif; ?>
                    <button type="submit" class="btn btn-primary" id="searchBtn">
                        <span>🔍</span>
                        <span>Buscar IPs</span>
                    </button>
                </form>

                <button id="cancelBtn" class="btn btn-cancel" style="display: none;">
                    🛑 Cancelar Verificación
                </button>

                <div class="loading" id="loading">
                    <div class="spinner"></div>
                    <p id="loadingMessage">Consultando IPs disponibles...</p>
                    <p id="loadingPingWarning" style="display: none; color: var(--text-secondary); font-size: 0.9rem; margin-top: 10px;">
                        ⏱️ Verificación por ping habilitada. Esto puede tardar varios minutos...
                    </p>
                </div>

                <div id="errorContainer"></div>

                <div class="results" id="results">
                    <div class="stats">
                        <div class="stat-card">
                            <div class="stat-value" id="availableCount">0</div>
                            <div class="stat-label">IPs Disponibles</div>
                        </div>
                        <div class="stat-card">
                            <div class="stat-value" id="usedCount">0</div>
                            <div class="stat-label">IPs en Uso</div>
                        </div>
                        <div class="stat-card">
                            <div class="stat-value" id="segmentDisplay">-</div>
                            <div class="stat-label">Segmento</div>
                        </div>
                    </div>

                    <div class="table-container">
                        <table>
                            <thead>
                                <tr>
                                    <th>#</th>
                                    <th>Dirección IP</th>
                                    <th>Estado</th>
                                    <th>Acción</th>
                                </tr>
                            </thead>
                            <tbody id="ipTableBody">
                            </tbody>
                        </table>
                    </div>
                </div>
            </div>

            <div class="footer">
                <p>Desarrollado por <a href="https://siip.mx" target="_blank">SIIP Internet</a></p>
            </div>
        </div>
    </div> <!-- END mainAppContent -->

    <script>
        // ━━━ Login Logic ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
        (function() {
            const ALLOWED_ROLES = ['admin', 'superadmin'];
            let _twoFactorData = null;

            // Generar partículas decorativas
            const particlesEl = document.getElementById('loginParticles');
            if (particlesEl) {
                for (let i = 0; i < 20; i++) {
                    const s = document.createElement('span');
                    s.style.left = Math.random() * 100 + '%';
                    s.style.top = (60 + Math.random() * 40) + '%';
                    s.style.animationDelay = (Math.random() * 12) + 's';
                    s.style.animationDuration = (8 + Math.random() * 8) + 's';
                    particlesEl.appendChild(s);
                }
            }

            function showLoginError(msg) {
                const el = document.getElementById('loginError');
                el.textContent = msg;
                el.classList.add('visible');
            }

            function hideLoginError() {
                document.getElementById('loginError').classList.remove('visible');
            }

            function setLoginLoading(loading) {
                const btn = document.getElementById('loginBtn');
                const totpBtn = document.getElementById('loginTotpBtn');
                if (loading) {
                    btn.disabled = true;
                    totpBtn.disabled = true;
                    btn.innerHTML = '<span class="login-spinner"></span>Autenticando...';
                    totpBtn.innerHTML = '<span class="login-spinner"></span>Verificando...';
                } else {
                    btn.disabled = false;
                    totpBtn.disabled = false;
                    btn.textContent = 'Iniciar Sesión';
                    totpBtn.textContent = 'Verificar Código';
                }
            }

            function onLoginSuccess(token, user) {
                sessionStorage.setItem('nms_auth_token', token);
                sessionStorage.setItem('nms_user', JSON.stringify(user));
                SYSTEM_USER_ID = user.id || user.userId || null;
                console.log('Login OK — User:', user.username, 'Role:', user.role, 'ID:', SYSTEM_USER_ID);

                // Ocultar overlay con animación
                const overlay = document.getElementById('loginOverlay');
                overlay.classList.add('hidden');
                setTimeout(() => {
                    overlay.style.display = 'none';
                }, 500);
            }

            window.handleLogin = async function() {
                hideLoginError();
                const username = document.getElementById('loginUsername').value.trim();
                const password = document.getElementById('loginPassword').value;

                if (!username || !password) {
                    showLoginError('Ingresa usuario y contraseña.');
                    return;
                }

                setLoginLoading(true);
                try {
                    const resp = await fetch('?action=nms_login', {
                        method: 'POST',
                        headers: {
                            'Content-Type': 'application/json'
                        },
                        body: JSON.stringify({
                            username,
                            password
                        }),
                    });

                    const data = await resp.json();

                    if (data.success && data.token) {
                        const role = data.user?.role || '';
                        if (!ALLOWED_ROLES.includes(role)) {
                            showLoginError(`Acceso denegado. Tu rol (${role}) no tiene permisos para este portal.`);
                            setLoginLoading(false);
                            return;
                        }
                        onLoginSuccess(data.token, data.user);
                    } else if (data.requires2FA) {
                        _twoFactorData = data.twoFactorToken;
                        document.getElementById('loginFormSection').style.display = 'none';
                        document.getElementById('loginTotpSection').classList.add('visible');
                        document.getElementById('loginTotpCode').focus();
                        setLoginLoading(false);
                    } else {
                        showLoginError(data.error || 'Credenciales inválidas.');
                        setLoginLoading(false);
                    }
                } catch (e) {
                    showLoginError('Error de conexión. Intenta de nuevo.');
                    setLoginLoading(false);
                }
            };

            window.handleTotpLogin = async function() {
                hideLoginError();
                const code = document.getElementById('loginTotpCode').value.trim();
                if (!code || code.length < 6) {
                    showLoginError('Ingresa el código de 6 dígitos.');
                    return;
                }

                setLoginLoading(true);
                try {
                    const payload = {
                        ..._twoFactorData,
                        totpCode: code
                    };
                    const resp = await fetch('?action=nms_login_totp', {
                        method: 'POST',
                        headers: {
                            'Content-Type': 'application/json'
                        },
                        body: JSON.stringify(payload),
                    });

                    const data = await resp.json();
                    if (data.success && data.token) {
                        const role = data.user?.role || '';
                        if (!ALLOWED_ROLES.includes(role)) {
                            showLoginError(`Acceso denegado. Tu rol (${role}) no tiene permisos.`);
                            setLoginLoading(false);
                            return;
                        }
                        onLoginSuccess(data.token, data.user);
                    } else {
                        showLoginError(data.error || 'Código TOTP inválido.');
                        setLoginLoading(false);
                    }
                } catch (e) {
                    showLoginError('Error de conexión. Intenta de nuevo.');
                    setLoginLoading(false);
                }
            };

            // Verificar sesión almacenada al cargar
            async function verifyStoredSession() {
                const token = sessionStorage.getItem('nms_auth_token');
                if (!token) return false;

                try {
                    const resp = await fetch('?action=nms_verify_session', {
                        headers: {
                            'x-auth-token': token
                        },
                    });
                    const data = await resp.json();
                    if (data.success && data.user) {
                        const role = data.user?.role || '';
                        if (ALLOWED_ROLES.includes(role)) {
                            onLoginSuccess(token, data.user);
                            return true;
                        }
                    }
                } catch (e) {
                    /* token inválido, mostrar login */
                }

                sessionStorage.removeItem('nms_auth_token');
                sessionStorage.removeItem('nms_user');
                return false;
            }

            // Enter key handlers
            document.getElementById('loginPassword')?.addEventListener('keydown', e => {
                if (e.key === 'Enter') handleLogin();
            });
            document.getElementById('loginUsername')?.addEventListener('keydown', e => {
                if (e.key === 'Enter') document.getElementById('loginPassword').focus();
            });
            document.getElementById('loginTotpCode')?.addEventListener('keydown', e => {
                if (e.key === 'Enter') handleTotpLogin();
            });

            // Inicialización: decidir si mostrar login o portal
            if (NEEDS_LOGIN) {
                // No hay sesión UCRM, intentar con token almacenado
                verifyStoredSession().then(valid => {
                    if (!valid) {
                        document.getElementById('loginOverlay').style.display = 'flex';
                    }
                });
            } else {
                // Sesión UCRM activa, ocultar login overlay
                const overlay = document.getElementById('loginOverlay');
                overlay.classList.add('hidden');
                overlay.style.display = 'none';
            }
        })();
    </script>

    <script>
        // Configuración de rangos de IPs administrativas
        const adminConfig = {
            rangeStart: <?php echo isset($config['adminRangeStart']) ? (int)$config['adminRangeStart'] : 1; ?>,
            rangeEnd: <?php echo isset($config['adminRangeEnd']) ? (int)$config['adminRangeEnd'] : 30; ?>,
            finalStart: <?php echo isset($config['adminRangeFinalStart']) ? (int)$config['adminRangeFinalStart'] : 254; ?>,
            finalEnd: <?php echo isset($config['adminRangeFinalEnd']) ? (int)$config['adminRangeFinalEnd'] : 254; ?>
        };

        console.log('PHP Config Debug:', <?php echo json_encode($config); ?>);

        const useCustomRanges = <?php echo !empty($config['useCustomAdminRanges']) ? 'true' : 'false'; ?>;

        const searchForm = document.getElementById('searchForm');

        // Mostrar indicador de modo
        const header = document.querySelector('.header');
        const modeBadge = document.createElement('div');
        modeBadge.className = useCustomRanges ? 'mode-badge custom' : 'mode-badge global';
        modeBadge.innerHTML = useCustomRanges ? '✨ Modo: Rangos Personalizados' : '🌐 Modo: Rangos Globales';
        modeBadge.style.cssText = `
            display: inline-block;
            padding: 4px 12px;
            border-radius: 20px;
            font-size: 0.8rem;
            margin-top: 10px;
            background: ${useCustomRanges ? 'rgba(102, 126, 234, 0.2)' : 'rgba(255, 255, 255, 0.1)'};
            color: ${useCustomRanges ? '#667eea' : '#a0aec0'};
            border: 1px solid ${useCustomRanges ? 'rgba(102, 126, 234, 0.3)' : 'rgba(255, 255, 255, 0.2)'};
        `;
        header.appendChild(modeBadge);

        const searchBtn = document.getElementById('searchBtn');
        const loading = document.getElementById('loading');
        const results = document.getElementById('results');
        const errorContainer = document.getElementById('errorContainer');
        const ipTableBody = document.getElementById('ipTableBody');
        const availableCount = document.getElementById('availableCount');
        const usedCount = document.getElementById('usedCount');
        const segmentDisplay = document.getElementById('segmentDisplay');
        const cancelBtn = document.getElementById('cancelBtn');
        let verificationCancelled = false;

        // ========== ADVANCED CONFIGURATION EDITOR ==========

        // Variables del editor
        // Inicializar editorData con los rangos personalizados
        let editorData;
        const customRangesJson = <?php echo json_encode($config['customAdminRangesJson'] ?? '{"segmentos":[]}'); ?>;

        try {
            editorData = JSON.parse(customRangesJson);
            if (!editorData.segmentos) {
                editorData = {
                    segmentos: []
                };
            }
            console.log('editorData cargado al inicio:', editorData);
        } catch (e) {
            console.error('Error loading initial editorData:', e);
            editorData = {
                segmentos: []
            };
        }

        let hasUnsavedChanges = false;
        let editingIndex = null; // Track which segment is being edited
        const adminPassword = <?php echo json_encode($config['adminPassword'] ?? ''); ?>;

        // Event listener para botón de configuración avanzada
        document.getElementById('advancedConfigBtn').addEventListener('click', openAdvancedConfig);

        function openAdvancedConfig() {
            document.getElementById('passwordModal').style.display = 'flex';
            document.getElementById('adminPasswordInput').value = '';
            document.getElementById('adminPasswordInput').focus();
        }

        function closePasswordModal() {
            document.getElementById('passwordModal').style.display = 'none';
        }

        function validatePassword() {
            const inputPassword = document.getElementById('adminPasswordInput').value;

            if (inputPassword === adminPassword) {
                closePasswordModal();
                showEditor();
            } else {
                alert('❌ Contraseña incorrecta');
                document.getElementById('adminPasswordInput').value = '';
                document.getElementById('adminPasswordInput').focus();
            }
            return false;
        }

        window.handleLogout = () => {
            sessionStorage.removeItem('nms_auth_token');
            sessionStorage.removeItem('nms_user');
            window.location.reload();
        };

        // Escuchar "Enter" en el input de contraseña
        document.getElementById('adminPasswordInput').addEventListener('keypress', function(e) {
            if (e.key === 'Enter') {
                validatePassword();
            }
        });

        function showEditor() {
            document.querySelector('.container').style.display = 'none';
            document.getElementById('advancedEditor').style.display = 'block';
            loadEditorData();
            hasUnsavedChanges = false;
        }

        function returnToMain() {
            if (hasUnsavedChanges) {
                if (!confirm('⚠️ Tienes cambios sin guardar. ¿Deseas salir de todos modos?')) {
                    return;
                }
            }

            document.getElementById('advancedEditor').style.display = 'none';
            document.querySelector('.container').style.display = 'block';
            hasUnsavedChanges = false;
        }

        function loadEditorData() {
            try {
                editorData = JSON.parse(customRangesJson);
                if (!editorData.segmentos) {
                    editorData = {
                        segmentos: []
                    };
                }
            } catch (e) {
                console.error('Error parsing JSON:', e);
                editorData = {
                    segmentos: []
                };
            }
            renderSegmentsTable();
        }

        function renderSegmentsTable() {
            const tbody = document.getElementById('segmentsTableBody');
            tbody.innerHTML = '';

            if (editorData.segmentos.length === 0) {
                tbody.innerHTML = '<tr><td colspan="4" style="text-align: center; color: var(--text-secondary);">No hay segmentos configurados</td></tr>';
                return;
            }

            editorData.segmentos.forEach((seg, index) => {
                const row = document.createElement('tr');

                // Formatear rangos iniciales
                const iniciales = seg.administrativas_iniciales.map(r => `${r.inicio}-${r.hasta}`).join(', ');

                // Formatear rangos finales
                const finales = seg.administrativas_finales.map(r => `${r.inicio}-${r.hasta}`).join(', ');

                row.innerHTML = `
                    <td><strong>172.16.${seg.segmento}.x</strong></td>
                    <td>${iniciales || '-'}</td>
                    <td>${finales || '-'}</td>
                    <td>
                        <button class="btn-small" onclick="editSegment(${index})" style="background: rgba(79, 172, 254, 0.2); color: #4facfe; border-color: rgba(79, 172, 254, 0.3); margin-right: 8px;">
                            ✏️ Editar
                        </button>
                        <button class="btn-small" onclick="deleteSegment(${index})" style="background: rgba(245, 87, 108, 0.2); color: #ff6b6b; border-color: rgba(245, 87, 108, 0.3);">
                            🗑️ Eliminar
                        </button>
                    </td>
                `;

                tbody.appendChild(row);
            });
        }

        function addInitialRange() {
            const container = document.getElementById('initialRangesContainer');
            const newRange = document.createElement('div');
            newRange.className = 'range-input-group';
            newRange.innerHTML = `
                <input type="number" class="range-start" placeholder="Desde" min="1" max="254" />
                <span>hasta</span>
                <input type="number" class="range-end" placeholder="Hasta" min="1" max="254" />
                <button class="btn-small" onclick="this.parentElement.remove()" style="background: rgba(245, 87, 108, 0.2); color: #ff6b6b;">
                    ✖ Quitar
                </button>
            `;
            container.appendChild(newRange);
        }

        function addFinalRange() {
            const container = document.getElementById('finalRangesContainer');
            const newRange = document.createElement('div');
            newRange.className = 'range-input-group';
            newRange.innerHTML = `
                <input type="number" class="range-start" placeholder="Desde" min="1" max="254" />
                <span>hasta</span>
                <input type="number" class="range-end" placeholder="Hasta" min="1" max="254" value="255" />
                <button class="btn-small" onclick="this.parentElement.remove()" style="background: rgba(245, 87, 108, 0.2); color: #ff6b6b;">
                    ✖ Quitar
                </button>
            `;
            container.appendChild(newRange);
        }

        // Helper function: Clear all range containers
        function clearRangeContainers() {
            document.getElementById('initialRangesContainer').innerHTML = '';
            document.getElementById('finalRangesContainer').innerHTML = '';
        }

        // Helper function: Add initial range with data
        function addInitialRangeWithData(start, end) {
            const container = document.getElementById('initialRangesContainer');
            const div = document.createElement('div');
            div.className = 'range-input-group';
            div.innerHTML = `
                <input type="number" class="range-start" value="${start}" min="1" max="254" />
                <span>hasta</span>
                <input type="number" class="range-end" value="${end}" min="1" max="254" />
                <button class="btn-small" onclick="this.parentElement.remove()" style="background: rgba(245, 87, 108, 0.2); color: #ff6b6b;">
                    ✖ Quitar
                </button>
            `;
            container.appendChild(div);
        }

        // Helper function: Add final range with data
        function addFinalRangeWithData(start, end) {
            const container = document.getElementById('finalRangesContainer');
            const div = document.createElement('div');
            div.className = 'range-input-group';
            div.innerHTML = `
                <input type="number" class="range-start" value="${start}" min="1" max="254" />
                <span>hasta</span>
                <input type="number" class="range-end" value="${end}" min="1" max="254" />
                <button class="btn-small" onclick="this.parentElement.remove()" style="background: rgba(245, 87, 108, 0.2); color: #ff6b6b;">
                    ✖ Quitar
                </button>
            `;
            container.appendChild(div);
        }

        // Reset form to add mode
        function resetForm() {
            const segmentInput = document.getElementById('newSegment');
            segmentInput.value = '';
            segmentInput.disabled = false;

            clearRangeContainers();

            // Add default empty ranges
            document.getElementById('initialRangesContainer').innerHTML = `
                <div class="range-input-group">
                    <input type="number" class="range-start" placeholder="Desde" min="1" max="254" />
                    <span>hasta</span>
                    <input type="number" class="range-end" placeholder="Hasta" min="1" max="254" />
                    <button class="btn-small" onclick="addInitialRange()">+ Agregar Rango</button>
                </div>
            `;

            document.getElementById('finalRangesContainer').innerHTML = `
                <div class="range-input-group">
                    <input type="number" class="range-start" placeholder="Desde" min="1" max="254" />
                    <span>hasta</span>
                    <input type="number" class="range-end" placeholder="Hasta" min="1" max="254" value="254" />
                    <button class="btn-small" onclick="addFinalRange()">+ Agregar Rango</button>
                </div>
            `;

            // Reset UI text
            document.querySelector('#advancedEditor .card h3').textContent = 'Agregar Nuevo Segmento';
            const submitBtn = document.querySelector('button[onclick="addSegmentToTable()"]');
            if (submitBtn) {
                submitBtn.textContent = '✅ Agregar Segmento';
            }

            editingIndex = null;
        }

        // Edit existing segment
        function editSegment(index) {
            editingIndex = index;
            const segment = editorData.segmentos[index];

            // Populate segment number
            const segmentInput = document.getElementById('newSegment');
            segmentInput.value = segment.segmento;
            segmentInput.disabled = true; // Can't change segment number when editing

            // Clear and populate ranges
            clearRangeContainers();

            // Populate initial ranges
            if (segment.administrativas_iniciales && segment.administrativas_iniciales.length > 0) {
                segment.administrativas_iniciales.forEach(rango => {
                    addInitialRangeWithData(rango.inicio, rango.hasta);
                });
            } else {
                // Add empty range if none exist
                addInitialRange();
            }

            // Populate final ranges
            if (segment.administrativas_finales && segment.administrativas_finales.length > 0) {
                segment.administrativas_finales.forEach(rango => {
                    addFinalRangeWithData(rango.inicio, rango.hasta);
                });
            } else {
                // Add empty range if none exist
                addFinalRange();
            }

            // Update UI
            document.querySelector('#advancedEditor .card h3').textContent = `Editar Segmento ${segment.segmento}`;
            const submitBtn = document.querySelector('button[onclick="addSegmentToTable()"]');
            if (submitBtn) {
                submitBtn.textContent = '💾 Actualizar Segmento';
            }

            // Scroll to top of editor
            document.getElementById('advancedEditor').scrollTop = 0;
        }

        function addSegmentToTable() {
            const segmentInput = document.getElementById('newSegment');
            const segment = segmentInput.value;

            if (!segment || segment < 0 || segment > 255) {
                alert('❌ Por favor ingresa un segmento válido (0-255)');
                return;
            }

            // Verificar si el segmento ya existe (solo en modo CREATE)
            if (editingIndex === null && editorData.segmentos.some(s => s.segmento == segment)) {
                alert('⚠️ Este segmento ya está configurado');
                return;
            }

            // Obtener rangos iniciales
            const initialRanges = [];
            const initialContainer = document.getElementById('initialRangesContainer');
            const initialGroups = initialContainer.querySelectorAll('.range-input-group');

            initialGroups.forEach(group => {
                const start = parseInt(group.querySelector('.range-start').value);
                const end = parseInt(group.querySelector('.range-end').value);

                if (start && end && start <= end) {
                    initialRanges.push({
                        inicio: start,
                        hasta: end
                    });
                }
            });

            // Obtener rangos finales
            const finalRanges = [];
            const finalContainer = document.getElementById('finalRangesContainer');
            const finalGroups = finalContainer.querySelectorAll('.range-input-group');

            finalGroups.forEach(group => {
                const start = parseInt(group.querySelector('.range-start').value);
                const end = parseInt(group.querySelector('.range-end').value);

                if (start && end && start <= end) {
                    finalRanges.push({
                        inicio: start,
                        hasta: end
                    });
                }
            });

            const newSegment = {
                segmento: segment,
                administrativas_iniciales: initialRanges,
                administrativas_finales: finalRanges
            };

            if (editingIndex !== null) {
                // UPDATE mode
                editorData.segmentos[editingIndex] = newSegment;
                alert('✅ Segmento actualizado correctamente');
            } else {
                // CREATE mode
                editorData.segmentos.push(newSegment);
                alert('✅ Segmento agregado correctamente');
            }

            // Reset form and update table
            resetForm();
            hasUnsavedChanges = true;
            renderSegmentsTable();
        }

        function deleteSegment(index) {
            if (confirm('¿Estás seguro de eliminar este segmento?')) {
                editorData.segmentos.splice(index, 1);
                hasUnsavedChanges = true;
                renderSegmentsTable();
            }
        }

        function saveConfiguration() {
            if (!confirm('¿Deseas guardar la configuración? Esto actualizará el archivo de configuración del plugin.')) {
                return;
            }

            const jsonData = JSON.stringify(editorData);

            // Crear formulario para enviar datos
            const form = document.createElement('form');
            form.method = 'POST';
            form.action = '';

            const input = document.createElement('input');
            input.type = 'hidden';
            input.name = 'save_advanced_config';
            input.value = jsonData;

            form.appendChild(input);
            document.body.appendChild(form);
            form.submit();
        }

        // ========== FIN ADVANCED CONFIGURATION EDITOR ==========


        // Theme toggle functionality
        const themeToggle = document.getElementById('themeToggle');
        const loginThemeToggleBtn = document.getElementById('loginThemeToggleBtn');
        const themeIcon = document.getElementById('themeIcon');
        const loginThemeIcon = document.getElementById('loginThemeIcon');
        const loginThemeText = document.getElementById('loginThemeText');
        const body = document.body;

        // Load saved theme or default to dark
        const savedTheme = localStorage.getItem('theme') || 'dark';
        body.setAttribute('data-theme', savedTheme);
        updateThemeIcon(savedTheme);

        function applyThemeChange() {
            const currentTheme = body.getAttribute('data-theme');
            const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
            body.setAttribute('data-theme', newTheme);
            localStorage.setItem('theme', newTheme);
            updateThemeIcon(newTheme);
        }

        // Theme toggle events
        if (themeToggle) themeToggle.addEventListener('click', applyThemeChange);
        if (loginThemeToggleBtn) loginThemeToggleBtn.addEventListener('click', applyThemeChange);

        function updateThemeIcon(theme) {
            if (themeIcon) themeIcon.textContent = theme === 'dark' ? '🌙' : '☀️';
            if (loginThemeIcon) loginThemeIcon.textContent = theme === 'dark' ? '🌙' : '☀️';
            if (loginThemeText) loginThemeText.textContent = theme === 'dark' ? 'Modo Claro' : 'Modo Oscuro';
        }

        // Toggle visibility of ping limit select
        <?php if ($pingEnabled): ?>
            const verifyPingCheckbox = document.getElementById('verifyPing');
            const pingLimitContainer = document.getElementById('pingLimitContainer');
            if (verifyPingCheckbox && pingLimitContainer) {
                verifyPingCheckbox.addEventListener('change', function() {
                    pingLimitContainer.style.display = this.checked ? 'block' : 'none';
                });
            }
        <?php endif; ?>

        searchForm.addEventListener('submit', async (e) => {
            e.preventDefault();

            const segment = document.getElementById('segment').value;

            // Validar segmento
            const segmentNum = parseInt(segment);
            if (isNaN(segmentNum) || segmentNum < 0 || segmentNum > 255) {
                showError('El segmento debe ser un número entre 0 y 255');
                return;
            }

            // Mostrar loading
            <?php if ($pingEnabled): ?>
                const verifyPingCheckbox = document.getElementById('verifyPing');
                const loadingPingWarning = document.getElementById('loadingPingWarning');
                if (verifyPingCheckbox && verifyPingCheckbox.checked) {
                    loadingPingWarning.style.display = 'block';
                }
            <?php endif; ?>

            loading.classList.add('active');
            results.classList.remove('active');
            errorContainer.innerHTML = '';
            searchBtn.disabled = true;

            try {
                const formData = new FormData();
                formData.append('action', 'search');
                formData.append('segment', segment);

                // Agregar verificación por ping si está habilitada y marcada
                <?php if ($pingEnabled): ?>
                    const verifyPingCheckbox = document.getElementById('verifyPing');
                    const pingLimitSelect = document.getElementById('pingLimit');
                    const shouldVerifyPing = verifyPingCheckbox && verifyPingCheckbox.checked;
                    const pingLimit = pingLimitSelect ? parseInt(pingLimitSelect.value) : 0;

                    // NOTA: Ya no enviamos verify_ping=true al backend para la búsqueda inicial
                    // La verificación se hará progresivamente después de recibir la lista
                    // Solo lo enviamos como 'false' para que el backend sepa que no debe verificar
                    formData.append('verify_ping', 'false');
                <?php endif; ?>

                console.log('Enviando petición AJAX...');
                console.log('Segmento:', segment);

                const response = await fetch('', {
                    method: 'POST',
                    body: formData
                });

                console.log('Respuesta recibida:', response.status, response.statusText);

                // Verificar si la respuesta es JSON
                const contentType = response.headers.get('content-type');
                console.log('Content-Type:', contentType);

                if (!contentType || !contentType.includes('application/json')) {
                    const textResponse = await response.text();
                    console.error('Respuesta no es JSON:', textResponse.substring(0, 500));
                    throw new Error('El servidor no devolvió una respuesta JSON válida');
                }

                const data = await response.json();
                console.log('Datos recibidos:', data);

                if (data.success) {
                    const clientIps = displayResults(data);

                    // Validación progresiva con búsqueda de sitios
                    <?php if ($pingEnabled): ?>
                        if (shouldVerifyPing) {
                            // Si ping está marcado, validar con site search y luego con ping
                            // NO ocultar loading, se encargará runProgressiveValidation
                            runProgressiveValidation(clientIps, pingLimit, shouldVerifyPing);
                        } else {
                            // Si ping NO está marcado, validar solo con site search
                            // NO ocultar loading, se encargará runProgressiveValidation
                            runProgressiveValidation(clientIps, 0, false);
                        }
                    <?php else: ?>
                        // Si ping no está habilitado globalmente, solo site search
                        runProgressiveValidation(clientIps, 0, false);
                    <?php endif; ?>
                } else {
                    showError(data.message || 'Error al buscar IPs disponibles');
                }
            } catch (error) {
                loading.classList.remove('active');
                <?php if ($pingEnabled): ?>
                    loadingPingWarning.style.display = 'none'; // Ocultar advertencia
                <?php endif; ?>
                searchBtn.disabled = false;
                console.error('Error completo:', error);
                console.error('Tipo de error:', error.name);
                console.error('Mensaje:', error.message);
                console.error('Stack:', error.stack);
                showError('Error de conexión: ' + error.message + '. Revise la consola del navegador para más detalles.');
            }
        });

        function displayResults(data) {
            // Actualizar estadísticas
            availableCount.textContent = data.data.length;
            usedCount.textContent = data.used ? data.used.length : 0;
            segmentDisplay.textContent = data.segment || '-';

            // Limpiar tabla
            ipTableBody.innerHTML = '';

            // Mostrar mensaje si no hay IPs disponibles y no hay flotantes
            if (data.data.length === 0 && (!data.floating || data.floating.length === 0)) {
                showError('No hay IPs disponibles en este segmento', 'warning');
                return [];
            }

            // Renderizar IPs flotantes primero (dispositivos no autorizados / Pending Adoption)
            if (data.floating && data.floating.length > 0) {
                data.floating.forEach(device => {
                    renderRow(device.ip, `⚠️ IP Flotante - ${device.name} (${device.model})`, 'floating');
                });
            }

            const clientIps = [];

            // Separar y renderizar solo IPs de administración
            data.data.forEach((ip, index) => {
                const ipTypeLabel = getIpType(ip);

                if (ipTypeLabel === 'Administración') {
                    renderRow(ip, 'Sólo validada con UISP', 'pending');
                } else {
                    clientIps.push(ip);
                }
            });

            // Renumerar filas visibles después de renderizar
            renumberVisibleRows();

            // Mostrar resultados container
            results.classList.add('active');

            // Mostrar mensaje de éxito
            showError(data.message, 'success');

            return clientIps;
        }

        function renderRow(ip, statusText, statusClass) {
            const ipTypeLabel = getIpType(ip);
            const hideAdminCheckbox = document.getElementById('hideAdmin');
            const isHidden = hideAdminCheckbox && hideAdminCheckbox.checked && ipTypeLabel === 'Administración';

            const row = document.createElement('tr');
            row.id = `row-${ip.replace(/\./g, '-')}`;
            if (isHidden) row.classList.add('hidden-row');
            if (ipTypeLabel === 'Administración') row.classList.add('admin-row');
            if (statusClass === 'floating') row.classList.add('floating-row');

            // El índice se asignará posteriormente por renumberVisibleRows()
            const index = 0;

            // Determinar el badge de tipo de IP
            let ipTypeBadge = '';
            if (statusClass === 'floating') {
                ipTypeBadge = '<span class="ip-type-badge ip-type-floating">IP Flotante</span>';
            } else if (ipTypeLabel === 'Administración') {
                ipTypeBadge = '<span class="ip-type-badge ip-type-admin">Administración</span>';
            } else {
                // Si la IP está en uso (status contiene "En uso" o statusClass es "used"), mostrar "No disponible" en rojo
                if (statusClass === 'used' || statusText.includes('En uso')) {
                    ipTypeBadge = '<span class="ip-type-badge ip-type-admin">No disponible</span>';
                } else {
                    ipTypeBadge = '<span class="ip-type-badge ip-type-client">Cliente</span>';
                }
            }

            row.innerHTML = `
                <td class="row-number">${index}</td>
                <td>
                    <div class="ip-cell-mobile">
                        <span class="ip-address">${ip}</span>
                        ${ipTypeBadge}
                    </div>
                </td>
                <td id="status-${ip.replace(/\./g, '-')}">
                    <span class="status-badge status-${statusClass}">${statusText}</span>
                </td>
                <td>
                    <button class="btn-copy" onclick="copyToClipboard('${ip}', this)">
                        📋 Copiar
                    </button>
                </td>
            `;
            ipTableBody.appendChild(row);

            // Renumerar filas visibles después de insertar
            renumberVisibleRows();
        }

        /**
         * Renumera las filas visibles consecutivamente (1, 2, 3...)
         */
        function renumberVisibleRows() {
            const allRows = ipTableBody.querySelectorAll('tr');
            let visibleIndex = 1;
            allRows.forEach(row => {
                const numberCell = row.querySelector('.row-number');
                if (!numberCell) return;
                if (row.classList.contains('hidden-row')) {
                    numberCell.textContent = '-';
                } else {
                    numberCell.textContent = visibleIndex++;
                }
            });
        }

        // Listener para el filtro de Admin IPs
        const hideAdminCheckbox = document.getElementById('hideAdmin');
        if (hideAdminCheckbox) {
            hideAdminCheckbox.addEventListener('change', function() {
                const adminRows = document.querySelectorAll('.admin-row');
                adminRows.forEach(row => {
                    if (this.checked) {
                        row.classList.add('hidden-row');
                    } else {
                        row.classList.remove('hidden-row');
                    }
                });
                // Renumerar filas después de cambiar visibilidad
                renumberVisibleRows();
            });
        }

        // Función para clasificar el tipo de IP
        function getIpType(ip) {
            const parts = ip.split('.');
            if (parts.length !== 4) return 'Cliente';

            const segment = parts[2];
            const lastOctet = parseInt(parts[3]);

            // 1. Verificar rangos personalizados si existen
            // Asegurarse de que editorData esté cargado
            if (typeof editorData === 'undefined' || !editorData.segmentos) {
                try {
                    if (typeof customRangesJson !== 'undefined') {
                        console.log('customRangesJson type:', typeof customRangesJson);
                        console.log('customRangesJson value:', customRangesJson);
                        editorData = JSON.parse(customRangesJson);
                        console.log('Parsed editorData:', editorData);
                        console.log('editorData.segmentos:', editorData.segmentos);
                    } else {
                        console.warn('customRangesJson is undefined');
                        editorData = {
                            segmentos: []
                        };
                    }
                } catch (e) {
                    console.error('Error parsing JSON in getIpType:', e);
                    console.error('Failed to parse:', customRangesJson);
                    editorData = {
                        segmentos: []
                    };
                }
            }

            // Buscar segmento actual en configuración personalizada
            // Convertir ambos a string y limpiar espacios para asegurar coincidencia
            const searchSeg = segment.toString().trim();
            const customSegment = editorData.segmentos.find(s => s.segmento.toString().trim() === searchSeg);

            if (useCustomRanges && customSegment) {
                // Verificar rangos iniciales personalizados
                if (customSegment.administrativas_iniciales) {
                    for (const rango of customSegment.administrativas_iniciales) {
                        if (lastOctet >= rango.inicio && lastOctet <= rango.hasta) {
                            console.log(`IP ${ip} es Admin (Custom Init: ${rango.inicio}-${rango.hasta})`);
                            return 'Administración';
                        }
                    }
                }

                // Verificar rangos finales personalizados
                if (customSegment.administrativas_finales) {
                    for (const rango of customSegment.administrativas_finales) {
                        if (lastOctet >= rango.inicio && lastOctet <= rango.hasta) {
                            console.log(`IP ${ip} es Admin (Custom Final: ${rango.inicio}-${rango.hasta})`);
                            return 'Administración';
                        }
                    }
                }

                // Si hay configuración personalizada para este segmento y no cayó en los rangos admin, es Cliente
                console.log(`IP ${ip} es Cliente (Custom Segment Found but not in ranges)`);
                return 'Cliente';
            } else if (useCustomRanges) {
                console.log(`IP ${ip}: Segmento '${searchSeg}' no encontrado en custom ranges.`);
                if (editorData.segmentos) {
                    console.log('Segmentos disponibles:', editorData.segmentos.map(s => `'${s.segmento}'`));
                } else {
                    console.log('editorData.segmentos es undefined o null');
                }
            }

            // 2. Fallback a configuración global si no hay segmento personalizado
            // Verificar si está en alguno de los rangos administrativos configurados globalmente
            if ((lastOctet >= adminConfig.rangeStart && lastOctet <= adminConfig.rangeEnd) ||
                (lastOctet >= adminConfig.finalStart && lastOctet <= adminConfig.finalEnd)) {
                return 'Administración';
            }

            return 'Cliente';
        }


        /**
         * Validación progresiva con búsqueda de sitios (event.ip_validate)
         * Valida cada IP antes de mostrarla en la tabla
         */
        async function runProgressiveValidation(clientIps, pingLimit, shouldVerifyPing) {
            console.log(`Iniciando validación progresiva de ${clientIps.length} IPs`);
            console.log(`Ping habilitado: ${shouldVerifyPing}, Límite: ${pingLimit}`);

            // Determinar IPs a validar (inicialmente todas, filtramos dinámicamente)
            let ipsToProcess = [...clientIps];

            console.log(`Validando hasta encontrar ${pingLimit > 0 ? pingLimit : 'todas'} IPs disponibles entre ${clientIps.length} candidatos`);

            // Mostrar mensaje de progreso según cantidad de IPs
            let progressMessage = '';
            if (shouldVerifyPing && (pingLimit === 0 || pingLimit >= 20)) {
                progressMessage = 'Validando todas las IP\'s por ping, esto puede llevar varios minutos. Espere por favor...';
            } else if (shouldVerifyPing) {
                progressMessage = 'Validando IP\'s por ping. Espere por favor...';
            } else {
                progressMessage = 'Validando IP\'s con búsqueda de sitios. Espere por favor...';
            }

            // Usar autohide = false explícitamente y agregar spinner HTML al mensaje
            const spinnerHtml = '<span class="loading-spinner-small"></span> ';
            showError(spinnerHtml + progressMessage, 'info', false);

            // Mostrar botón de cancelar
            verificationCancelled = false;
            if (cancelBtn) {
                cancelBtn.style.display = 'inline-flex';
            }

            let foundAvailableCount = 0;

            // Procesar cada IP secuencialmente
            for (const ip of ipsToProcess) {
                // Verificar si debemos detenernos por límite (Smart Limit)
                if (pingLimit > 0 && shouldVerifyPing && foundAvailableCount >= pingLimit) {
                    console.log(`Se alcanzó el límite de ${pingLimit} IPs disponibles. Deteniendo búsqueda.`);
                    break;
                }

                // Verificar si el usuario canceló
                if (verificationCancelled) {
                    console.log('Validación cancelada por el usuario');
                    showError('Validación cancelada. Mostrando resultados parciales.', 'warning');
                    break;
                }

                // NO renderizar aún, primero validar

                // Scroll al final de la tabla
                const tableContainer = document.querySelector('.table-container');
                if (tableContainer) {
                    tableContainer.scrollTop = tableContainer.scrollHeight;
                }

                try {
                    // Llamar a validación de IP con búsqueda de sitios
                    const formData = new FormData();
                    formData.append('action', 'validate');
                    formData.append('ip', ip);

                    const response = await fetch('', {
                        method: 'POST',
                        body: formData
                    });

                    const data = await response.json();

                    if (data.success && !data.in_use) {
                        // IP disponible según site search

                        if (shouldVerifyPing) {
                            // Si ping está habilitado, renderizar y verificar con ping
                            renderRow(ip, '⏳ Verificando ping...', 'verifying');

                            // Verificar ping y esperar resultado
                            const verifyResult = await verifyBatch([ip]);

                            // Si el resultado confirma que NO responde (not_responding), entonces es válida
                            if (verifyResult && verifyResult.not_responding && verifyResult.not_responding.includes(ip)) {
                                foundAvailableCount++;
                            }
                            // Si resonding (conflicto), NO incrementamos contador y seguimos buscando
                        } else {
                            // Si ping NO está habilitado, renderizar como disponible
                            renderRow(ip, '✅ Disponible', 'available');
                            foundAvailableCount++; // Contamos como encontrada
                        }
                    } else {
                        // IP en uso según site search - NO RENDERIZAR
                        // Solo agregar log en consola
                        console.log(`IP ${ip} filtrada (en uso en UISP)`);
                    }
                } catch (error) {
                    console.error(`Error validando IP ${ip}:`, error);
                    // En caso de error, renderizar con error
                    renderRow(ip, '❌ Error validación', 'error');
                }
            }

            // Ocultar botón de cancelar
            if (cancelBtn) {
                cancelBtn.style.display = 'none';
            }

            // Actualizar estadísticas con los números reales
            // Contar IPs disponibles (status-available) y en uso (status-used, status-conflict, o status-floating)
            const allRows = ipTableBody.querySelectorAll('tr');
            let availableIpsCount = 0;
            let usedIpsCount = 0;

            allRows.forEach(row => {
                const statusBadge = row.querySelector('.status-badge');
                if (statusBadge) {
                    if (statusBadge.classList.contains('status-available')) {
                        availableIpsCount++;
                    } else if (statusBadge.classList.contains('status-used') ||
                        statusBadge.classList.contains('status-conflict') ||
                        statusBadge.classList.contains('status-floating')) {
                        usedIpsCount++;
                    }
                }
            });

            // Actualizar contadores en la UI
            availableCount.textContent = availableIpsCount;
            usedCount.textContent = usedIpsCount;

            // Ocultar indicadores de carga y reactivar botón
            loading.classList.remove('active');
            <?php if ($pingEnabled): ?>
                if (loadingPingWarning) loadingPingWarning.style.display = 'none';
            <?php endif; ?>
            if (searchBtn) searchBtn.disabled = false;

            console.log(`Validación completada. ${availableIpsCount} IPs disponibles, ${usedIpsCount} IPs en uso`);
            showError(`Validación completada. ${availableIpsCount} IPs disponibles encontradas.`, 'success', false);
        }

        /**
         * Actualizar el estado de una fila existente
         */
        function updateRowStatus(ip, statusText, statusClass) {
            const statusCell = document.getElementById(`status-${ip.replace(/\./g, '-')}`);
            if (statusCell) {
                statusCell.innerHTML = `<span class="status-badge status-${statusClass}">${statusText}</span>`;
            }

            // Si el estado es "En uso", también actualizar el badge de tipo de IP a "No disponible"
            if (statusClass === 'used' || statusText.includes('En uso')) {
                const row = document.getElementById(`row-${ip.replace(/\./g, '-')}`);
                if (row) {
                    const ipTypeBadge = row.querySelector('.ip-type-badge');
                    if (ipTypeBadge && !ipTypeBadge.classList.contains('ip-type-admin')) {
                        // Cambiar de "Cliente" a "No disponible" con color rojo
                        ipTypeBadge.className = 'ip-type-badge ip-type-admin';
                        ipTypeBadge.textContent = 'No disponible';
                    }
                }
            }
        }

        async function runProgressiveVerification(clientIps, limit) {
            let ipsToVerify = [];

            // 1. Filtrar IPs a verificar según el límite
            if (limit > 0) {
                // Si hay límite, solo tomamos las primeras N
                ipsToVerify = clientIps.slice(0, limit);
            } else {
                // Si límite es 0 (Todas), verificamos todas
                ipsToVerify = [...clientIps];
            }

            console.log(`Iniciando verificación progresiva de ${ipsToVerify.length} IPs`);

            // Mostrar botón de cancelar
            verificationCancelled = false;
            if (cancelBtn) {
                cancelBtn.style.display = 'inline-flex';
            }

            // 2. Procesar una por una (secuencialmente)
            for (const ip of ipsToVerify) {
                // Verificar si el usuario canceló
                if (verificationCancelled) {
                    console.log('Verificación cancelada por el usuario');
                    showError('Verificación cancelada. Mostrando resultados parciales.', 'warning');
                    break;
                }

                // A. Renderizar fila con estado "Verificando"
                renderRow(ip, '⏳ Verificando...', 'verifying');

                // Scroll al final de la tabla para seguir el progreso
                const tableContainer = document.querySelector('.table-container');
                tableContainer.scrollTop = tableContainer.scrollHeight;

                // B. Verificar (lote de 1)
                await verifyBatch([ip]);
            }

            // Ocultar botón de cancelar al finalizar
            if (cancelBtn) {
                cancelBtn.style.display = 'none';
            }

            // Actualizar estadísticas con los números reales
            const allRows = ipTableBody.querySelectorAll('tr');
            let availableIpsCount = 0;
            let usedIpsCount = 0;

            allRows.forEach(row => {
                const statusBadge = row.querySelector('.status-badge');
                if (statusBadge) {
                    if (statusBadge.classList.contains('status-available')) {
                        availableIpsCount++;
                    } else if (statusBadge.classList.contains('status-used') ||
                        statusBadge.classList.contains('status-conflict') ||
                        statusBadge.classList.contains('status-floating')) {
                        usedIpsCount++;
                    }
                }
            });

            // Actualizar contadores en la UI
            availableCount.textContent = availableIpsCount;
            usedCount.textContent = usedIpsCount;

            // NOTA: Las IPs que exceden el límite NO se renderizan, cumpliendo el requerimiento.
        }

        // Event listener para botón de cancelar
        if (cancelBtn) {
            cancelBtn.addEventListener('click', () => {
                verificationCancelled = true;
                cancelBtn.style.display = 'none';
            });
        }

        async function verifyBatch(ips) {
            try {
                const formData = new FormData();
                formData.append('action', 'verify_batch');
                formData.append('ips', JSON.stringify(ips));

                // Timeout de 30 segundos por lote
                const controller = new AbortController();
                const timeoutId = setTimeout(() => controller.abort(), 30000);

                const response = await fetch('', {
                    method: 'POST',
                    body: formData,
                    signal: controller.signal
                });

                clearTimeout(timeoutId);

                if (!response.ok) {
                    throw new Error(`HTTP error! status: ${response.status}`);
                }

                const text = await response.text();
                let data;
                try {
                    data = JSON.parse(text);
                } catch (e) {
                    console.error('Respuesta no válida del servidor:', text);
                    throw new Error('Respuesta inválida del servidor');
                }

                if (data.success) {
                    // Actualizar UI
                    // Responding = Conflicto (Rojo)
                    if (data.responding) {
                        data.responding.forEach(ip => {
                            updateStatus(ip, 'conflict', '⚠️ En uso (Ping)');
                        });
                    }

                    // Not Responding = Disponible (Verde)
                    if (data.not_responding) {
                        data.not_responding.forEach(ip => {
                            updateStatus(ip, 'available', '✅ Disponible');
                        });
                    }

                    return data; // Devolver datos para uso externo
                } else {
                    throw new Error(data.message || 'Error en verificación');
                }
            } catch (error) {
                console.error('Error verificando lote:', error);
                // Marcar como error visualmente para que no se quede cargando
                ips.forEach(ip => {
                    updateStatus(ip, 'error', '❌ Error');
                });
                return null;
            }
        }

        function updateStatus(ip, type, text) {
            const cellId = `status-${ip.replace(/\./g, '-')}`;
            const cell = document.getElementById(cellId);
            if (cell) {
                cell.innerHTML = `<span class="status-badge status-${type}">${text}</span>`;
            }

            // Si el tipo es "conflict" (En uso por ping), actualizar el badge de tipo de IP
            if (type === 'conflict') {
                const row = document.getElementById(`row-${ip.replace(/\./g, '-')}`);
                if (row) {
                    const ipTypeBadge = row.querySelector('.ip-type-badge');
                    if (ipTypeBadge && !ipTypeBadge.classList.contains('ip-type-admin')) {
                        // Cambiar de "Cliente" a "No disponible" con color rojo
                        ipTypeBadge.className = 'ip-type-badge ip-type-admin';
                        ipTypeBadge.textContent = 'No disponible';
                    }
                }
            }
        }

        function showError(message, type = 'error', autohide = true) {
            let alertClass = 'alert-error';
            let icon = '⚠';

            if (type === 'success') {
                alertClass = 'alert-success';
                icon = '✓';
            } else if (type === 'info') {
                alertClass = 'alert-info';
                icon = '⏳';
            } else if (type === 'warning') {
                alertClass = 'alert-warning';
                icon = '⚠';
            }

            errorContainer.innerHTML = `
                <div class="alert ${alertClass}">
                    <span style="font-size: 1.5rem;">${icon}</span>
                    <span>${message}</span>
                </div>
            `;

            // Auto-ocultar solo si autohide es true
            if (autohide && type === 'success') {
                setTimeout(() => {
                    errorContainer.innerHTML = '';
                }, 5000);
            }
        }

        async function copyToClipboard(text, button) {
            try {
                await navigator.clipboard.writeText(text);

                const originalText = button.innerHTML;
                button.innerHTML = '✓ Copiado';
                button.classList.add('copied');

                setTimeout(() => {
                    button.innerHTML = originalText;
                    button.classList.remove('copied');
                }, 2000);
            } catch (error) {
                console.error('Error al copiar:', error);
                alert('Error al copiar al portapapeles');
            }
        }

        // Auto-focus en el campo de segmento
        document.getElementById('segment').focus();
    </script>
</body>

</html>