{{-- resources/views/dashboard-api/dashboard_new.blade.php --}}

@extends('header_nuevo_generico')

@section('styles')
    {{-- ============================================= --}}
    {{-- == ESTILOS EXACTAMENTE COMO LOS PROPORCIONASTE == --}}
    {{-- ============================================= --}}
    <link rel="stylesheet" href="{{ URL::asset('/Libreria_CA/css/vista_generica.css') }}">
    <style>
        .api-nav{
            width:250px;
            border-top-left-radius: 1.5rem !important;
            border-top-right-radius: 1.5rem !important;
            border: 1px solid white !important;
            text-align: center;
        }
        .card-procesos{
            border-radius: 1.0rem !important;
            width:250px; /* MANTENIDO */
            height:150px; /* MANTENIDO */
            /* display: flex; */ /* QUITADO - Volviendo al original */
            /* flex-direction: column; */ /* QUITADO - Volviendo al original */
        }

        .card-procesos-cuerpo{
            border-radius: 1.0rem !important;
            width:450px; /* MANTENIDO */
            height:172px; /* MANTENIDO */
            /* display: flex; */ /* QUITADO */
            /* flex-direction: column; */ /* QUITADO */
        }
        .graficos_style{
            border-radius: 1.0rem !important;
            height:350px !important;
             background: white; /* Fondo por defecto */
        }

         .grafico-sin-datos { /* Estilo añadido para mensajes "sin datos" */
             display: flex;
             flex-direction: column;
             justify-content: center;
             align-items: center;
             height: 100%;
             text-align: center;
             padding: 20px;
             background: #f8f9fa;
             border-radius: 1.0rem;
             color: #6c757d;
         }
         .grafico-sin-datos i { font-size: 2.5rem; margin-bottom: 0.5rem; }

        /* Card sin datos - MANTENIDO */
        .card-sin-datos{
            border-radius: 1.0rem !important;
            width:250px;
            height:150px;
        }

        /* Tooltip styles - MANTENIDO */
        .info-icon { position: relative; display: inline-block; cursor: pointer; } /* Añadido cursor */
        .info-icon .tooltip-text {
            visibility: hidden;
            width: 200px;
            background-color: #333;
            color: #fff;
            text-align: center;
            border-radius: 6px;
            padding: 8px;
            position: absolute;
            z-index: 1;
            bottom: 100%;
            left: 98%;
            transform: translateX(-100%); /* Ajuste para alinear a la derecha */
            opacity: 0;
            transition: opacity 0.3s;
        }
        .info-icon .tooltip-text::after { /* Flecha */
            content: "";
            position: absolute;
            top: 100%;
            right: 10px; /* Posición desde la derecha */
            margin-left: -5px;
            border-width: 5px;
            border-style: solid;
            border-color: #333 transparent transparent transparent;
        }
        .info-icon:hover .tooltip-text {
            visibility: visible;
            opacity: 1;
        }

        /* Botones período - MANTENIDO */
        .periodo-btn {
            border: 1px solid #1a4e3b;
            background-color: white;
            color: #1a4e3b;
            border-radius: 20px;
            padding: 5px 20px;
            font-weight: 500;
            transition: background-color 0.3s ease, color 0.3s ease;
        }
        .periodo-btn.active {
            background-color: #d0f0e4; /* verde suave */
            color: #1a4e3b;
            border: 1px solid #d0f0e4; /* Borde igual al fondo */
        }
         /* Alineación texto card - MANTENIDO (si estaba antes) */
         /* Si necesitas forzar alineación vertical, puedes necesitar flexbox de nuevo,
            pero lo dejo como estaba según tu instrucción. */
        /* .card-procesos .fs-2, .card-procesos-cuerpo .fs-2 { margin-top: auto; } */ /* QUITADO */
    </style>
    {{-- ============================================= --}}
   {{-- == FIN ESTILOS EXACTAMENTE COMO LOS PROPORCIONASTE == --}}
    {{-- ============================================= --}}
@endsection

@section('main')
<input type="hidden" id="token" name="_token" value="{{ csrf_token() }}">

{{-- Título y Navegación Superior (SIN CAMBIOS) --}}
<div class="rectangle_bg_backend align-items-start pt-5 pb-5 mt-5 mb-5">
    <div class="d-flex flex-column" style="width: 100%;">
        <div class="d-flex align-items-center mt-2">
                <h1 class="title_page mb-0" style="font-size: 1.5rem">Gestor de APIs</h1>
            </div>
        <div class="nav-apis nav-container pt-4" style="border-bottom: 1px solid #dee2e6;">
            <ul class="nav nav-tabs border-0"> 
                <li class="nav-item rounder"> <a class="nav-link api-nav text-secondary fs-7 me-1 " href="/dashboard-api/clientes-apis" disabled
                    style="background-color: #507d70 !important; color: white !important;">Clientes y APIs</a> 
                </li>
                <li class="nav-item"> 
                    <a class="nav-link api-nav active fs-7 me-1" aria-current="page" href="#" style="color: black; border-bottom: 2px solid #0d6efd;">Supervisión de APIs</a> 
                </li>
                <li class="nav-item">
                    <a class="nav-link api-nav text-secondary fs-7" href="#" disabled style="background-color: #507d70 !important; color: white !important;">Información de APIs</a>
                </li>
            </ul>
        </div>
    </div>
</div>

{{-- Contenido Principal del Dashboard --}}
<div style="display: flex; justify-content: center; align-items: flex-start; width: 100%;">
    <div class="content-target" style="width: 98%; ">
        <div class="content-box">
            <div class="mt-2">
                <div id="contenedor">

                    {{-- FILTROS (HTML SIN CAMBIOS) --}}
                    <div id="contenedor-botones" class="d-flex flex-wrap align-items-center gap-3 mt-3 mb-4 p-3 bg-light rounded shadow-sm">
                        
                        <button id="periodo_mensual" class="btn periodo-btn">Mensual</button>
                        <button id="periodo_diario" class="btn periodo-btn">Diario</button>
                        <button id="periodo_actual" class="btn periodo-btn">Actual</button>


                        <select class="form-select" id="mes_seleccion" style="width: auto; display: none;">
                            @php
                                $fecha = \Carbon\Carbon::now();
                                $fecha->locale('es');
                            @endphp

                            @for ($i = 0; $i < 12; $i++)
                                {{-- Value: "11", Data-Anio: "2025", Label: "Noviembre" --}}
                                <option value="{{ $fecha->format('n') }}" data-anio="{{ $fecha->format('Y') }}">
                                    {{ ucfirst($fecha->translatedFormat('F Y')) }}
                                </option>
                                
                                @php $fecha->subMonth(); @endphp
                            @endfor
                        </select>

                        <select class="form-select" id="fecha_seleccion" style="width: auto; display: none;">
                            {{-- Opciones llenadas por JS --}}
                        </select>

                        <select id="producto" class="form-select ms-auto" style="width: auto;">
                            <option value="" selected>Todas las APIs</option>
                             @isset($productosApis)
                                @foreach($productosApis as $producto)
                                    <option value='{{ $producto->producto }}'>{{ strtoupper($producto->nombre_producto) }}</option>
                                @endforeach
                            @endisset
                        </select>

                        <select id="cliente" class="form-select" style="width: auto;">
                            <option value="" selected>Todos los clientes</option>
                             @isset($clientesApis)
                                @foreach($clientesApis as $cliente)
                                    <option value="{{ $cliente->cliente }}">{{ strtoupper($cliente->nombre_cliente) }}</option>
                                @endforeach
                            @endisset
                        </select>
                    </div>

                    {{-- ========================================================== --}}
                    {{-- == CARDS Y GRÁFICOS (HTML Preparado para llenado con JS) == --}}
                    {{-- ========================================================== --}}

                    {{-- FILA 1: Cards Métricas Principales y "Próximamente" --}}
                    <div class="row g-3 mb-4">
                        <div class="col-lg-6 col-md-12"> {{-- Ajustado ancho para probar --}}
                            <div class="d-flex flex-wrap gap-3">
                                {{-- Card 1: Solicitudes Totales --}}
                                <div class="card-procesos card shadow p-3 flex-grow-1"> {{-- flex-grow-1 añadido para flexibilidad --}}
                                    <div class="d-flex justify-content-between align-items-center">
                                        <small class="text fs-7 pe-2 text-uppercase">Solicitudes Totales</small>
                                        <span class="info-icon"><i class="bi bi-info-circle"></i><span class="tooltip-text text-start fs-7">Total de llamadas (aciertos + errores).</span></span>
                                    </div>
                                    <small class="mes-consultado text-muted fs-7 pe-2 mb-1"></small>
                                    <h3 class="fs-2 text-start mt-auto" id="Soli_cant"><b><!-- JS --></b></h3> {{-- mt-auto para intentar empujar hacia abajo --}}
                                </div>

                                {{-- Card 2: Tiempo Promedio --}}
                                <div class="card-procesos card shadow p-3 flex-grow-1">
                                    <div class="d-flex justify-content-between align-items-center">
                                        <small class="text fs-7 pe-2 text-uppercase">Tiempo Promedio</small>
                                         <span class="info-icon"><i class="bi bi-info-circle"></i><span class="tooltip-text text-start fs-7">Tiempo promedio (seg) por solicitud.</span></span>
                                    </div>
                                    <small class="mes-consultado text-muted fs-7 pe-2 mb-1"></small>
                                    <h3 class="fs-2 text-start mt-auto" id="tempPros"><b><!-- JS --></b></h3>
                                </div>

                                {{-- Card 3: Última Consulta Renaper (Próximamente) --}}
                                <div class="card-procesos card shadow p-3 flex-grow-1">
                                <div class="d-flex justify-content-between align-items-center">
                                        <small class="text fs-7 pe-2 text-uppercase">Ultima consulta Renaper</small>
                                         <span class="info-icon"><i class="bi bi-info-circle"></i><span class="tooltip-text text-start fs-7">Ultima consulta a renaper.</span></span>
                                    </div>
                                    <small class="mes-consultado text-muted fs-7 pe-2 mb-1"></small>
                                    <h3 class="fs-5 text-start mt-auto" id="UltRenaper"><b>{{$ultimaConsultaProvedoresArg[1]->computed1}}</b></h3>
                                </div>

                                {{-- Card 4: Aciertos --}}
                                <div class="card-procesos card shadow p-3 flex-grow-1">
                                     <div class="d-flex justify-content-between align-items-center">
                                        <small class="text fs-7 pe-2 text-uppercase">Aciertos</small>
                                         <span class="info-icon"><i class="bi bi-info-circle"></i><span class="tooltip-text text-start fs-7">Llamadas exitosas (consumo).</span></span>
                                    </div>
                                    <small class="mes-consultado text-muted fs-7 pe-2 mb-1"></small>
                                    <h3 class="fs-2 text-start mt-auto text-success" id="total_ok"><b><!-- JS --></b></h3>
                                </div>

                                {{-- Card 5: Errores --}}
                                <div class="card-procesos card shadow p-3 flex-grow-1">
                                    <div class="d-flex justify-content-between align-items-center">
                                        <small class="text fs-7 pe-2 text-uppercase">Errores</small>
                                         <span class="info-icon"><i class="bi bi-info-circle"></i><span class="tooltip-text text-start fs-7">Llamadas fallidas (no consumo).</span></span>
                                    </div>
                                    <small class="mes-consultado text-muted fs-7 pe-2 mb-1"></small>
                                    <h3 class="fs-2 text-start mt-auto text-danger" id="total_error"><b><!-- JS --></b></h3>
                                </div>

                                {{-- Card 6: Última Consulta ARCA (Próximamente) --}}
                                <div class="card-procesos card shadow p-3 flex-grow-1">
                                    <div class="d-flex justify-content-between align-items-center">
                                        <small class="text fs-7 pe-2 text-uppercase">Ultima consulta ARCA</small>
                                         <span class="info-icon"><i class="bi bi-info-circle"></i><span class="tooltip-text text-start fs-7">Ultima consulta a ARCA.</span></span>
                                    </div>
                                    <small class="mes-consultado text-muted fs-7 pe-2 mb-1"></small>
                                    <h3 class="fs-5 text-start mt-auto" id="UltArca"><b>{{$ultimaConsultaProvedoresArg[0]->computed1}}</b></h3>
                                </div>
                            </div>
                        </div>

                        {{-- Columna Derecha: Card Grande  --}}
                        <div class="col-lg-6 col-md-12">
                             <div class="card shadow bg-light d-flex flex-column justify-content-center align-items-center" style="border-radius: 1.0rem; height: 315px;">
                                 <div id="UptimeHeatmap" class="shadow w-100 h-100" style="border-radius: 1.0rem "></div> 
                            </div>
                        </div>
                    </div>

                    {{-- FILA 2: Gráficos Principales y Consumos Promedio --}}
                    <div class="row g-3 mb-4">
                        <div class="col-lg-3 col-md-6"> <div id="solicitudesTotales" class="graficos_style shadow"></div> </div>
                        <div class="col-lg-3 col-md-6"> <div id="apisConsumo" class="graficos_style shadow"></div> </div>
                        <div class="col-lg-3 col-md-6"> <div id="clientesConsumo" class="graficos_style shadow"></div> </div>
                        <div class="col-lg-3 col-md-6">
                             {{-- NOTA: Estas cards usan 'card-procesos-cuerpo' que SÍ tenía width y height fijos. Los mantuve según tu estilo. --}}
                            <div class="card-procesos-cuerpo card shadow p-3 w-100 mb-3">
                                <div class="d-flex justify-content-between align-items-center">
                                    <small class="text fs-7 pe-2 text-uppercase">Consumo Promedio / API*</small>
                                    <span class="info-icon"><i class="bi bi-info-circle"></i><span class="tooltip-text text-start fs-7">Aciertos totales / APIs disponibles</span></span>
                                </div>
                                <small class="mes-consultado text-muted fs-7 pe-2 mb-1"></small>
                                <h3 class="fs-2 text-start mt-auto" id="consumoPromedioApi"><b><!-- JS --></b></h3>
                                <small class="text-muted fs-7 mt-1">*Incluye solo aciertos</small>
                            </div>
                            <div class="card-procesos-cuerpo card shadow p-3 w-100">
                                <div class="d-flex justify-content-between align-items-center">
                                    <small class="text fs-7 pe-2 text-uppercase">Consumo Promedio / Cliente*</small>
                                     <span class="info-icon"><i class="bi bi-info-circle"></i><span class="tooltip-text text-start fs-7">Aciertos totales / Clientes activos</span></span>
                                </div>
                                <small class="mes-consultado text-muted fs-7 pe-2 mb-1"></small>
                                <h3 class="fs-2 text-start mt-auto" id="consumoPromedioCliente"><b><!-- JS --></b></h3>
                                <small class="text-muted fs-7 mt-1">*Incluye solo aciertos</small>
                            </div>
                        </div>
                    </div>


                    {{-- FILA 3: Gráficos de Errores y Tasa de Aciertos --}}
                    <div class="row g-3 mb-4">
                        <div class="col-lg-3 col-md-6"> <div id="TasadeErrores" class="graficos_style shadow"></div> </div>
                        <div class="col-lg-3 col-md-6"> <div id="ApimasErrores" class="graficos_style shadow"></div> </div>
                        <div class="col-lg-3 col-md-6"> <div id="CodigosResp" class="graficos_style shadow"></div> </div>
                        <div class="col-lg-3 col-md-6"> <div id="TortaPorcentaje" class="graficos_style shadow"></div> </div>
                    </div>

                     {{-- FILA 4: Gráficos de Tiempo y Tiempos Detallados --}}
                    <div class="row g-3 mb-4">
                        <div class="col-lg-3 col-md-6"> <div id="TiempoProcesamiento" class="graficos_style shadow"></div> </div>
                        <div class="col-lg-3 col-md-6"> <div id="ApismasLentas" class="graficos_style shadow"></div> </div>
                        <div class="col-lg-3 col-md-6"> <div id="DistriProce" class="graficos_style shadow"></div> </div>
                        <div class="col-lg-3 col-md-6">
                            {{-- NOTA: Esta card usa 'card-procesos-cuerpo'. --}}
                            <div class="card-procesos-cuerpo card shadow p-3 w-100 h-100">
                                <div class="d-flex justify-content-between align-items-center mb-1">
                                    <small class="text fs-7 pe-2 text-uppercase">Promedios Tiempo Procesamiento</small>
                                     <span class="info-icon"><i class="bi bi-info-circle"></i><span class="tooltip-text text-start fs-7">Promedios (seg) según filtros.<br>SID Datos/ARCA/WORLDSYS: Promedio específico del proveedor (si aplica).</span></span>
                                </div>
                                <small class="mes-consultado text-muted fs-7 pe-2 mb-2"></small>

                                <div class="mt-1 border-bottom pb-1">
                                    <div class="d-flex justify-content-between">
                                        <span class="fw-semibold nombre_tiempoProce" style="font-size: 0.8rem;"><!-- JS --></span>
                                        <span class="fw-bold text-dark promedio_duracion"><!-- JS --></span>
                                    </div>
                                </div>
                                <div id="proveedores_promedio"></div>
                            </div>
                        </div>
                    </div>

                </div> {{-- Fin #contenedor --}}
            </div>
        </div>
    </div>
</div>

{{-- Modal Recalculando (SIN CAMBIOS) --}}
<div class="modal fade" id="modalRecalculando" tabindex="-1" aria-labelledby="modalRecalculandoLabel" aria-hidden="true" data-bs-backdrop="static" data-bs-keyboard="false">
    <div class="modal-dialog modal-dialog-centered">
        <div class="modal-content">
            <div class="modal-body text-center">
                <div class="spinner-border text-primary" role="status">
                    <span class="visually-hidden">Recalculando...</span>
                </div>
                <p class="mt-2">Recalculando datos, por favor espere...</p>
            </div>
        </div>
    </div>
</div>

@endsection

@section('funcionesJS')
    <script src="{{ asset('/HighCharts/code/highcharts.js') }}"></script>
    <script src="{{ asset('/HighCharts/code/modules/accessibility.js')}}"></script>
    <script src="{{ asset('/HighCharts/code/modules/heatmap.js')}}"></script>
    <script>
        // Inyectar los datos iniciales desde el controlador PHP a JS
        const initialDashboardData = @json($initialData);

        // Variables globales
        let mesConsultadoGlobal = '';
        let subtituloGlobal = '';

        // --- Función Central para poblar la vista (cards y gráficos) ---
        function populateView(data) {
            //console.log("Populando vista con data:", data);

            if (!data || typeof data !== 'object' || !data.metadata || !data.cards || !data.graphs || typeof data.metadata !== 'object' || typeof data.cards !== 'object' || typeof data.graphs !== 'object') {
                //  console.error("populateView: Datos inválidos o incompletos recibidos:", data);
                if ($('#contenedor .alert-danger').length === 0) {
                    $('#contenedor').html('<div class="alert alert-danger text-center"><strong>Error Crítico:</strong> No se pudieron cargar o procesar los datos del dashboard. Por favor, contacte al soporte técnico.</div>');
                }
                $('#modalRecalculando').modal('hide');
                return;
            }

            // 1. Actualizar Metadatos y Texto en la UI
            mesConsultadoGlobal = data.metadata.mesConsultado || 'N/D';
            subtituloGlobal = data.metadata.subtitulo || '';
            $('.mes-consultado').html(mesConsultadoGlobal);

            // Funciones de formato (sin cambios)
            const formatNumber = (num) => (num !== null && num !== undefined && !isNaN(num)) ? num.toLocaleString('es-AR') : '--';
            const formatSeconds = (secs) => (secs !== null && secs !== undefined && !isNaN(secs)) ? parseFloat(secs).toFixed(2) : '--';
            const formatSecondsDetailed = (secs) => (secs !== null && secs !== undefined && !isNaN(secs)) ? parseFloat(secs).toFixed(3) : '--';
            const formatText = (text) => (typeof text === 'string' && text.trim() !== '') ? text.trim() : '--';

            // *** NUEVA FUNCIÓN AUXILIAR (definida fuera o antes de populateView) ***
            // function updateCardElement(element, rawValue, formatterFn, options = {}) { ... }
            // (ya la definimos arriba)

            // Opciones comunes para "no hay datos"
            const noDataOpts = {
                noDataMessage: 'Sin datos',
                //noDataIcon: '<sub style="font-size:0.6em; color:red;">🚫</sub>', // Ejemplo más elaborado
                // noDataIcon: '🤷‍♂️',
                 noDataIcon: '<i class="fas fa-chart-bar" style="opacity:0.5;"></i>', // si usas FontAwesome
            };

            // 2. Actualizar Cards usando la nueva función
            updateCardElement($('#Soli_cant b'), data.cards.solicitudes?.total, formatNumber, noDataOpts);
            updateCardElement($('#total_ok b'), data.cards.solicitudes?.ok, formatNumber, noDataOpts);
            updateCardElement($('#total_error b'), data.cards.solicitudes?.error, formatNumber, noDataOpts);
            updateCardElement($('#tempPros b'), data.cards.tiempoPromedioSegundos, formatSeconds, { ...noDataOpts, unit: 'seg' });

            //updateCardElement($('#UltRenaper b'), data.cards.Ultrenaper, formatSeconds, { ...noDataOpts, unit: 'seg' });
            //updateCardElement($('#UltArca b'), data.cards.Ultarca, formatSeconds, { ...noDataOpts, unit: 'seg' });



            updateCardElement(
                $('#consumoPromedioApi b'),
                data.cards.consumoPromedio?.porApi !== undefined ? Math.round(data.cards.consumoPromedio.porApi) : undefined, // Aseguramos pasar undefined si no existe
                formatNumber,
                noDataOpts
            );
            updateCardElement(
                $('#consumoPromedioCliente b'),
                data.cards.consumoPromedio?.porCliente !== undefined ? Math.round(data.cards.consumoPromedio.porCliente) : undefined,
                formatNumber,
                noDataOpts
            );

            const tiemposDet = data.cards.tiemposDetallados;
            $('#proveedores_promedio').empty();
            if (tiemposDet && typeof tiemposDet === 'object'){
                //console.log(tiemposDet);
                // Leemos nombres de cliente/producto desde la clave 'promedio_total_apis' (global)
                const global = tiemposDet.promedio_total_apis || {};
                //console.log(global);
                $('.nombre_tiempoProce').html(`${global.nombre_producto || 'Global'} - ${global.nombre_cliente || 'Todos'}`);
                $('.promedio_duracion').html((global.duracion) ? `${global.duracion}` : 'Sin datos') 
                // Iteramos cada proveedor de la colección y generamos el html y ponemos limite 6 items
                let count = 0;
                for (const key in tiemposDet) {
                    //Si hay 6 items se frena y no agrega mas
                    if (count >= 6) break;
                    const item = tiemposDet[key];
                    if (!item) continue;
                    if ( 'proveedor' in item ){
                        $('#proveedores_promedio').append(`
                            <div class="mt-2 border-bottom pb-1">
                                <div class="d-flex justify-content-between">
                                    <span class="fw-semibold">${item.proveedor ? item.proveedor : 'Sin datos'}</span>
                                    <span class="fw-bold text-dark">${item.duracion ? item.duracion : 'Sin datos'}</span>
                                </div>
                            </div>
                        `);
                    }
                    continue;
                } 
            };

            // 3. Llamar a las funciones para dibujar los gráficos (sin cambios aquí)
            const defaultGraphData = { categories: [], series: [] };
            const defaultPieData = { seriesData: [] };

            solicitudesTotales(data.graphs.solicitudesPeriodo || defaultGraphData);
            TasaAciertos(data.graphs.tasaAciertosErroresPie || defaultPieData);
            apisConsumo(data.graphs.consumoPorApi || defaultGraphData);
            clientesConsumo(data.graphs.consumoPorCliente || defaultGraphData);
            TiempoProcesamiento(data.graphs.tiempoProcesamiento || defaultGraphData);
            TasadeErrores(data.graphs.tasaErroresPorCodigo || defaultGraphData);
            ApimasErrores(data.graphs.apisConMasErrores || defaultGraphData);
            codigoResp(data.graphs.codigosRespuesta || defaultGraphData);
            ApismasLentas(data.graphs.apisMasLentas || defaultGraphData);
            DistriProce(data.graphs.distribucionTiempos || defaultGraphData);
            Heatmap(data.graphs.uptimeHeatmap || defaultGraphData);
        }

        function actualizarSelects() {
            let periodoActivo = $('.periodo-btn.active').attr('id');
            $('#mes_seleccion').toggle(periodoActivo === 'periodo_mensual');
            $('#fecha_seleccion').toggle(periodoActivo === 'periodo_diario');
        }

        // Llena el select de fechas con los últimos 30 días (formato YYYY-MM-DD)
        function llenarFechas() {
            const $fechaSelect = $('#fecha_seleccion');
            $fechaSelect.empty();
            let hoy = new Date();
            for(let i=1; i<=30; i++) {
                let dia = new Date(hoy);
                dia.setDate(hoy.getDate() - i); // días atrás
                let yyyy = dia.getFullYear();
                let mm = (dia.getMonth() + 1).toString().padStart(2, '0');
                let dd = dia.getDate().toString().padStart(2, '0');
                let valor = `${yyyy}-${mm}-${dd}`;
                $fechaSelect.append(`<option value="${valor}">${valor}</option>`);
            }
        }

        // Cuando cambie el periodo, actualizar selects y valores por defecto
        $('.periodo-btn').click(function() {
            $('.periodo-btn').removeClass('active');
            $(this).addClass('active');
            actualizarSelects();
            // Si es mensual, seleccionar mes actual por defecto
            if ($(this).attr('id') === 'periodo_mensual') {
                //alert('mensual');
                $("#mes_seleccion").prop("selectedIndex", 0);
                actualizarVista();
            } else if($(this).attr('id') === 'periodo_diario'){ // diario
                //alert('diario');
                llenarFechas();
                actualizarVista();
                $('#fecha_seleccion').val($('#fecha_seleccion option:first').val()); // el día anterior por defecto
            }else if($(this).attr('id') === 'periodo_actual'){
                //alert('clickactual');
                actualizarVistaActual();
            }
             // Actualizar vista al cambiar periodo
        });

        // --- Función AJAX para actualizar vista con filtros ---
        function actualizarVista() {
            let periodoId = $('.periodo-btn.active').attr('id') || 'periodo_mensual';
            let periodo = (periodoId === 'periodo_diario') ? 'diario' : 'mensual';

            let anio = null;
            let mes = null;
            let dia = null;

            if (periodo === 'mensual') {
                // Enviar mes seleccionado (número)
                // Obtenemos la opción seleccionada
                let $selectedOption = $('#mes_seleccion option:selected');
                
                // Capturamos el mes (value)
                let mesVal = $selectedOption.val();
                mes = mesVal ? parseInt(mesVal) : null;
                // Capturamos el año (data-anio)
                // Si no encuentra el atributo, usa el año actual por defecto
                let anioVal = $selectedOption.data('anio');
                anio = anioVal ? parseInt(anioVal) : new Date().getFullYear();
            } else {
                // Enviar día seleccionado (formato YYYY-MM-DD)
                let diaVal = $('#fecha_seleccion').val();
                if (!diaVal) {
                    // Si no hay día seleccionado, por defecto el día anterior a hoy
                    let hoy = new Date();
                    hoy.setDate(hoy.getDate() -1);
                    let yyyy = hoy.getFullYear();
                    let mm = (hoy.getMonth() + 1).toString().padStart(2, '0');
                    let dd = hoy.getDate().toString().padStart(2, '0');
                    dia = `${yyyy}-${mm}-${dd}`;
                } else {
                    dia = diaVal;
                }
            }

            let producto = $('#producto').val();
            let cliente = $('#cliente').val();

            //console.log("Enviando filtros:", { periodo, mes, dia, producto, cliente });

            
            //  let modal = bootstrap.Modal.getOrCreateInstance(document.getElementById('modalRecalculando')); //segun gpt boostrap 5 se debe llamar asi al modal....


            $.ajax({
                url: '/dashboard-api/json/filtrado',
                method: 'POST',
                data: { periodo, anio, mes, producto, cliente, dia, _token: $('#token').val() },
                dataType: 'json',
                beforeSend: function() {
                    $('#contenedor .alert').remove();
                    $('#modalRecalculando').modal('show');
                },
                success: function(response) {
                        setTimeout(function() {
                            $('#modalRecalculando').modal('hide');
                            populateView(response);
                        }, 500);
                    },
                    error: function(xhr, status, error) {
                        setTimeout(function() {
                            console.error('Error en AJAX:', status, error, xhr.responseText);
                            $('#contenedor').prepend(
                            '<div class="alert alert-warning alert-dismissible fade show" role="alert">' +
                            '<strong>¡Atención!</strong> No se encontraron datos para la combinación de filtros seleccionada.' +
                            '<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>' +
                            '</div>'
                            );
                            $('#modalRecalculando').modal('hide');
                        }, 500);
                    }
            });
        }
        function actualizarVistaActual() {

            let producto = $('#producto').val();
            let cliente = $('#cliente').val();

            //console.log("Enviando filtros:", { periodo, producto, cliente });

            
          //  let modal = bootstrap.Modal.getOrCreateInstance(document.getElementById('modalRecalculando')); //segun gpt boostrap 5 se debe llamar asi al modal....


            $.ajax({
                url: '/dashboard-api/json/actual',
                method: 'POST',
                data: {producto, cliente, _token: $('#token').val() },
                dataType: 'json',
                beforeSend: function() {
                    $('#contenedor .alert').remove();
                    $('#modalRecalculando').modal('show');
                },
                success: function(response) {
                        setTimeout(function() {
                            $('#modalRecalculando').modal('hide');
                            populateView(response);
                        }, 500);
                    },
                    error: function(xhr, status, error) {
                        setTimeout(function() {
                            console.error('Error en AJAX:', status, error, xhr.responseText);
                            $('#contenedor').prepend(
                            '<div class="alert alert-warning alert-dismissible fade show" role="alert">' +
                            '<strong>¡Atención!</strong> No se encontraron datos para la combinación de filtros seleccionada.' +
                            '<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>' +
                            '</div>'
                            );
                            $('#modalRecalculando').modal('hide');
                        }, 500);
                    }
            });
        }
        function updateCardElement(element, rawValue, formatterFn, options = {}) {
                const {
                    unit = '',
                    noDataMessage = 'No hay datos', // Mensaje por defecto
                    noDataIcon = '🤷', // Emoji por defecto (puedes usar un <i> de FontAwesome, etc.)
                    // Ejemplo con FontAwesome: noDataIcon = '<i class="fas fa-info-circle"></i>',
                    valueFormatterReturnsForNoData = '--' // Lo que tu formateador devuelve para "sin datos"
                } = options;

                let displayValue = formatterFn(rawValue); // Llama a tu función de formateo
                let isDataAvailable = true;

                // Comprobamos si el valor formateado indica "sin datos"
                // Esto ahora funcionará correctamente si formatterFn devuelve '--' para cadenas vacías.
                if (displayValue === valueFormatterReturnsForNoData) {
                    isDataAvailable = false;
                }
                // Las siguientes condiciones son más bien una salvaguarda adicional o para casos donde
                // el formateador podría no ser invocado o fallar por alguna razón no prevista.
                // Con los formateadores corregidos, la primera condición (displayValue === valueFormatterReturnsForNoData)
                // debería ser suficiente.
                else if (rawValue === null ||
                    rawValue === undefined ||
                    (typeof rawValue === 'number' && isNaN(rawValue)) ||
                    (typeof rawValue === 'string' && rawValue.trim() === '' && displayValue !== valueFormatterReturnsForNoData) // Caso borde por si el formateador no manejó bien ''
                    ) {
                    isDataAvailable = false;
                    // Si llegamos aquí y displayValue no es '--', forzamos el mensaje de no datos
                    // Esto es defensivo; idealmente, formatterFn ya devolvió '--'.
                    if (displayValue !== valueFormatterReturnsForNoData) {
                        console.warn("updateCardElement: Formatter function did not return the expected 'no data' string for a problematic rawValue. Raw value:", rawValue, "Formatter output:", displayValue);
                    }
                }


                const parentCard = element.closest('.card, .info-box'); // Intenta encontrar el contenedor de la card

                if (!isDataAvailable) {
                    element.html(`<span class="no-data-indicator"><span class="icon">${noDataIcon}</span> ${noDataMessage}</span>`);
                    if (parentCard && parentCard.length) { // Asegurarse que parentCard existe
                        parentCard.addClass('card-no-data');
                    }
                } else {
                    element.html(displayValue + (unit ? ' ' + unit : ''));
                    if (parentCard && parentCard.length) { // Asegurarse que parentCard existe
                        parentCard.removeClass('card-no-data');
                    }
                }
        }
        // --- Ejecución cuando el DOM está listo ---
        $(document).ready(function() {

            // 1. Poblar la vista con los datos INICIALES
            populateView(initialDashboardData);

            // 2. Configurar estado inicial de botones y selects
            const periodoInicial = initialDashboardData?.metadata?.periodo || 'mensual';
            $('.periodo-btn').removeClass('active');
            const mesActual = new Date().getMonth() + 1;
            const hoyStr = new Date().toISOString().split('T')[0]; // YYYY-MM-DD

            if (periodoInicial === 'diario') {
                $('#periodo_diario').addClass('active');
                const fechaInicial = initialDashboardData?.metadata?.fechaSeleccionada || hoyStr;
                 // Llenar select de fechas ANTES de intentar seleccionar valor
                const selectFecha = $('#fecha_seleccion');
                const hoyDt = new Date();
                const meses = ["Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"];
                selectFecha.empty();
                for (let i = 0; i <= 15; i++) {
                    let fechaIter = new Date();
                    fechaIter.setDate(hoyDt.getDate() - i);
                    let diaNum = String(fechaIter.getDate()).padStart(2, '0');
                    let mesNum = String(fechaIter.getMonth() + 1).padStart(2, '0');
                    let anio = fechaIter.getFullYear();
                    let valor = `${anio}-${mesNum}-${diaNum}`;
                    let texto = `${diaNum} de ${meses[fechaIter.getMonth()]}`;
                    selectFecha.append(new Option(texto, valor));
                }
                // Ahora sí, seleccionar el valor
                 if ($('#fecha_seleccion option[value="' + fechaInicial + '"]').length > 0) {
                     $('#fecha_seleccion').val(fechaInicial);
                 } else {
                      $('#fecha_seleccion').val(hoyStr); // Fallback si la fecha inicial no está en las opciones
                 }

                 $('#mes_seleccion').val(mesActual); // Poner mes actual aunque esté oculto

            } else { // Default a mensual
                $('#periodo_mensual').addClass('active');
                const mesInicialNum = initialDashboardData?.metadata?.mesNumero || mesActual;
                $('#mes_seleccion').val(mesInicialNum);

                 // Llenar select de fechas y seleccionar hoy aunque esté oculto
                 const selectFecha = $('#fecha_seleccion');
                 const hoyDt = new Date();
                 const meses = ["Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"];
                 selectFecha.empty();
                 for (let i = 0; i <= 15; i++) { /* ... bucle ... */
                    let fechaIter = new Date(); fechaIter.setDate(hoyDt.getDate() - i);
                    let diaNum = String(fechaIter.getDate()).padStart(2, '0'); let mesNum = String(fechaIter.getMonth() + 1).padStart(2, '0'); let anio = fechaIter.getFullYear();
                    let valor = `${anio}-${mesNum}-${diaNum}`; let texto = `${diaNum} de ${meses[fechaIter.getMonth()]}`;
                    selectFecha.append(new Option(texto, valor));
                 }
                 $('#fecha_seleccion').val(hoyStr);
            }


            actualizarSelects(); // Ajusta visibilidad inicial

            // 3. Asignar Event Handlers para FILTROS
            $('.periodo-btn').on('click', function () {
                if ($(this).hasClass('active')) return;
                $('.periodo-btn').removeClass('active');
                $(this).addClass('active');
                actualizarSelects();
                actualizarVista();
            });

            $('#mes_seleccion, #fecha_seleccion').on('change', function () {
              
                   actualizarVista();
            
            });
            $('#producto, #cliente').on('change', function () {
            let periodoActivo = $('.periodo-btn.active').attr('id');
             console.log(periodoActivo);
                if(periodoActivo =='periodo_actual'){
                   actualizarVistaActual();
                }else{
                  actualizarVista(); 
                }
            });    
        });      
        // --- ========================================== ---
        // --- == FUNCIONES DE GRÁFICOS (COMPLETAS) == ---
        // --- ========================================== ---

        function solicitudesTotales(dataGrafico) {
            const containerId = 'solicitudesTotales'; const container = document.getElementById(containerId);
            const hasData = dataGrafico && Array.isArray(dataGrafico.categories) && dataGrafico.categories.length > 0 && Array.isArray(dataGrafico.series) && dataGrafico.series.length > 0;
            if (!hasData) { container.innerHTML = `
                <div class="grafico-sin-datos position-relative border rounded p-3" style="min-height: 200px;">
                <div class="position-absolute top-0 start-0 p-2">
                    <small class="text fs-7 pe-2 text-uppercase">Solicitudes totales</small>
                </div>
                <div class="d-flex flex-column justify-content-center align-items-center h-100">
                    <i class="bi bi-bar-chart-line  fs-1"></i>
                    <h6 class="mt-2">Sin datos de solicitudes</h6>
                </div>
                </div>
            `; return; }
            Highcharts.chart(containerId, {
                chart: { type: 'column', backgroundColor: 'white' }, title: { text: `SOLICITUDES TOTALES<br/><span style="font-size: 12px; font-weight: normal;">${subtituloGlobal || mesConsultadoGlobal}</span>`, align: 'left', style: { fontSize: '15px', fontWeight: 'bold' }, margin: 30 },
                xAxis: { categories: dataGrafico.categories, labels: { style: { fontSize: '10px' } } }, yAxis: { min: 0, title: { text: 'Cantidad', style: { fontSize: '10px' } }, labels: { style: { fontSize: '10px' } }, gridLineColor: '#e6e6e6' },
                legend: { enabled: true, itemStyle: { fontSize: '10px', fontWeight: 'normal' } }, plotOptions: { column: { stacking: 'normal', borderWidth: 0, pointPadding: 0.1, groupPadding: 0.1 } },
                series: dataGrafico.series.map(s => ({ name: s.name, data: s.data, color: s.name === 'Aciertos' ? '#34A853' : (s.name === 'Errores' ? '#EA4335' : undefined) })),
                credits: { enabled: false }, tooltip: { shared: true }
            });
        }

        function TasaAciertos(dataGrafico) {
            const containerId = 'TortaPorcentaje'; const container = document.getElementById(containerId);
            const hasData = dataGrafico && Array.isArray(dataGrafico.seriesData) && dataGrafico.seriesData.length > 0 && dataGrafico.seriesData.some(p => p.y > 0);
            if (!hasData) { container.innerHTML = `
            <div class="grafico-sin-datos position-relative border rounded p-3" style="min-height: 200px;">
            <div class="position-absolute top-0 start-0 p-2">
                <small class="text fs-7 pe-2 text-uppercase">Tasa de errores y aciertos</small>
            </div>
            <div class="d-flex flex-column justify-content-center align-items-center h-100">
                <i class="bi bi-pie-chart fs-1"></i>
                <h6 class="mt-2">Sin datos aciertos/errores</h6>
            </div>
            </div>
            `; return; }
            Highcharts.chart(containerId, {
                chart: { type: 'pie', backgroundColor: 'white' }, title: { text: `ACIERTOS vs ERRORES<br/><span style="font-size: 12px; font-weight: normal;">${mesConsultadoGlobal}</span>`, align: 'left', style: { fontSize: '15px', fontWeight: 'bold' } },
                tooltip: { pointFormat: '{series.name}: <b>{point.percentage:.1f}%</b> ({point.y:,.0f})' },
                plotOptions: { pie: { allowPointSelect: true, cursor: 'pointer', dataLabels: { enabled: true, format: '{point.name}<br>{point.percentage:.1f} %', style: { fontSize: '11px', textOutline: 'none' } }, showInLegend: true, colors: ['#34A853', '#EA4335'] } },
                series: [{ name: 'Porcentaje', colorByPoint: true, data: dataGrafico.seriesData }],
                legend: { itemStyle: { fontSize: '10px', fontWeight: 'normal' } }, credits: { enabled: false }
            });
        }

        function apisConsumo(dataGrafico) {
            const containerId = 'apisConsumo'; const container = document.getElementById(containerId);
            const hasData = dataGrafico && Array.isArray(dataGrafico.categories) && dataGrafico.categories.length > 0 && Array.isArray(dataGrafico.series) && dataGrafico.series[0]?.data?.length > 0;
            if (!hasData) { container.innerHTML = `
                <div class="grafico-sin-datos position-relative border rounded p-3" style="min-height: 200px;">
                <div class="position-absolute top-0 start-0 p-2">
                    <small class="text fs-7 pe-2 text-uppercase">APIs con mayor consumo*</small>
                </div>
                <div class="d-flex flex-column justify-content-center align-items-center h-100">
                    <i class="bi bi-bar-chart-steps  fs-1"></i>
                    <h6 class="mt-2">Sin datos consumo API</h6>
                </div>
                </div>
            `; return; }
            let data = dataGrafico.categories.map((cat, i) => ({ name: cat, y: dataGrafico.series[0].data[i] })).sort((a, b) => b.y - a.y).slice(0, 5);
            Highcharts.chart(containerId, {
                chart: { type: 'bar', backgroundColor: 'white' }, title: { text: `TOP 5 APIs CON MAYOR CONSUMO*<br/><span style="font-size: 12px; font-weight: normal;">${mesConsultadoGlobal}</span>`, align: 'left', style: { fontSize: '15px', fontWeight: 'bold' } },
                caption: { text: '*Incluye solo aciertos', align: 'left', style: { fontSize: '10px', color: '#666' } }, xAxis: { categories: data.map(d => d.name), labels: { style: { fontSize: '10px' } } },
                yAxis: { title: { text: null }, labels: { enabled: false }, gridLineWidth: 0 }, legend: { enabled: false },
                plotOptions: { bar: { dataLabels: { enabled: true, format: '{y:,.0f}', style: { fontSize: '10px', fontWeight: 'normal', textOutline: 'none' } }, pointPadding: 0.1, groupPadding: 0.1 } },
                series: [{ name: dataGrafico.series[0]?.name || 'Consumos', data: data.map(d => d.y), colorByPoint: true, colors: ['#4285F4', '#FBBC05', '#34A853', '#EA4335', '#673AB7'] }],
                credits: { enabled: false }
            });
        }

        function clientesConsumo(dataGrafico) {
            const containerId = 'clientesConsumo'; const container = document.getElementById(containerId);
            const hasData = dataGrafico && Array.isArray(dataGrafico.categories) && dataGrafico.categories.length > 0 && Array.isArray(dataGrafico.series) && dataGrafico.series[0]?.data?.length > 0;
            if (!hasData) { container.innerHTML = `
            <div class="grafico-sin-datos position-relative border rounded p-3" style="min-height: 200px;">
            <div class="position-absolute top-0 start-0 p-2">
                <small class="text fs-7 pe-2 text-uppercase">Clientes con mayor consumo*</small>
            </div>
            <div class="d-flex flex-column justify-content-center align-items-center h-100">
                <i class="bi bi-people  fs-1"></i>
                <h6 class="mt-2">Sin datos consumo Cliente</h6>
            </div>
            </div>
            `; return; }
            let data = dataGrafico.categories.map((cat, i) => ({ name: cat, y: dataGrafico.series[0].data[i] })).filter(d => d.y > 0).sort((a, b) => b.y - a.y).slice(0, 5);
            if (data.length === 0) { container.innerHTML = `<div class="grafico-sin-datos"><i class="bi bi-people fs-1"></i><h6>Sin consumo por Cliente</h6></div>`; return; }
            Highcharts.chart(containerId, {
                chart: { type: 'bar', backgroundColor: 'white' }, title: { text: `TOP 5 CLIENTES CON MAYOR CONSUMO*<br/><span style="font-size: 12px; font-weight: normal;">${mesConsultadoGlobal}</span>`, align: 'left', style: { fontSize: '15px', fontWeight: 'bold' } },
                caption: { text: '*Incluye solo aciertos', align: 'left', style: { fontSize: '10px', color: '#666' } }, xAxis: { categories: data.map(d => d.name), labels: { style: { fontSize: '10px' } } },
                yAxis: { title: { text: null }, labels: { enabled: false }, gridLineWidth: 0 }, legend: { enabled: false },
                plotOptions: { bar: { dataLabels: { enabled: true, format: '{y:,.0f}', style: { fontSize: '10px', fontWeight: 'normal', textOutline: 'none' } }, pointPadding: 0.1, groupPadding: 0.1 } },
                series: [{ name: dataGrafico.series[0]?.name || 'Consumos', data: data.map(d => d.y), colorByPoint: true, colors: ['#4285F4', '#FBBC05', '#34A853', '#EA4335', '#673AB7'].reverse() }],
                credits: { enabled: false }
            });
        }

        function TiempoProcesamiento(dataGrafico){
            const containerId = 'TiempoProcesamiento'; const container = document.getElementById(containerId);
            const hasData = dataGrafico && Array.isArray(dataGrafico.categories) && dataGrafico.categories.length > 0 && Array.isArray(dataGrafico.series) && dataGrafico.series.length > 0;
            if (!hasData) { container.innerHTML = `
            <div class="grafico-sin-datos position-relative border rounded p-3" style="min-height: 200px;">
            <div class="position-absolute top-0 start-0 p-2">
                <small class="text fs-7 pe-2 text-uppercase">Tiempo de procesamiento</small>
            </div>
            <div class="d-flex flex-column justify-content-center align-items-center h-100">
                <i class="bi bi-clock-history fs-1"></i>
                <h6 class="mt-2">Sin datos tiempo proc.</h6>
            </div>
            </div>`; return; }
            Highcharts.chart(containerId, {
                chart: { type: 'column', backgroundColor: 'white' }, title: { text: `TIEMPO PROCESAMIENTO PROMEDIO<br/><span style="font-size: 12px; font-weight: normal;">${subtituloGlobal || mesConsultadoGlobal}</span>`, align: 'left', style: { fontSize: '15px', fontWeight: 'bold' }, margin: 30 },
                xAxis: { categories: dataGrafico.categories, labels: { style: { fontSize: '10px' } } }, yAxis: { min: 0, title: { text: 'Segundos', style: { fontSize: '10px' } }, labels: { style: { fontSize: '10px' }, format: '{value:.2f}s' }, gridLineColor: '#e6e6e6' },
                legend: { enabled: dataGrafico.series.length > 1, itemStyle: { fontSize: '10px', fontWeight: 'normal' } }, plotOptions: { line: { marker: { enabled: true, radius: 3 }, lineWidth: 2 } },
                series: dataGrafico.series, credits: { enabled: false }, tooltip: { shared: true, valueSuffix: ' s', valueDecimals: 3 }
            });
        }

        function TasadeErrores(dataGrafico){
            const containerId = 'TasadeErrores'; const container = document.getElementById(containerId);
            const hasData = dataGrafico && Array.isArray(dataGrafico.categories) && dataGrafico.categories.length > 0 && Array.isArray(dataGrafico.series) && dataGrafico.series.length > 0;
            if (!hasData) { container.innerHTML = `
                <div class="grafico-sin-datos position-relative border rounded p-3" style="min-height: 200px;">
                <div class="position-absolute top-0 start-0 p-2">
                    <small class="text fs-7 pe-2 text-uppercase">Tasa de errores</small>
                </div>
                <div class="d-flex flex-column justify-content-center align-items-center h-100">
                    <i class="bi bi-graph-down-arrow  fs-1"></i>
                    <h6 class="mt-2">Sin datos consumo API</h6>
                </div>
                </div>
            `; return; }
            Highcharts.chart(containerId, {
                chart: { type: 'column', backgroundColor: 'white' }, title: { text: `ERRORES POR TIPO<br/><span style="font-size: 12px; font-weight: normal;">${subtituloGlobal || mesConsultadoGlobal}</span>`, align: 'left', style: { fontSize: '15px', fontWeight: 'bold' }, margin: 30 },
                xAxis: { categories: dataGrafico.categories, labels: { style: { fontSize: '10px' } } }, yAxis: { min: 0, title: { text: 'Cantidad', style: { fontSize: '10px' } }, labels: { style: { fontSize: '10px' } }, gridLineColor: '#e6e6e6', stackLabels: { enabled: true, style: { fontSize: '9px', color: '#555', textOutline: 'none' }, format: '{total:,.0f}' } },
                legend: { enabled: true, itemStyle: { fontSize: '10px', fontWeight: 'normal' } }, plotOptions: { column: { stacking: 'normal', borderWidth: 0, pointPadding: 0.1, groupPadding: 0.1 } },
                series: dataGrafico.series, colors: ['#EA4335', '#FBBC05', '#673AB7', '#4285F4', '#34A853'],
                credits: { enabled: false }, tooltip: { shared: true }
            });
        }

        function ApimasErrores(dataGrafico){
            console.log(dataGrafico);
            const containerId = 'ApimasErrores';
            const container = document.getElementById(containerId);
            const hasData = dataGrafico && Array.isArray(dataGrafico.categories) && dataGrafico.categories.length > 0 && Array.isArray(dataGrafico.series) && dataGrafico.series.some(s => Array.isArray(s.data) && s.data.some(d => d > 0));
            if (!hasData) { container.innerHTML = `
                <div class="grafico-sin-datos position-relative border rounded p-3" style="min-height: 200px;">
                <div class="position-absolute top-0 start-0 p-2">
                    <small class="text fs-7 pe-2 text-uppercase">APIs con mas errores</small>
                </div>
                <div class="d-flex flex-column justify-content-center align-items-center h-100">
                    <i class="bi bi-bug fs-1"></i>
                    <h6 class="mt-2">Sin datos APIs con errores</h6>
                </div>
                </div>
            `; return; }
            Highcharts.chart(containerId, {
                chart: { type: 'bar', backgroundColor: 'white' }, title: { text: `TOP APIs CON MÁS ERRORES<br/><span style="font-size: 12px; font-weight: normal;">${mesConsultadoGlobal}</span>`, align: 'left', style: { fontSize: '15px', fontWeight: 'bold' } },
                xAxis: { categories: dataGrafico.categories, labels: { style: { fontSize: '10px' } }, max: 4 }, yAxis: { min: 0, title: { text: null }, labels: { enabled: false }, gridLineWidth: 0, stackLabels: { enabled: true, style: { fontSize: '9px', color: '#555', textOutline: 'none' }, format: '{total:,.0f}' } },
                legend: { enabled: true, reversed: true, itemStyle: { fontSize: '10px', fontWeight: 'normal' } },
                plotOptions: { bar: { stacking: 'normal', pointPadding: 0.1, groupPadding: 0.1 }, series: { dataLabels: { enabled: false } } },
                series: dataGrafico.series, colors: ['#EA4335', '#FBBC05', '#673AB7', '#4285F4', '#34A853'],
                credits: { enabled: false }, tooltip: { shared: true }
            });
        }

        function codigoResp(dataGrafico){
            const containerId = 'CodigosResp'; const container = document.getElementById(containerId);
            const hasData = dataGrafico && Array.isArray(dataGrafico.categories) && dataGrafico.categories.length > 0 && Array.isArray(dataGrafico.series) && dataGrafico.series[0]?.data?.length > 0;
            if (!hasData) { container.innerHTML = `
                <div class="grafico-sin-datos position-relative border rounded p-3" style="min-height: 200px;">
                <div class="position-absolute top-0 start-0 p-2">
                    <small class="text fs-7 pe-2 text-uppercase">Códigos de respuesta</small>
                </div>
                <div class="d-flex flex-column justify-content-center align-items-center h-100">
                    <i class="bi bi-hdd-stack fs-1"></i>
                    <h6 class="mt-2">Sin datos códigos resp.</h6>
                </div>
                </div>
                `; return; }
            let data = dataGrafico.categories.map((cat, i) => ({ name: cat || 'N/A', y: dataGrafico.series[0].data[i] })).sort((a, b) => b.y - a.y).slice(0, 5);
            Highcharts.chart(containerId, {
                chart: { type: 'bar', backgroundColor: 'white' }, title: { text: `TOP 5 CÓDIGOS DE RESPUESTA<br/><span style="font-size: 12px; font-weight: normal;">${mesConsultadoGlobal}</span>`, align: 'left', style: { fontSize: '15px', fontWeight: 'bold' } },
                xAxis: { categories: data.map(d => d.name), labels: { style: { fontSize: '10px' } } }, yAxis: { title: { text: null }, labels: { enabled: false }, gridLineWidth: 0 },
                legend: { enabled: false }, plotOptions: { bar: { dataLabels: { enabled: true, format: '{y:,.0f}', style: { fontSize: '10px', fontWeight: 'normal', textOutline: 'none' } }, pointPadding: 0.1, groupPadding: 0.1 } },
                series: [{ name: dataGrafico.series[0]?.name || 'Cantidad', data: data.map(d => d.y), colorByPoint: true, colors: ['#4285F4', '#FBBC05', '#34A853', '#EA4335', '#673AB7'] }],
                credits: { enabled: false }
            });
        }

        function ApismasLentas(dataGrafico){
            const containerId = 'ApismasLentas'; const container = document.getElementById(containerId);
            const hasData = dataGrafico && Array.isArray(dataGrafico.categories) && dataGrafico.categories.length > 0 && Array.isArray(dataGrafico.series) && dataGrafico.series[0]?.data?.length > 0;
            if (!hasData) { container.innerHTML = `
                <div class="grafico-sin-datos position-relative border rounded p-3" style="min-height: 200px;">
                <div class="position-absolute top-0 start-0 p-2">
                    <small class="text fs-7 pe-2 text-uppercase">APIs más lentas</small>
                </div>
                <div class="d-flex flex-column justify-content-center align-items-center h-100">
                    <i class="bi bi-hourglass-split fs-1"></i>
                    <h6 class="mt-2">Sin datos APIs lentas</h6>
                </div>
                </div>
                `; return; }
            let data = dataGrafico.categories.map((cat, i) => ({ name: cat, y: dataGrafico.series[0].data[i] })).sort((a, b) => b.y - a.y).slice(0, 5);
            Highcharts.chart(containerId, {
                chart: { type: 'bar', backgroundColor: 'white' }, title: { text: `TOP 5 APIs MÁS LENTAS (Promedio)<br/><span style="font-size: 12px; font-weight: normal;">${mesConsultadoGlobal}</span>`, align: 'left', style: { fontSize: '15px', fontWeight: 'bold' } },
                xAxis: { categories: data.map(d => d.name), labels: { style: { fontSize: '10px' } } }, yAxis: { title: { text: null }, labels: { enabled: false }, gridLineWidth: 0 },
                legend: { enabled: false }, plotOptions: { bar: { dataLabels: { enabled: true, format: '{y:.3f} s', style: { fontSize: '10px', fontWeight: 'normal', textOutline: 'none' } }, pointPadding: 0.1, groupPadding: 0.1 } },
                series: [{ name: dataGrafico.series[0]?.name || 'Segundos', data: data.map(d => d.y), colorByPoint: true, colors: ['#EA4335', '#FBBC05', '#673AB7','#4285F4', '#34A853'] }],
                credits: { enabled: false }, tooltip: { valueSuffix: ' s', valueDecimals: 3 }
            });
        }

        function DistriProce(dataGrafico){
            const containerId = 'DistriProce'; const container = document.getElementById(containerId);
            const hasData = dataGrafico && Array.isArray(dataGrafico.categories) && dataGrafico.categories.length > 0 && Array.isArray(dataGrafico.series) && dataGrafico.series[0]?.data?.length > 0 && dataGrafico.series[0].data.some(y=>y>0);
            if (!hasData) { container.innerHTML = `
            <div class="grafico-sin-datos position-relative border rounded p-3" style="min-height: 200px;">
            <div class="position-absolute top-0 start-0 p-2">
                <small class="text fs-7 pe-2 text-uppercase">Distribución de tiempos de procesamiento</small>
            </div>
            <div class="d-flex flex-column justify-content-center align-items-center h-100">
                <i class="bi bi-distribute-vertical fs-1"></i>
                <h6 class="mt-2">Sin datos dist. tiempos</h6>
            </div>
            </div>
            `; return; }
            const pieData = dataGrafico.categories.map((label, index) => ({ name: label, y: dataGrafico.series[0].data[index] })).filter(d => d.y > 0);
            Highcharts.chart(containerId, {
                chart: { type: 'pie', backgroundColor: 'white' }, title: { text: `DISTRIBUCIÓN TIEMPOS<br/><span style="font-size: 12px; font-weight: normal;">${mesConsultadoGlobal}</span>`, align: 'left', style: { fontSize: '15px', fontWeight: 'bold' } },
                tooltip: { pointFormat: '{series.name}: <b>{point.percentage:.1f}%</b> ({point.y:,.0f})' },
                plotOptions: { pie: { allowPointSelect: true, cursor: 'pointer', dataLabels: { enabled: true, format: '{point.name}<br>{point.percentage:.1f} %', style: { fontSize: '11px', textOutline: 'none' } }, showInLegend: true } },
                series: [{ name: dataGrafico.series[0]?.name || 'Cantidad', colorByPoint: true, data: pieData, colors: ['#34A853', '#FBBC05', '#4285F4', '#EA4335', '#673AB7'] }],
                legend: { itemStyle: { fontSize: '10px', fontWeight: 'normal' } }, credits: { enabled: false }
            });
        }

        function Heatmap(dataGrafico) {
            const containerId = 'UptimeHeatmap';
            const container = document.getElementById(containerId);

            if (!container) {
                console.error(`Contenedor del Heatmap con ID '${containerId}' no encontrado.`);
                return;
            }

            const isValidHeatmapData = dataGrafico &&
                typeof dataGrafico.monthName === 'string' &&
                typeof dataGrafico.daysInMonth === 'number' && dataGrafico.daysInMonth > 0 &&
                Array.isArray(dataGrafico.services) &&
                dataGrafico.services.length > 0 &&
                dataGrafico.services.every(service =>
                    typeof service.name === 'string' &&
                    typeof service.overallUptime === 'number' && // Necesitamos overallUptime para la etiqueta Y
                    Array.isArray(service.dailyData) &&
                    service.dailyData.length === dataGrafico.daysInMonth
                );

            if (!isValidHeatmapData) {
                container.innerHTML = `
                    <div class="grafico-sin-datos" style="text-align:center; padding:20px; color:#777;">
                        <i class="bi bi-grid-3x3-gap-fill fs-1" style="font-size: 3rem !important; display:block; margin-bottom:10px;"></i>
                        <h6>Sin datos válidos de Uptime para mostrar</h6>
                    </div>`;
                return;
            }

            const yAxisCategories = []; // No se usa directamente para las categorías, pero sí para el mapeo en tooltip
            const seriesDataForHeatmap = [];
            const serviceDetailsForYAxis = {}; // Para construir las etiquetas del eje Y

            dataGrafico.services.forEach((service, serviceIndex) => {
                yAxisCategories.push(service.name); // Para el tooltip y mapeo
                serviceDetailsForYAxis[service.name] = { // Para el formatter del yAxis
                    overallUptime: service.overallUptime,
                    monthName: dataGrafico.monthName // El nombre del mes viene de la raíz de dataGrafico
                };
                service.dailyData.forEach((value, dayIndex) => {
                    seriesDataForHeatmap.push([dayIndex, serviceIndex, value]);
                });
            });

            // Las categorías del eje Y se manejarán con el formatter
            const yCategoriesForChart = dataGrafico.services.map(s => s.name);
            const xAxisCategories = Array.from({ length: dataGrafico.daysInMonth }, (_, i) => (i + 1).toString());


            Highcharts.chart(containerId, {
                chart: {
                    type: 'heatmap',
                    backgroundColor: 'white',
                    marginTop: 0, // Reducimos si el título principal está fuera o es simple
                    marginBottom: 0, // Reducimos porque la leyenda va fuera
                    plotBorderWidth: 0, // Borde controlado por plotOptions
                    height: (yAxisCategories.length * 94) ,  // Ajusta 55px por fila, 60px para márgenes y título
                    style: {
                        fontFamily: '"Helvetica Neue", Helvetica, Arial, sans-serif' // Fuente similar a la imagen
                    }
                },
                title: { // Título superior del gráfico (podría estar fuera del chart en tu UI)
                    text: null, 
                },
                xAxis: {
                    categories: xAxisCategories,
                    labels: { enabled: false },
                    tickWidth: 0,
                    lineWidth: 0,
                    opposite: true // Mueve el eje arriba si tuviera etiquetas, como en la imagen
                },
                yAxis: {
                    categories: yCategoriesForChart, // Nombres de los servicios
                    title: null,
                    reversed: true,
                    labels: {
                        useHTML: true,
                        align: 'left', // Alinea el contenedor de la etiqueta a la izquierda
                        x: 0,          // Ajuste de posición horizontal
                        formatter: function () {
                            const serviceName = this.value; // Nombre del servicio
                            const details = serviceDetailsForYAxis[serviceName];
                            if (details) {
                                return `  <div class="ms-2 mb-5 pb-3" style="display: flex; align-items: center; width: 100%; padding-right: 5px;">
                                            <span class="mt-2 pe-5 text fs-7 pe-2 text-uppercase" style="font-size: 12px; color:rgb(0, 0, 0); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; flex-shrink: 1; ">
                                                UPTIME ${serviceName.toUpperCase()} - ${details.monthName.toUpperCase()}
                                            </span>
                                           <span class="mt-2" style="font-size: 10px; color: #555e69; font-weight: normal; white-space: nowrap; margin-left: auto; flex-shrink: 0;">
                                                ${(details.overallUptime).toFixed(2).replace('.', ',')}%
                                                
                                            </span>
                                        </div>`;
                            
                            }
                            return serviceName;
                        },
                    },
                    gridLineWidth: 1, // Línea divisoria horizontal
                    gridLineColor: '#f3f4f6', // Color de la línea divisoria más sutil
                    tickWidth: 0,
                    lineWidth: 0,
                },
                colorAxis: {
                    dataClasses: [
                        // Colores tomados de tu imagen
                        { to: 96, color: '#ef4444', name: 'Menos del 96%' }, // Rojo
                        { from: 96, to: 98, color: '#f97316', name: '96% a 98%' }, // Naranja
                        { from: 98, color: '#22c55e', name: '98% a 100%' }  // Verde
                    ],
                    nullColor: '#e5e7eb', // Gris para "No hay datos" (similar a tu imagen)
                },
                legend: {
                    enabled: false // Deshabilitamos la leyenda automática, la crearemos con HTML
                },
                tooltip: {
                    formatter: function () {
                        const day = this.point.x + 1; // Día del mes (1-indexado)
                        // Usamos yAxisCategories que tiene los nombres puros para el tooltip
                        const serviceName = yAxisCategories[this.point.y];
                        const month = dataGrafico.monthName.charAt(0).toUpperCase() + dataGrafico.monthName.slice(1).toLowerCase();

                        return this.point.value === null
                            ? `Día ${day} ${month}<br/>${serviceName}: No hay datos`
                            : `Día ${day} ${month}<br/>${serviceName}: ${this.point.value.toFixed(2)}%`;
                    }
                },
                plotOptions: {
                    heatmap: {
                        borderWidth: 3, // Espacio entre bloques (ajusta según tu preferencia)
                        borderColor: 'white', // Color del espacio (fondo del gráfico)
                        borderRadius: 2,      // Bordes de los bloques ligeramente redondeados
                        colsize: 0.9,         // Ajusta el tamaño de las columnas si es necesario
                        rowsize: 0.30,         // Ajusta el tamaño de las filas (altura de los bloques)
                        dataLabels: { enabled: false },
                        states: {
                            hover: {
                                enabled: false // Deshabilitar efecto hover si no se desea
                                // brightness: -0.1
                            }
                        }
                    }
                },
                series: [{
                    name: 'Uptime',
                    data: seriesDataForHeatmap,
                    // No se necesita `keys` aquí si los datos ya están en formato [x, y, value]
                }],
                credits: { enabled: false }
            });

            // 4. Añadir leyenda personalizada en HTML (similar a tu imagen de referencia)
            // Eliminar leyenda anterior si existe para evitar duplicados al recargar datos
            const existingLegend = container.querySelector('.custom-heatmap-legend-container');
            if (existingLegend) {
                existingLegend.remove();
            }

            const legendContainer = document.createElement('div');
            legendContainer.className = 'custom-heatmap-legend-container';
            legendContainer.style.cssText = `
                display: flex;
                justify-content: space-between; /* Para alinear "Ver historial" a la derecha */
                align-items: center;
                padding-top: 10px;
                font-size: 10px;
                color: #555e69;
                background-color:white;
            `;

            const legendItemsHTML = `
                <div class="pb-1" >
                    <span class="ms-3" style="display:inline-block; width:10px; height:10px; background-color:#22c55e; border-radius:2px; margin-right:3px; vertical-align:middle;"></span> 98% a 100%
                    <span style="display:inline-block; width:10px; height:10px; background-color:#f97316; border-radius:2px; margin-left:8px; margin-right:3px; vertical-align:middle;"></span> 96% a 98%
                    <span style="display:inline-block; width:10px; height:10px; background-color:#ef4444; border-radius:2px; margin-left:8px; margin-right:3px; vertical-align:middle;"></span> Menos del 96%
                    <span style="display:inline-block; width:10px; height:10px; background-color:#e5e7eb; border-radius:2px; margin-left:8px; margin-right:3px; vertical-align:middle;"></span> No hay datos
                </div>
            `;


            legendContainer.innerHTML = legendItemsHTML ;
            container.appendChild(legendContainer);
        }

    </script>
@endsection