import { ref } from 'vue'; import { supabase } from '@/supabase'; import type { BusStop } from '@/types'; export interface BusETA { horario_id: string; hora_salida: string; // "HH:mm" para mostrar en UI horaLlegadaParada: string; // "HH:mm" hora estimada de llegada a la parada etaMinutos: number; // minutos hasta que llega (negativo = ya pasó) estado: 'próximo' | 'en_camino' | 'pasó'; } export function useETA() { const busesActivos = ref([]); const cargando = ref(false); const calcularETA = async (ruta_id: string, parada_cercana: BusStop) => { cargando.value = true; busesActivos.value = []; try { // PASO 1: Obtener travel_time_minutes de la parada del usuario // desde route_stops usando el stop_id de la parada cercana const { data: routeStopData, error: rsError } = await supabase .from('route_stops') .select('travel_time_minutes, stop_order, stop_delay_minutes') .eq('route_id', ruta_id) .eq('stop_id', parada_cercana.id) .single(); if (rsError || !routeStopData) { console.warn('SIBU | No se encontró travel_time para la parada:', parada_cercana.name); return; } // Tiempo total hasta la parada del usuario en minutos const minutosHastaParada = (routeStopData.travel_time_minutes ?? 0) + (routeStopData.stop_delay_minutes ?? 0); // PASO 2: Obtener horarios activos para hoy const diaActual = new Date().getDay(); const dias = ['domingo', 'lunes', 'martes', 'miercoles', 'jueves', 'viernes', 'sabado']; const diaString = dias[diaActual]; const tipoDia = (diaActual === 0 || diaActual === 6) ? 'weekend' : 'weekday'; const { data: horarios, error: hError } = await supabase .from('bus_schedules') .select('id, departure_time, dias_operacion, schedule_type') .eq('route_id', ruta_id) .eq('is_active', true) .eq('is_published', true); if (hError) throw hError; // Filtrar horarios que operan hoy const horariosHoy = (horarios ?? []).filter(h => { if (h.dias_operacion) { return h.dias_operacion.includes('todos') || h.dias_operacion.includes(diaString); } return h.schedule_type === tipoDia || h.schedule_type === 'todos' || !h.schedule_type; }); // PASO 3: Calcular ETA para cada horario const ahora = new Date(); const minutosAhora = ahora.getHours() * 60 + ahora.getMinutes(); const resultados: BusETA[] = []; for (const h of horariosHoy) { const salida = h.departure_time; // "HH:mm:ss" if (!salida) continue; // Parsear hora de salida a minutos desde medianoche const [hStr, mStr] = salida.split(':'); const minutosSalida = parseInt(hStr) * 60 + parseInt(mStr); // ── FÓRMULA PRINCIPAL ──────────────────────────── // Hora de llegada del bus a la parada del usuario: const minutosLlegadaParada = minutosSalida + minutosHastaParada; // ETA = cuántos minutos faltan desde ahora: const etaMinutos = minutosLlegadaParada - minutosAhora; // ───────────────────────────────────────────────── // Formatear hora de llegada para mostrar en UI const horaLlegada = minutosAHora(minutosLlegadaParada); const horaSalidaFormato = `${hStr.padStart(2, '0')}:${mStr.padStart(2, '0')}`; // Determinar estado let estado: BusETA['estado']; if (etaMinutos > 5) { // Bus aún no llega a la parada // Verificar si ya salió del terminal o no const yaPartio = minutosAhora >= minutosSalida; estado = yaPartio ? 'en_camino' : 'próximo'; } else if (etaMinutos >= -2) { // Llegando ahora (ventana de ±2 minutos) estado = 'en_camino'; } else { // Ya pasó la parada estado = 'pasó'; } // No incluir buses que pasaron hace más de 60 minutos if (etaMinutos < -60) continue; resultados.push({ horario_id: h.id, hora_salida: horaSalidaFormato, horaLlegadaParada: horaLlegada, etaMinutos: Math.round(etaMinutos), estado }); } // PASO 4: Ordenar resultados // Prioridad: en_camino → próximo → pasó // Dentro de cada grupo: menor ETA primero resultados.sort((a, b) => { const prioridad = { 'en_camino': 0, 'próximo': 1, 'pasó': 2 }; if (prioridad[a.estado] !== prioridad[b.estado]) { return prioridad[a.estado] - prioridad[b.estado]; } return a.etaMinutos - b.etaMinutos; }); // Máximo 3 buses busesActivos.value = resultados.slice(0, 3); } catch (e) { console.error('SIBU | Error calculando ETA:', e); } finally { cargando.value = false; } }; // Helper: convierte minutos desde medianoche a "HH:mm" function minutosAHora(minutos: number): string { const m = ((minutos % 1440) + 1440) % 1440; // normalizar 0-1439 const h = Math.floor(m / 60); const min = m % 60; return `${String(h).padStart(2, '0')}:${String(min).padStart(2, '0')}`; } return { calcularETA, busesActivos, cargando }; }