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暴力猴,之后才能安装此脚本。

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

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

您需要先安装一个扩展,例如 篡改猴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();
    }
})();