BOT - BJX1 ETA-CCP 🤖

Sistema automatizado para gestión de solicitudes ETA (Estimated Time of Arrival) 🕒 y CCP (Comprobante de Carga Procesada) 📄 en BJX1. Optimiza la comunicación con carriers mediante webhooks integrados con Amazon Chime, mejorando la eficiencia operativa en procesos IB/OB.

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         BOT - BJX1 ETA-CCP 🤖
// @namespace    http://tampermonkey.net/
// @version      3.1
// @description  Sistema automatizado para gestión de solicitudes ETA (Estimated Time of Arrival) 🕒 y CCP (Comprobante de Carga Procesada) 📄 en BJX1. Optimiza la comunicación con carriers mediante webhooks integrados con Amazon Chime, mejorando la eficiencia operativa en procesos IB/OB.
// @author       dnaldair - Transportation Operations Manager BJX1
// @match        https://trans-logistics.amazon.com/ssp/dock/hrz/ib*
// @match        https://trans-logistics.amazon.com/ssp/dock/hrz/ob*
// @grant        GM_xmlhttpRequest
// @license      MIT
// @supportURL   https://github.com/tuusuario/BOT-BJX1-ETA-CCP/issues
// ==/UserScript==

(function() {
    'use strict';

    // Configuración global y sistema de temas
    const APP_CONFIG = {
        version: '1.0',
        debug: false,
        theme: localStorage.getItem('preferred-theme') || 'light',
        animationsEnabled: true,
        notificationDuration: 3000,
        refreshInterval: 2000,
        sounds: {
            enabled: true,
            volume: 0.5
        }
    };

    // Sistema de temas
    const THEMES = {
        light: {
            primary: '#2196F3',
            secondary: '#FF9800',
            background: '#ffffff',
            surface: 'rgba(255, 255, 255, 0.95)',
            text: '#000000',
            textSecondary: '#666666',
            border: 'rgba(255, 255, 255, 0.18)',
            shadow: 'rgba(31, 38, 135, 0.15)'
        },
        dark: {
            primary: '#64B5F6',
            secondary: '#FFB74D',
            background: '#1a1a1a',
            surface: 'rgba(33, 33, 33, 0.95)',
            text: '#ffffff',
            textSecondary: '#bbbbbb',
            border: 'rgba(255, 255, 255, 0.1)',
            shadow: 'rgba(0, 0, 0, 0.3)'
        }
    };

    // Función para detectar si estamos en IB u OB
    function isInboundPage() {
        return window.location.href.includes('/hrz/ib');
    }

    // Log inicial para verificar que el script se está ejecutando
    console.log('Script iniciado - Versión:', APP_CONFIG.version);

    // Objeto para almacenar los timestamps de las solicitudes de ETA
    const etaRequestTimes = {};

    // Función para formatear la hora en 12h
    function formatTime(date) {
        return date.toLocaleString('en-US', {
            hour: 'numeric',
            minute: '2-digit',
            hour12: true
        });
    }
    // Configuración de webhooks por carrier
    const CARRIER_CONFIGS = {
    'TRRS': {
        webhook: 'https://hooks.chime.aws/incomingwebhooks/924a4843-2a80-42ba-954e-55674f09c54a?token=UVVnZEJVa1F8MXwyQ0ZmakgweEdtV1hiT0RBVkVkNkZuQWozYU0xZ1BqdkxEaGJUWHdFckJ3',
        color: '#FF5252',
        enabled: true
    },
    'MXBP': {
        webhook: 'https://hooks.chime.aws/incomingwebhooks/584cd794-5911-466b-ab8c-8fc6968d1d2d?token=cHZ0bENSNnB8MXx6ZTlZejFldThOTlEycEdWLXVlR3M2OXRnbEtwU1FrbVQ2QXpjdGROQ1JN',
        color: '#2196F3',
        enabled: true
    },
    'TRUCK': {
        webhook: 'https://hooks.chime.aws/incomingwebhooks/40bbdbf8-bd08-4f95-a275-c8a1dc1e1340?token=ODBYQjJoWER8MXxfUkNqbmxwYlIwWHd2NTdTWUcyNmotZUZYMmc5dFM4V0NVbUNRZ29lRUhF',
        color: '#2196F3',
        enabled: true
    },

        'MXVGO': {
        webhook: 'https://hooks.chime.aws/incomingwebhooks/2a86ea89-3b33-4c99-bb92-5d32f74eb6db?token=dEJFTEo1ekZ8MXxwSU02dlJhXzBBUXhQMFdxeWh4LXV0LXlLV1Rfa0g3Z29vWllMTWJwVDhz',
        color: '#00BCD4',
        enabled: true
    },
    'RLB1': {
        webhook: '',
        color: '#FFC107',
        enabled: false,
        isSpecial: true,
        specialMessage: 'Pendiente de carrier'
    },
    'MINAN': {
        webhook: '',
        color: '#4CAF50',
        enabled: false
    },
    'MPRU': {
        webhook: '',
        color: '#8BC34A',
        enabled: false
    },
    'MXEF': {
        webhook: '',
        color: '#CDDC39',
        enabled: false
    },
    'ARDMV': {
        webhook: 'https://hooks.chime.aws/incomingwebhooks/9e0c76df-370c-471f-b5d0-596d00a8907d?token=bVc5V2ZwT3B8MXxvN0RyOXRQTzVmbGlJLWFyaTRrbmZSYlg0cHFjOTA4WVp1UUlLdU55VHdN',
        color: '#FF9800',
        enabled: true
    },
    'MARVA': {
        webhook: 'https://hooks.chime.aws/incomingwebhooks/bb63ed20-e375-4c6a-b89b-16babe063c35?token=cHVzZHVJbDh8MXwtTk1NRFN5RmMzcHlvSk5xNlh5NkVNclhDSnpDcEVFel9JY1gydW5ZazNJ',
        color: '#FF5722',
        enabled: true
    },
    'MXAK': {
        webhook: 'https://hooks.chime.aws/incomingwebhooks/b9968bd0-f16e-4d6a-9d75-a83534792766?token=eG10ZmlWYmx8MXxLdUgzbjRzQThpOFQ0eWVaUV81MENWb3pIaTdObkRJRXpobE9mbTlHREp3',
        color: '#795548',
        enabled: true
    },
    'MXGTM': {
        webhook: 'https://hooks.chime.aws/incomingwebhooks/d041ec1b-9919-4d69-8971-153d88435a79?token=OHZkTEh6cUh8MXxqWkVxX29fZkcyZGhzXzh4RmR2ZGtjNHVnR0JXY3M1R3EzNWlraUVfam5j',
        color: '#9E9E9E',
        enabled: true
    },
    'MXLAR': {
        webhook: 'https://hooks.chime.aws/incomingwebhooks/4b999303-9aab-4504-bb47-6502c414991d?token=a2F5SzNvVVZ8MXxvVl9vd1pPLU1BV3dEZ3RBU3N2RlJkRTh4blZ6ZHc5OHZuOC1EdWJjeF9R',
        color: '#607D8B',
        enabled: true
    },
    'MTUML': {
        webhook: 'https://hooks.chime.aws/incomingwebhooks/b12a85fa-c0f3-46c9-bfab-9ad2d0ac33e1?token=MGlMSHdtTGl8MXxEaE5zVjFDNGI4Wi1BSlcyMkp2Qkd2OU1vQXJDZmpWNmdWSjMteWJWQ28w',
        color: '#3F51B5',
        enabled: true
    },
    'GOMX': {
        webhook: '',
        color: '#673AB7',
        enabled: false
    },
    'MGUR': {
        webhook: 'https://hooks.chime.aws/incomingwebhooks/86df076e-661e-4685-9dd8-4bb024dd4823?token=WlhuMHl3NXp8MXw1d0xtYVM1aEg2MnhZbWI3cmFJMERmNEZIdUl4aG5aUjRLUlh0NUl4elBB',
        color: '#9C27B0',
        enabled: true
    },
    'AWLRY': {
        webhook: 'https://hooks.chime.aws/incomingwebhooks/715ca057-b030-4d05-8f79-0e1d0ff5945a?token=SkdKeVR2Q0d8MXxBYXdYeE0yU3BBako3YnpaVi1ZdXR1TG5nTG15N05zTHZ3R1hkVkhneXZn',
        color: '#E91E63',
        enabled: true
    },
    'FMEX': {
        webhook: '',
        color: '#F44336',
        enabled: false
    },
    'AWJNS': {
        webhook: '',
        color: '#009688',
        enabled: false
    },
    'MXTX': {
        webhook: '',
        color: '#4DB6AC',
        enabled: false
    },
    'INTLO': {
        webhook: '',
        color: '#26A69A69A',
        enabled: false
    },
    'AQTNS': {
        webhook: 'https://hooks.chime.aws/incomingwebhooks/e8e2b828-33c6-49bf-9f20-976473fb3395?token=dzdqbnI1ZjF8MXxsd1daZnZBTzRuVUh4QmxLdUVTN20zaGxiTWFhUGNTSkkycW5wWjZjeXpB',
        color: '#66BB6A',
        enabled: true
    },
    'MXTDR': {
        webhook: '',
        color: '#9CCC65',
        enabled: false
    },
    'MXFH': {
        webhook: '',
        color: '#D4E157',
        enabled: false
    },
    'MXAX': {
        webhook: '',
        color: '#FFEE58',
        enabled: false
    },
    'RDPK': {
        webhook: '',
        color: '#FFCA28',
        enabled: false
    },
    'MXDLR': {
        webhook: '',
        color: '#FFA726',
        enabled: false
    },
    'SIFRA': {
        webhook: '',
        color: '#FF7043',
        enabled: false
    },
    'AMPM': {
        webhook: '',
        color: '#8D6E63',
        enabled: false
    },
    'AYLSO': {
        webhook: '',
        color: '#78909C',
        enabled: false
    },
    'PQEX': {
        webhook: '',
        color: '#5C6BC0',
        enabled: false
    },
    'TXDV': {
        webhook: 'https://hooks.chime.aws/incomingwebhooks/94f1e8a7-8fbc-4864-9a23-3e7aef38e234?token=emJ3VDdlYTl8MXxnazhRYnFrX2lxdWJCTXFCWFI1ZEtlRFRVcjlJdjROLUROX0czS0pqaHBZ',
        color: '#7E57C2',
        enabled: true
    },
    'DHLC': {
        webhook: '',
        color: '#EC407A',
        enabled: false
    },
    'NCSL': {
        webhook: '',
        color: '#AB47BC',
        enabled: false,
        isSpecial: true,
        specialMessage: 'VRID DUMMY'
    },
};

    // Array para almacenar unidades seleccionadas
    let unitsToRequest = [];

    // Sistema de notificaciones con sonido
    const NOTIFICATION_SOUNDS = {
        success: 'data:audio/mp3;base64,SUQzBAAAAAAAI1RTU0UAAAAPAAADTGF2ZjU4Ljc2LjEwMAAAAAAAAAAAAAAA//tQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWGluZwAAAA8AAAACAAAFbgCenp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6e//////////////////////////////////////////////////////////////////8AAAAATGF2YzU4LjEzAAAAAAAAAAAAAAAAJAAAAAAAAAAAAW7LZ3a6AAAAAAAAAAAAAAAAAAAA//sUZAAP8AAAaQAAAAgAAA0gAAABAAABpAAAACAAADSAAAAETEFNRTMuMTAwVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//sUZB4P8AAAaQAAAAgAAA0gAAABAAABpAAAACAAADSAAAAEVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//sUZDwP8AAAaQAAAAgAAA0gAAABAAABpAAAACAAADSAAAAEVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
        error: 'data:audio/mp3;base64,SUQzBAAAAAAAI1RTU0UAAAAPAAADTGF2ZjU4Ljc2LjEwMAAAAAAAAAAAAAAA//tQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWGluZwAAAA8AAAACAAAFbgCenp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6e//////////////////////////////////////////////////////////////////8AAAAATGF2YzU4LjEzAAAAAAAAAAAAAAAAJAAAAAAAAAAAAW7A+JvXAAAAAAAAAAAAAAAAAAAA//sUZAAP8AAAaQAAAAgAAA0gAAABAAABpAAAACAAADSAAAAETEFNRTMuMTAwVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//sUZB4P8AAAaQAAAAgAAA0gAAABAAABpAAAACAAADSAAAAEVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//sUZDwP8AAAaQAAAAgAAA0gA0gAAABAAABpAAAACAAADSAAAAEVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV'
    };
    // Estilos globales mejorados - Primera parte
    const styleSheet = document.createElement('style');
    styleSheet.innerHTML = `
    /* Animaciones Globales */
    @keyframes neonGlow {
        0% { box-shadow: 0 0 5px rgba(33, 150, 243, 0.5), 0 0 10px rgba(33, 150, 243, 0.3); }
        50% { box-shadow: 0 0 20px rgba(33, 150, 243, 0.8), 0 0 30px rgba(33, 150, 243, 0.5); }
        100% { box-shadow: 0 0 5px rgba(33, 150, 243, 0.5), 0 0 10px rgba(33, 150, 243, 0.3); }
    }

    @keyframes shimmer {
        0% { transform: translateX(-100%) rotate(45deg); }
        100% { transform: translateX(100%) rotate(45deg); }
    }

    @keyframes floatAnimation {
        0% { transform: translateY(0px); }
        50% { transform: translateY(-5px); }
        100% { transform: translateY(0px); }
    }

    @keyframes pulseAnimation {
        0% { transform: scale(1); }
        50% { transform: scale(1.02); }
        100% { transform: scale(1); }
    }

    @keyframes fadeIn {
        from { opacity: 0; transform: translateY(-5px); }
        to { opacity: 1; transform: translateY(0); }
    }

    @keyframes slideIn {
        from { transform: translateX(50px); opacity: 0; }
        to { transform: translateX(0); opacity: 1; }
    }

    @keyframes slideUp {
        from { transform: translateY(20px); opacity: 0; }
        to { transform: translateY(0); opacity: 1; }
    }

    @keyframes slideDown {
        from { transform: translateY(0); opacity: 1; }
        to { transform: translateY(20px); opacity: 0; }
    }

    @keyframes shake {
        0%, 100% { transform: translateX(0); }
        25% { transform: translateX(-2px); }
        75% { transform: translateX(2px); }
    }

    @keyframes sendingPulse {
        0% { transform: scale(1); }
        50% { transform: scale(0.95); }
        100% { transform: scale(1); }
    }

    /* Variables de tema */
    :root {
        --background: #ffffff;
        --text: #000000;
        --primary: #2196F3;
        --secondary: #FF9800;
        --success: #4CAF50;
        --warning: #FFC107;
        --error: #F44336;
    }

    /* Container principal */
    .button-container {
        display: flex;
        align-items: center;
        gap: 8px;
        padding: 6px 12px;
        background: rgba(255, 255, 255, 0.95);
        border-radius: 12px;
        box-shadow: 0 8px 32px rgba(31, 38, 135, 0.15);
        backdrop-filter: blur(8px);
        border: 1px solid rgba(255, 255, 255, 0.18);
        margin: 4px 0;
        flex-wrap: wrap;
        transition: all 0.3s ease;
    }

    .button-container:hover {
        transform: translateY(-2px);
        box-shadow: 0 12px 36px rgba(31, 38, 135, 0.25);
    }

    /* Botones de acción */
    .action-button {
        padding: 6px 12px;
        color: white;
        border: none;
        border-radius: 8px;
        cursor: pointer;
        font-size: 11px;
        font-weight: 600;
        transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
        min-width: 130px;
        max-width: 130px;
        height: 28px;
        line-height: 16px;
        text-align: center;
        position: relative;
        overflow: hidden;
        text-transform: uppercase;
        letter-spacing: 0.5px;
        background: linear-gradient(45deg, var(--primary), #1976D2);
        box-shadow: 0 2px 10px rgba(33, 150, 243, 0.3);
    }
`;
document.head.appendChild(styleSheet);

// Segunda parte de los estilos
const styleSheet2 = document.createElement('style');
styleSheet2.innerHTML = `
    .action-button {
        position: relative;
        overflow: hidden;
    }

    .action-button::before {
        content: '';
        position: absolute;
        top: -50%;
        left: -50%;
        width: 200%;
        height: 200%;
        background: linear-gradient(
            45deg,
            transparent,
            rgba(255, 255, 255, 0.2),
            transparent
        );
        transform: rotate(45deg);
        animation: shimmer 3s infinite;
        z-index: 1;
    }

    .eta-action-button {
        background: linear-gradient(45deg, #2196F3, #3F51B5);
        box-shadow: 0 0 15px rgba(33, 150, 243, 0.3);
    }

    .ccp-action-button {
        background: linear-gradient(45deg, #FF9800, #F57C00);
        box-shadow: 0 0 15px rgba(255, 152, 0, 0.3);
    }

    .action-button.selected {
        animation: pulseAnimation 2s infinite;
        background: linear-gradient(45deg, #4CAF50, #45a049);
        box-shadow: 0 0 20px rgba(76, 175, 80, 0.4);
    }

    .action-button:disabled {
        opacity: 0.6;
        cursor: not-allowed;
        transform: none !important;
    }

    .action-button:hover {
        transform: translateY(-2px);
        box-shadow: 0 8px 25px rgba(0, 0, 0, 0.2);
        filter: brightness(1.1);
    }

    /* Iconos de los botones */
    .eta-action-button::after {
        content: '🕒';
        font-size: 14px;
        margin-right: 4px;
        position: relative;
        z-index: 2;
    }

    .ccp-action-button::after {
        content: '📄';
        font-size: 14px;
        margin-right: 4px;
        position: relative;
        z-index: 2;
    }

    .action-button.selected::after {
        content: '✓';
        animation: checkmarkGlow 1.5s ease-in-out infinite alternate;
    }
`;
document.head.appendChild(styleSheet2);

// Tercera parte de los estilos
const styleSheet3 = document.createElement('style');
styleSheet3.innerHTML = `
    /* Carrier Indicator */
    .carrier-indicator {
        padding: 6px 12px;
        border-radius: 8px;
        color: white;
        font-size: 12px;
        font-weight: 700;
        letter-spacing: 1px;
        text-transform: uppercase;
        display: flex;
        align-items: center;
        gap: 8px;
        box-shadow: 0 4px 15px rgba(0,0,0,0.1);
        position: relative;
        overflow: hidden;
        background: linear-gradient(45deg, var(--carrier-color), var(--carrier-color-dark));
    }

    .carrier-indicator::before {
        content: '';
        position: absolute;
        top: -50%;
        left: -50%;
        width: 200%;
        height: 200%;
        background: linear-gradient(
            45deg,
            transparent,
            rgba(255, 255, 255, 0.2),
            transparent
        );
        transform: rotate(45deg);
        animation: shimmer 3s infinite;
    }

    .carrier-indicator.disabled {
        opacity: 0.7;
    }

    .carrier-indicator.disabled::after {
        content: "⚠️";
        font-size: 12px;
        margin-left: 4px;
        animation: shake 0.5s ease-in-out;
    }

.panel-container {
    position: fixed;
    top: 20px;
    right: 80px;
    width: auto;
    min-width: 240px;  /* Tamaño reducido */
    max-width: 280px;
    background: linear-gradient(135deg, rgba(255,255,255,0.95), rgba(240,240,255,0.95));
    border-radius: 16px;
    box-shadow: 0 8px 32px rgba(31, 38, 135, 0.25);
    z-index: 9999999;  /* Aumentado para asegurar que esté por encimaima */
    backdrop-filter: blur(12px);
    border: 1px solid rgba(255, 255, 255, 0.18);
    transform-origin: right top;
    animation: slideIn 0.5s ease-out;
    pointer-events: auto;  /* Asegura que sea interactivo */
}

.panel-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding: 12px 16px;
        background: linear-gradient(45deg, #1976D2, #2196F3);
        border-radius: 16px 16px 0 0;
        color: white;
    }

    .panel-title {
        font-size: 14px;
        font-weight: 600;
        text-transform: uppercase;
        letter-spacing: 1px;
        display: flex;
        align-items: center;
        gap: 8px;
    }

    .panel-controls {
        display: flex;
        gap: 8px;
    }

    .panel-minimize,
    .panel-drag {
        background: none;
        border: none;
        color: white;
        cursor: pointer;
        padding: 4px 8px;
        border-radius: 4px;
        transition: all 0.3s ease;
    }

    .panel-minimize:hover,
    .panel-drag:hover {
        background: rgba(255, 255, 255, 0.2);
        transform: translateY(-1px);
    }

    .panel-content {
        transition: all 0.3s ease;
    }

    .panel-content.minimized {
        height: 0;
        overflow: hidden;
        padding: 0;
    }

    .panel-footer {
        padding: 16px;
        display: flex;
        flex-direction: column;
        align-items: center;
        gap: 12px;
    }
`;
document.head.appendChild(styleSheet3);

// Cuarta parte de los estilos
const styleSheet4 = document.createElement('style');
styleSheet4.innerHTML = `
    /* Stats Container */
    .stats-container {
        display: flex;
        justify-content: space-around;
        padding: 16px;
        background: rgba(33, 150, 243, 0.1);
        border-radius: 12px;
        margin: 12px;
        backdrop-filter: blur(4px);
    }

    .stat-item {
        text-align: center;
        animation: floatAnimation 3s ease-in-out infinite;
    }

    .stat-label {
        font-size: 12px;
        color: #666;
        display: block;
        margin-bottom: 4px;
    }

    .stat-value {
        font-size: 24px;
        font-weight: 700;
        color: var(--primary);
        text-shadow: 0 0 10px rgba(33, 150, 243, 0.3);
    }

/* Botón principal de envío mejorado */
.send-button {
    padding: 12px 24px;
    background: linear-gradient(45deg, #1976D2, #2196F3, #42A5F5);
    color: white;
    border: none;
    border-radius: 12px;
    cursor: pointer;
    font-weight: 700;
    font-size: 14px;
    transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
    min-width: 200px;
    height: auto;
    display: flex;
    justify-content: center;
    align-items: center;
    text-align: center;
    line-height: 1.4;
    text-transform: uppercase;
    letter-spacing: 1px;
    position: relative;
    overflow: hidden;
    box-shadow: 0 4px 15px rgba(33, 150, 243, 0.3);
    border: 1px solid rgba(255, 255, 255, 0.2);
}`;

document.head.appendChild(styleSheet4);
// Quinta parte de los estilos
const styleSheet5 = document.createElement('style');
styleSheet5.innerHTML = `
    .send-button:hover {
        transform: translateY(-2px);
        box-shadow: 0 0 30px rgba(33, 150, 243, 0.6);
    }

    .send-button.sending {
        animation: sendingPulse 1s infinite;
    }

    /* Timestamps y mensajes */
    .eta-timestamp {
        font-size: 10px;
        color: #666;
        margin-top: 6px;
        text-align: center;
        font-style: italic;
        width: 100%;
        display: block;
        padding: 4px 8px;
        background: rgba(33, 150, 243, 0.1);
        border-radius: 6px;
        backdrop-filter: blur(4px);
        animation: fadeIn 0.3s ease-in-out;
    }

    .last-request-time {
        font-size: 11px;
        color: #666;
        text-align: center;
        margin-top: 8px;
        font-style: italic;
        background: rgba(33, 150, 243, 0.1);
        padding: 8px 16px;
        border-radius: 8px;
        backdrop-filter: blur(4px);
        animation: fadeIn 0.3s ease-in-out;
    }

/* Notificaciones mejoradas */
.notification {
    position: fixed;
    bottom: 20px;
    right: 20px;
    background: linear-gradient(135deg, rgba(255,255,255,0.95), rgba(240,240,255,0.95));
    padding: 16px 24px;
    border-radius: 12px;
    box-shadow: 0 8px 32px rgba(31, 38, 135, 0.25);
    backdrop-filter: blur(8px);
    border: 1px solid rgba(255, 255, 255, 0.18);
    animation: slideUp 0.3s ease-out;
    z-index: 1000000;
    display: flex;
    align-items: center;
    gap: 12px;
    min-width: 300px;
    transform-origin: right;
}

.notification-message {
    color: #000000;  /* Color más oscuro */
    font-size: 14px;
    font-weight: 700;  /* Más negrita */
    letter-spacing: 0.5px;  /* Mejor legibilidad */
}

.notification.success {
    border-left: 4px solid #4CAF50;
}

.notification.warning {
    border-left: 4px solid #FFC107;
}

.notification.error {
    border-left: 4px solid #F44336;
}

.notification-content {
    display: flex;
    align-items: center;
    gap: 12px;
}

.notification-icon {
    font-size: 20px;
}

    /* Tooltip mejorado */
    .tooltip {
        position: relative;
        display: inline-block;
    }

    .tooltip:hover::after {
        content: attr(data-tooltip);
        position: absolute;
        bottom: 100%;
        left: 50%;
        transform: translateX(-50%);
        padding: 8px 12px;
        background: rgba(0,0,0,0.8);
        color: white;
        border-radius: 6px;
        font-size: 12px;
        white-space: nowrap;
        z-index: 1000;
        animation: fadeIn 0.2s ease-out;
    }

    /* Efectos adicionales */
    @keyframes bounceIn {
        0% { transform: scale(0.3); opacity: 0; }
        50% { transform: scale(1.05); }
        70% { transform: scale(0.9); }
        100% { transform: scale(1); opacity: 1; }
    }

    /* Tema oscuro */
    [data-theme="dark"] {
        --background: #1a1a1a;
        --text: #ffffff;
        --text-secondary: #bbbbbb;
    }

    /* Efectos de carga */
    .loading-indicator {
        width: 20px;
        height: 20px;
        border: 2px solid #ffffff;
        border-top-color: transparent;
        border-radius: 50%;
        animation: spin 1s linear infinite;
        display: inline-block;
        vertical-align: middle;
        margin-left: 8px;
    }

    @keyframes spin {
        0% { transform: rotate(0deg); }
        100% { transform: rotate(360deg); }
    }

    .button-icon {
        margin-right: 8px;
    }

    /* Mejoras de accesibilidad */
    .action-button:focus,
    .send-button:focus,
    .panel-minimize:focus,
    .panel-drag:focus {
        outline: none;
        box-shadow: 0 0 0 3px rgba(33, 150, 243, 0.5);
    }

    /* Animación de éxito */
    @keyframes successPulse {
        0% { transform: scale(1); background: var(--success); }
        50% { transform: scale(1.05); background: #45a049; }
        100% { transform: scale(1); background: var(--success); }
    }
`;
document.head.appendChild(styleSheet5);
// Sistema de notificaciones mejorado
function playNotificationSound(type = 'success') {
    if (APP_CONFIG.sounds.enabled) {
        const audio = new Audio(NOTIFICATION_SOUNDS[type]);
        audio.volume = APP_CONFIG.sounds.volume;
        audio.play().catch(() => {});
    }
}

function showNotification(message, type = 'success') {
    // Eliminar notificaciones anteriores
    const existingNotifications = document.querySelectorAll('.notification');
    existingNotifications.forEach(notification => {
        notification.style.animation = 'slideDown 0.3s ease-out forwards';
        setTimeout(() => notification.remove(), 300);
    });

    const notification = document.createElement('div');
    notification.className = `notification ${type}`;
    notification.innerHTML = `
        <div class="notification-content">
            <span class="notification-icon">
                ${type === 'success' ? '✅' : type === 'warning' ? '⚠️' : '❌'}
            </span>
            <span class="notification-message">${message}</span>
        </div>
    `;
    document.body.appendChild(notification);

    playNotificationSound(type);

    setTimeout(() => {
        notification.style.animation = 'slideDown 0.3s ease-out forwards';
        setTimeout(() => notification.remove(), 300);
    }, APP_CONFIG.notificationDuration);
}

// Función para detectar el carrier
function detectCarrier(row) {
    const cells = Array.from(row.cells);
    for (const cell of cells) {
        const text = cell.textContent.trim();
        if (text.includes('[ATS_CONTRACTED]')) {
            console.log('Encontrado [ATS_CONTRACTED] en:', text);

            if (text.includes('RLB1')) {
                console.log('Carrier detectado: RLB1');
                return 'RLB1';
            }

            for (const carrier of Object.keys(CARRIER_CONFIGS)) {
                if (text.includes(carrier)) {
                    console.log('Carrier detectado:', carrier);
                    return carrier;
                }
            }
        }
    }
    console.log('No se encontró carrier específico, usando TRRS por defecto');
    return 'TRRS';
}

// Función para obtener el webhook según el carrier
function getWebhookUrl(carrier) {
    console.log('Obteniendo webhook para carrier:', carrier);

    if (!CARRIER_CONFIGS[carrier]) {
        console.error('Carrier no encontrado en configuración:', carrier);
        return null;
    }

    const webhook = CARRIER_CONFIGS[carrier].webhook;
    if (!webhook) {
        CARRIER_CONFIGS[carrier].enabled = false;
    }
    console.log('Webhook encontrado:', webhook || 'No configurado');

    return webhook;
}

// Función para limpiar el texto
function cleanText(text) {
    if (!text) return '';
    text = text.trim();
    if (text.includes('->')) {
        return text.replace('WT', '').split('📋')[0].split('📍')[0].trim();
    }
    return text.split('FMCTT')[0].split('📋')[0].split('🆔')[0].trim();
}

// Función para obtener el saludo según la hora
function getGreeting() {
    const hour = new Date().getHours();
    if (hour < 12) return 'buenos días';
    if (hour < 19) return 'buenas tardes';
    return 'buenas noches';
}

// Función para formatear mensajes ETA
function formatMessage(units) {
    let message = `/md **Hola team ${getGreeting()}, nos podrias apoyar con la ETA de las siguientes unidades, por favor, muchas gracias por su apoyo**

🚛 Apoyo con ETA de unidades:`;

    units.forEach(unit => {
        message += `

• 🛣️ Route: **${unit.route}**
• 📦 VRID: **${unit.vrid}**`;
    });

    message += `

**Quedamos atentos, gracias por su apoyo!**`;

    return message;
}

// Función para formatear mensajes CCP
function formatCCPMessage(units) {
    let message = `/md **Hola team ${getGreeting()}, nos podrian apoyar a compartir CCP para ${units.length > 1 ? 'las siguientes unidades' : 'la siguiente unidad'}:**

🚛 Unidades para CCP:`;

    units.forEach(unit => {
        message += `

• 🛣️ Route: **${unit.route}**
• 📦 VRID: **${unit.vrid}**`;
    });

    message += `

**Gracias por su apoyo!**`;

    return message;
}
// Función para enviar mensaje al webhook
function sendWebhookMessage(message, carrier, type) {
    console.log('Iniciando envío de mensaje...', {message, carrier, type});

    if (!CARRIER_CONFIGS[carrier]) {
        console.error('Carrier no encontrado:', carrier);
        showNotification(`Error: Carrier ${carrier} no encontrado`, 'error');
        return;
    }

    if (!CARRIER_CONFIGS[carrier].enabled) {
        console.warn('Carrier deshabilitado:', carrier);
        showNotification(`El carrier ${carrier} no tiene webhook configurado aún`, 'warning');
        return;
    }

    const webhookUrl = getWebhookUrl(carrier);
    if (!webhookUrl) {
        console.error('No se encontró URL del webhook para:', carrier);
        showNotification(`Error: No hay URL de webhook para ${carrier}`, 'error');
        return;
    }

    // Mostrar notificación de envío con animación
    showNotification(`Enviando solicitud a ${carrier}...`, 'info');

    // Agregar animación de carga al botón correspondiente
    const buttons = document.querySelectorAll(`.${type}-action-button[data-carrier="${carrier}"].selected`);
    buttons.forEach(button => button.classList.add('loading'));

    const data = JSON.stringify({ Content: message }); // Corregido aquí

    try {
        GM_xmlhttpRequest({
            method: 'POST',
            url: webhookUrl,
            data: data,
            headers: {
                'Content-Type': 'application/json'
            },
            onload: function(response) {
                console.log('Respuesta:', response);

                if (response.status === 200) {
                    handleSuccessfulRequest(carrier, type, buttons);
                } else {
                    handleFailedRequest(carrier, response.status);
                }
            },
            onerror: function(error) {
                handleFailedRequest(carrier, error.message || 'Error desconocido');
            }
        });
    } catch (error) {
        handleFailedRequest(carrier, error.message);
    }
}

// Manejador de solicitud exitosa
function handleSuccessfulRequest(carrier, type, buttons) {
    const successMessage = `${type === 'eta' ? 'ETA' : 'CCP'} solicitado exitosamente a ${carrier}`;
    showNotification(successMessage, 'success');

    // Actualizar timestamps y efectos visuales
    if (type === 'eta') {
        updateEtaTimestamps(carrier);
    }

    // Efectos visuales en botones
    buttons.forEach(button => {
        button.classList.remove('loading');
        button.style.animation = 'successPulse 0.5s ease';

        setTimeout(() => {
            button.classList.remove('selected');
            button.textContent = type === 'eta' ? 'Solicitar ETA' : 'Solicitar CCP';
            button.style.backgroundColor = type === 'eta' ? '#2196F3' : '#FF9800';
            button.style.animation = '';
        }, 500);
    });

    // Actualizar lista de solicitudes y panel
    unitsToRequest = unitsToRequest.filter(u => !(u.carrier === carrier && u.type === type));
    updatePanel();
    updateStatistics();
}

// Manejador de solicitud fallida
function handleFailedRequest(carrier, errorMessage) {
    console.error('Error en la solicitud:', errorMessage);
    showNotification(`Error al enviar mensaje a ${carrier}: ${errorMessage}`, 'error');

    // Remover estados de carga
    document.querySelectorAll('.action-button.loading').forEach(button => {
        button.classList.remove('loading');
    });
}

// Función para crear el panel principal mejorado
function createWebhookPanel() {
    console.log('Creando panel de webhook...');
    const existingPanel = document.querySelector('.panel-container');
    if (existingPanel) return;

    const panel = document.createElement('div');
    panel.className = 'panel-container';
    panel.innerHTML = `
        <div class="panel-header">
            <div class="panel-title">
                <span class="robot-icon">🤖</span>
                Control de Solicitudes - dnaldair
                <span class="version-badge" title="Versión ${APP_CONFIG.version}">v${APP_CONFIG.version}</span>
            </div>
            <div class="panel-controls">
                <button class="panel-minimize tooltip" data-tooltip="Minimizar panel" title="Minimizar">_</button>
                <button class="panel-drag tooltip" data-tooltip="Mover panel" title="Mover">⋮</button>
            </div>
        </div>
        <div class="panel-content">
            <div class="stats-container">
                <div class="stat-item tooltip" data-tooltip="Total de ETAs pendientes">
                    <span class="stat-label">ETAs</span>
                    <span class="stat-value" id="etaCount">0</span>
                </div>
                <div class="stat-item tooltip" data-tooltip="Total de CCPs pendientes">
                    <span class="stat-label">CCPs</span>
                    <span class="stat-value" id="ccpCount">0</span>
                </div>
            </div>
            <div class="panel-footer">
                <button id="sendRequest" class="send-button tooltip" data-tooltip="Enviar todas las solicitudes pendientes">
                    <span class="button-icon">📤</span>
                    <span class="button-text">Enviar Solicitudes</span>
                </button>
                <div id="lastRequestTime" class="last-request-time"></div>
            </div>
        </div>
    `;

    document.body.appendChild(panel);
    console.log('Panel agregado al DOM exitosamente');

    // Inicializar funcionalidades del panel
    initializePanelControls(panel);
}

// Función para inicializar los controles del panel
function initializePanelControls(panel) {
    const minimizeButton = panel.querySelector('.panel-minimize');
    const panelContent = panel.querySelector('.panel-content');
    const sendButton = panel.querySelector('#sendRequest');

    // Minimizar/Maximizar
    minimizeButton.addEventListener('click', () => {
        panelContent.classList.toggle('minimized');
        minimizeButton.textContent = panelContent.classList.contains('minimized') ? '+' : '_';
        minimizeButton.setAttribute('data-tooltip',
            panelContent.classList.contains('minimized') ? 'Maximizar panel' : 'Minimizar panel');
    });

    // Manejo de envío de solicitudes
    sendButton.addEventListener('click', () => {
        if (unitsToRequest.length === 0) {
            showNotification("Selecciona al menos una unidad antes de enviar la solicitud", 'warning');
            return;
        }

        const now = new Date();
        document.getElementById('lastRequestTime').textContent =
            `Última solicitud: ${formatTime(now)}`;

        sendButton.classList.add('sending');

        const groupedRequests = unitsToRequest.reduce((acc, unit) => {
            const key = `${unit.carrier}-${unit.type}`;
            if (!acc[key]) acc[key] = [];
            acc[key].push(unit);
            return acc;
        }, {});

        updateRequestCounters(groupedRequests);

        Object.entries(groupedRequests).forEach(([key, units]) => {
            const [carrier, type] = key.split('-');
            const message = type === 'eta' ? formatMessage(units) : formatCCPMessage(units);
            sendWebhookMessage(message, carrier, type);
        });

        setTimeout(() => {
            sendButton.classList.remove('sending');
        }, 1000);
    });

    // Hacer el panel draggable
    makeDraggable(panel);
}

// Función para actualizar timestamps de ETA
function updateEtaTimestamps(carrier) {
    const now = new Date();
    unitsToRequest.forEach(unit => {
        if (unit.type === 'eta' && unit.carrier === carrier) {
            etaRequestTimes[unit.vrid] = now;

            const button = document.querySelector(`.eta-action-button[data-carrier="${carrier}"][data-vrid="${unit.vrid}"]`);
            if (button) {
                let timestampDiv = button.parentElement.querySelector('.eta-timestamp');
                if (!timestampDiv) {
                    timestampDiv = document.createElement('div');
                    timestampDiv.className = 'eta-timestamp';
                    button.parentElement.appendChild(timestampDiv);
                }
                timestampDiv.textContent = `Última solicitud: ${formatTime(now)}`;
                timestampDiv.style.animation = 'fadeIn 0.3s ease-in-out';
            }
        }
    });
}

// Función para actualizar estadísticas
function updateStatistics() {
    const stats = unitsToRequest.reduce((acc, unit) => {
        acc[unit.type]++;
        return acc;
    }, { eta: 0, ccp: 0 });

    animateCounterUpdate('etaCount', stats.eta);
    animateCounterUpdate('ccpCount', stats.ccp);
}

// Función para animar actualización de contadores
function animateCounterUpdate(elementId, newValue) {
    const element = document.getElementById(elementId);
    if (!element) return;

    const currentValue = parseInt(element.textContent);
    if (currentValue === newValue) return;

    element.style.animation = 'none';
    element.offsetHeight; // Trigger reflow
    element.style.animation = 'pulseAnimation 0.5s ease-out';
    element.textContent = newValue;
}
// Función mejorada para manejar el clic del botón
function handleButtonClick(e, buttonElement, button, route, vrid, carrier) {
    e.stopPropagation();
    const selected = buttonElement.classList.contains('selected');

    if (!selected) {
        selectButton(buttonElement, button, route, vrid, carrier);
    } else {
        deselectButton(buttonElement, button, vrid);
    }

    updatePanel();
}

// Función para seleccionar botón
function selectButton(buttonElement, button, route, vrid, carrier) {
    buttonElement.classList.add('selected');
    buttonElement.textContent = button.type === 'eta' ? 'ETA Solicitada' : 'CCP Solicitada';
    buttonElement.style.backgroundColor = button.selectedColor;

    // Efecto de selección
    buttonElement.style.animation = 'pulseAnimation 0.5s ease-out';
    setTimeout(() => {
    buttonElement.style.animation = '';
}, 500);


    if (button.type === 'eta') {
        addEtaTimestamp(buttonElement, vrid);
    }

    unitsToRequest.push({ route, vrid, carrier, type: button.type });

    // Efecto visual en el contenedor de estadísticas
    const statsContainer = document.querySelector('.stats-container');
    if (statsContainer) {
        statsContainer.style.animation = 'shake 0.5s ease-out';
        setTimeout(() => {
    statsContainer.style.animation = '';
}, 500);

    }
}

// Función para deseleccionar botón
function deselectButton(buttonElement, button, vrid) {
    buttonElement.classList.remove('selected');
    buttonElement.textContent = button.type === 'eta' ? 'Solicitar ETA' : 'Solicitar CCP';
    buttonElement.style.backgroundColor = button.color;

    if (button.type === 'eta') {
        removeEtaTimestamp(buttonElement, vrid);
    }

    unitsToRequest = unitsToRequest.filter(
        u => !(u.vrid === vrid && u.type === button.type)
    );
}

// Función para agregar timestamp de ETA
function addEtaTimestamp(buttonElement, vrid) {
    const now = new Date();
    etaRequestTimes[vrid] = now;

    let timestampDiv = buttonElement.parentElement.querySelector('.eta-timestamp');
    if (!timestampDiv) {
        timestampDiv = document.createElement('div');
        timestampDiv.className = 'eta-timestamp';
        buttonElement.parentElement.appendChild(timestampDiv);
    }

    timestampDiv.textContent = `Última solicitud: ${formatTime(now)}`;
    timestampDiv.style.animation = 'fadeIn 0.3s ease-in-out';
}

// Función para remover timestamp de ETA
function removeEtaTimestamp(buttonElement, vrid) {
    const timestampDiv = buttonElement.parentElement.querySelector('.eta-timestamp');
    if (timestampDiv) {
        timestampDiv.style.animation = 'fadeOut 0.3s ease-out';
        setTimeout(() => timestampDiv.remove(), 300);
    }
    delete etaRequestTimes[vrid];
}

// Función mejorada para actualizar el panel
function updatePanel() {
    const button = document.getElementById('sendRequest');
    if (!button) return;

    const etaUnits = unitsToRequest.filter(u => u.type === 'eta');
    const ccpUnits = unitsToRequest.filter(u => u.type === 'ccp');

    let buttonContent = `
        <span class="button-icon">📤</span>
        <span class="button-text">
            ${unitsToRequest.length === 0 ? 'Enviar Solicitudes' : ''}
    `;

    if (etaUnits.length > 0) {
        buttonContent += `
            <div class="request-group">
                <span class="group-label">ETA:</span>
                <span class="group-vrids">${etaUnits.map(u => u.vrid).join(', ')}</span>
            </div>
        `;
    }

    if (ccpUnits.length > 0) {
        buttonContent += `
            <div class="request-group">
                <span class="group-label">CCP:</span>
                <span class="group-vrids">${ccpUnits.map(u => u.vrid).join(', ')}</span>
            </div>
        `;
    }

    buttonContent += '</span>';
    button.innerHTML = buttonContent;

    // Actualizar estado del botón
    button.disabled = unitsToRequest.length === 0;
    button.classList.toggle('has-requests', unitsToRequest.length > 0);

    // Actualizar estadísticas
    updateStatistics();
}

// Función para hacer el panel draggable mejorada
function makeDraggable(element) {
    let pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
    const dragHandle = element.querySelector('.panel-drag');

    dragHandle.onmousedown = dragMouseDown;

    function dragMouseDown(e) {
        e.preventDefault();
        pos3 = e.clientX;
        pos4 = e.clientY;
        document.onmouseup = closeDragElement;
        document.onmousemove = elementDrag;

        // Efecto visual al comenzar el arrastre
        element.style.transition = 'none';
        element.style.opacity = '0.8';
        element.style.transform = 'scale(0.98)';
    }

    function elementDrag(e) {
        e.preventDefault();
        pos1 = pos3 - e.clientX;
        pos2 = pos4 - e.clientY;
        pos3 = e.clientX;
        pos4 = e.clientY;

        // Limitar el movimiento dentro de la ventana
        const newTop = element.offsetTop - pos2;
        const newRight = parseInt(getComputedStyle(element).right) + pos1;

        if (newTop >= 0 && newTop <= window.innerHeight - element.offsetHeight) {
            element.style.top = newTop + "px";
        }
        if (newRight >= 0 && newRight <= window.innerWidth - element.offsetWidth) {
            element.style.right = newRight + "px";
        }
    }

    function closeDragElement() {
        document.onmouseup = null;
        document.onmousemove = null;

        // Restaurar estilos después del arrastre
        element.style.transition = 'all 0.3s ease';
        element.style.opacity = '1';
        element.style.transform = 'scale(1)';
    }
}
// Función para procesar las filas de la tabla
function processTableRows(table) {
    const rows = table.getElementsByTagName('tr');
    console.log(`Procesando ${rows.length} filas`);

    for (let i = 1; i < rows.length; i++) {
        const row = rows[i];

        if (row.querySelector('.button-container')) {
            console.log(`Fila ${i}: Ya tiene botones`);
            continue;
        }

        const cells = row.cells;
        if (!cells || cells.length === 0) continue;

        let route = '';
        let vrid = '';
        let foundRoute = false;
        let foundVrid = false;

        for (let j = 0; j < cells.length; j++) {
            const cellText = cells[j].textContent.trim();
            if (cellText.includes('->')) {
                route = cleanText(cellText);
                foundRoute = true;
            }
            if (/^\d{3}[A-Z0-9]+/.test(cellText)) {
                vrid = cleanText(cellText);
                foundVrid = true;
            }
        }

        if (!foundRoute || !foundVrid) {
            console.log(`Fila ${i}: No se encontró route o VRID`);
            continue;
        }

        const carrier = detectCarrier(row);
        console.log(`Fila ${i}: Route=${route}, VRID=${vrid}, Carrier=${carrier}`);

        const buttonContainer = document.createElement('div');
        buttonContainer.className = 'button-container';

        const carrierIndicator = document.createElement('span');
        carrierIndicator.className = `carrier-indicator ${!CARRIER_CONFIGS[carrier].enabled ? 'disabled' : ''}`;
        carrierIndicator.textContent = carrier;
        carrierIndicator.style.backgroundColor = CARRIER_CONFIGS[carrier].color;
        buttonContainer.appendChild(carrierIndicator);

        if (CARRIER_CONFIGS[carrier].isSpecial) {
            const specialMessage = document.createElement('div');
            specialMessage.className = 'special-message';
            specialMessage.textContent = CARRIER_CONFIGS[carrier].specialMessage;
            buttonContainer.appendChild(specialMessage);
        } else {
            const buttons = [
                { type: 'eta', text: 'Solicitar ETA', color: '#2196F3', selectedColor: '#4CAF50' }
            ];

            if (!isInboundPage()) {
                buttons.push({ type: 'ccp', text: 'Solicitar CCP', color: '#FF9800', selectedColor: '#E65100' });
            }

            buttons.forEach(button => {
                const buttonElement = document.createElement('button');
                buttonElement.className = `action-button ${button.type}-action-button`;
                buttonElement.textContent = button.text;
                buttonElement.style.backgroundColor = button.color;
                buttonElement.dataset.carrier = carrier;
                buttonElement.dataset.vrid = vrid;
                buttonElement.disabled = !CARRIER_CONFIGS[carrier].enabled;
                buttonElement.title = CARRIER_CONFIGS[carrier].enabled ?
                    `Solicitar ${button.type.toUpperCase()}` :
                    'Carrier no configurado';

                buttonElement.addEventListener('click', (e) =>
                    handleButtonClick(e, buttonElement, button, route, vrid, carrier)
                );

                buttonContainer.appendChild(buttonElement);
            });
        }

        const lastCell = cells[cells.length - 1];
        lastCell.appendChild(buttonContainer);
        console.log(`Fila ${i}: Botones agregados`);
    }
}

// Función para agregar botones a la tabla
function addActionButtons() {
    const tables = document.querySelectorAll('table');
    console.log(`Encontradas ${tables.length} tablas`);

    tables.forEach((table, index) => {
        console.log(`Procesando tabla ${index + 1}`);
        processTableRows(table);
    });
}

// Función para actualizar contadores
function updateRequestCounters(groupedRequests) {
    const etaCount = document.getElementById('etaCount');
    const ccpCount = document.getElementById('ccpCount');

    let etaTotal = 0;
    let ccpTotal = 0;

    Object.entries(groupedRequests).forEach(([key, units]) => {
        const [, type] = key.split('-');
        if (type === 'eta') etaTotal += units.length;
        if (type === 'ccp') ccpTotal += units.length;
    });

    if (etaCount) etaCount.textContent = etaTotal;
    if (ccpCount) ccpCount.textContent = ccpTotal;
}

// Función de inicialización mejorada
function init() {
    console.log('Iniciando script versión:', APP_CONFIG.version);

    // Mostrar notificación de inicio
    showNotification('Bot ETA-CCP iniciado correctamente', 'success');

    // Crear panel con efecto de entrada
    createWebhookPanel();

    // Observar cambios en el DOM
const observer = new MutationObserver((mutations) => {
    // Debounce para evitar múltiples actualizaciones
    if (window.updateTimeout) clearTimeout(window.updateTimeout);
    window.updateTimeout = setTimeout(() => {
        if (APP_CONFIG.debug) console.log('Cambios detectados en el DOM');
        addActionButtons();
    }, 100);
});

observer.observe(document.body, {
    childList: true,
    subtree: true,
    attributeFilter: ['class']
});
    // Actualizar botones periódicamente
    setInterval(addActionButtons, APP_CONFIG.refreshInterval);

    // Inicializar tema
    const savedTheme = localStorage.getItem('preferred-theme') || 'light';
    document.documentElement.setAttribute('data-theme', savedTheme);
}

    // Iniciar cuando el documento esté listo
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }
})();