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<BusETA[]>([]);
    const cargando = ref<boolean>(false);

    // Configuración para el cálculo del ETA mejorado
    const VELOCIDAD_PROMEDIO_KMH = 30; // km/h (promedio ciudad/carretera)
    const TIEMPO_PARADA_SEGUNDOS = 45; // segundos detenido por parada

    // Fórmula Haversine para distancia en línea recta (km)
    function getDistanceKm(lat1: number, lon1: number, lat2: number, lon2: number): number {
        const R = 6371;
        const dLat = (lat2 - lat1) * (Math.PI / 180);
        const dLon = (lon2 - lon1) * (Math.PI / 180);
        const a =
            Math.sin(dLat / 2) * Math.sin(dLat / 2) +
            Math.cos(lat1 * (Math.PI / 180)) * Math.cos(lat2 * (Math.PI / 180)) *
            Math.sin(dLon / 2) * Math.sin(dLon / 2);
        const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
        return R * c;
    }

    const calcularETA = async (ruta_id: string, parada_cercana: BusStop | null) => {
        cargando.value = true;
        busesActivos.value = [];

        try {
            // OPTIMIZACIÓN: PASO 1 - Verificar horarios primero (más rápido que cálculos geo)
            // Esto permite dar feedback instantáneo de "No hay buses" sin esperar a la ubicación
            const diaActual = new Date().getDay();
            const dias = ['domingo', 'lunes', 'martes', 'miercoles', 'jueves', 'viernes', 'sabado'];
            const diaString = dias[diaActual];
            const normalizar = (s: string | null | undefined) => (s || "").toLowerCase().trim().normalize("NFD").replace(/[\u0300-\u036f]/g, "");
            const diaStringNorm = normalizar(diaString);
            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;

            const horariosHoy = (horarios ?? []).filter(h => {
                const diasOP = h.dias_operacion as string[] | null;
                if (diasOP && Array.isArray(diasOP) && diasOP.length > 0) {
                    return diasOP.some(d => {
                        const dNorm = normalizar(d);
                        return dNorm === 'todos' || dNorm === diaStringNorm;
                    });
                }
                const stNorm = normalizar(h.schedule_type);
                return stNorm === tipoDia || stNorm === 'todos' || !h.schedule_type;
            });

            if (horariosHoy.length === 0) {
                busesActivos.value = [];
                return;
            }

            // PASO 2: Obtener detalles de la ruta y todas sus paradas para calcular distancia
            let minutosHastaParada = 0;

            if (parada_cercana) {
                const [routeRes, stopsRes] = await Promise.all([
                    supabase
                        .from('routes')
                        .select('distance_km, average_speed_kmh, estimated_duration_minutes')
                        .eq('id', ruta_id)
                        .single(),
                    supabase
                        .from('route_stops')
                        .select('stop_id, stop_order, bus_stops(latitude, longitude)')
                        .eq('route_id', ruta_id)
                        .order('stop_order', { ascending: true })
                ]);

                if (!routeRes.error && stopsRes.data) {
                    const routeData = routeRes.data;
                    const routeStops = stopsRes.data;
                    const targetStopIndex = routeStops.findIndex(s => s.stop_id === parada_cercana.id);

                    if (targetStopIndex !== -1) {
                        let distanciaAcumuladaKm = 0;
                        for (let i = 0; i < targetStopIndex; i++) {
                            const stopA = routeStops[i];
                            const stopB = routeStops[i + 1];
                            const start = stopA ? (stopA.bus_stops as any) : null;
                            const end = stopB ? (stopB.bus_stops as any) : null;
                            if (start?.latitude != null && start?.longitude != null &&
                                end?.latitude != null && end?.longitude != null) {
                                distanciaAcumuladaKm += getDistanceKm(start.latitude, start.longitude, end.latitude, end.longitude);
                            }
                        }
                        distanciaAcumuladaKm *= 1.2;
                        const velocidad = routeData.average_speed_kmh || VELOCIDAD_PROMEDIO_KMH;

                        // Si la ruta tiene una duración estimada en BD, la usamos como base para el trayecto total
                        // y calculamos la proporción según la parada.
                        if (routeData.estimated_duration_minutes && routeData.distance_km) {
                            // Bug fix: No multiplicar el denominador por 1.2 si distance_km ya es la distancia real
                            const proporcionDistancia = Math.min(distanciaAcumuladaKm / routeData.distance_km, 1.0);
                            minutosHastaParada = routeData.estimated_duration_minutes * proporcionDistancia;
                        } else {
                            const tiempoViajeMinutos = (distanciaAcumuladaKm / velocidad) * 60;
                            const numeroParadas = targetStopIndex;
                            const tiempoParadasMinutos = (numeroParadas * TIEMPO_PARADA_SEGUNDOS) / 60;
                            minutosHastaParada = tiempoViajeMinutos + tiempoParadasMinutos;
                        }
                    }
                }
            }

            // PASO 3: Calcular ETA para cada salida
            const ahora = new Date();
            const minutosAhora = ahora.getHours() * 60 + ahora.getMinutes();
            const resultados: BusETA[] = [];

            for (const h of horariosHoy) {
                const salida = h.departure_time;
                if (!salida) continue;

                const [hStr, mStr] = salida.split(':');
                const minutosSalida = parseInt(hStr) * 60 + parseInt(mStr);

                const minutosTransitoBase = minutosHastaParada;
                const minutosLlegadaEstablecidos = minutosSalida + minutosTransitoBase;
                const etaMinutos = minutosLlegadaEstablecidos - minutosAhora;

                // Logging para depuración (solo en desarrollo)
                if (import.meta.env.DEV) {
                    console.log(`SIB | Bus ${salida}: Ahora=${minutosAhora}, Salida=${minutosSalida}, LlegadaEst=${minutosLlegadaEstablecidos}, ETA=${Math.round(etaMinutos)}`);
                }

                const horaLlegada = format12h(minutosLlegadaEstablecidos);
                const horaSalidaFormato = format12h(minutosSalida);

                let estado: BusETA['estado'];
                const busYaSalio = minutosAhora >= minutosSalida;

                if (etaMinutos > 5) {
                    estado = busYaSalio ? 'en_camino' : 'próximo';
                } else {
                    estado = 'en_camino';
                }

                // Filtrar buses que ya pasaron (ETA < 0)
                // Solo mostramos buses a los que el usuario tiene posibilidad de llegar
                if (etaMinutos < 0) continue;

                resultados.push({
                    horario_id: h.id,
                    hora_salida: horaSalidaFormato,
                    horaLlegadaParada: horaLlegada,
                    etaMinutos: Math.round(etaMinutos),
                    estado
                });
            }

            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;
            });

            busesActivos.value = resultados.slice(0, 5);
        } catch (e) {
            console.error('SIB | Error calculando ETA:', e);
        } finally {
            cargando.value = false;
        }
    };

    // Helper: convierte minutos desde medianoche a formato 12h (hh:mm am/pm)
    function format12h(minutos: number): string {
        const totalMinutes = Math.round(minutos);
        const m = ((totalMinutes % 1440) + 1440) % 1440; // normalizar 0-1439
        let h = Math.floor(m / 60);
        const min = Math.floor(m % 60);
        const ampm = h >= 12 ? 'PM' : 'AM';
        const h12 = h % 12 || 12;
        return `${h12}:${String(min).padStart(2, '0')} ${ampm}`;
    }

    return { calcularETA, busesActivos, cargando };
}
