import { ref } from 'vue';

export interface Parada {
    id: number;
    nombre: string;
    latitud: number;
    longitud: number;
    orden: number;
}

export function useDirectionsRoute() {
    const estasCargando = ref<boolean>(false);
    const errorRuta = ref<string | null>(null);
    const renderizadoresActivos = ref<google.maps.DirectionsRenderer[]>([]);

    // Limpia los tramos anteriores dibujados en el mapa
    const limpiarRuta = () => {
        if (renderizadoresActivos.value.length > 0) {
            renderizadoresActivos.value.forEach((renderer) => {
                renderer.setMap(null);
            });
            renderizadoresActivos.value = [];
        }
        errorRuta.value = null;
    };

    // Función utilitaria para pausar ejecución
    const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));

    const trazarRuta = async (paradas: Parada[], map: google.maps.Map) => {
        if (!paradas || paradas.length < 2) {
            errorRuta.value = 'Se requieren al menos 2 paradas para trazar una ruta.';
            return;
        }

        limpiarRuta();
        estasCargando.value = true;
        errorRuta.value = null;

        try {
            const directionsService = new google.maps.DirectionsService();
            // Límite de la API de Google Maps: Origen, Destino, y hasta 23 waypoints (25 puntos total por request)
            const maxPuntosPorChunk = 25;
            const overlaps = 1;

            // Iteramos sobre las paradas dividiéndolas en chunks con 1 punto en común ("overlap")
            // para asegurar que las secciones se conecten correctamente.
            for (let i = 0; i < paradas.length - 1; i += (maxPuntosPorChunk - overlaps)) {
                const chunk = paradas.slice(i, i + maxPuntosPorChunk);

                // Si el chunk es muy pequeño (último fragmento o vector final), detenemos
                if (chunk.length < 2) break;

                const origen = new google.maps.LatLng(chunk[0]!.latitud, chunk[0]!.longitud);
                const destino = new google.maps.LatLng(chunk[chunk.length - 1]!.latitud, chunk[chunk.length - 1]!.longitud);

                // Excluimos el primero y último para que sean los waypoints intermedios
                const waypoints: google.maps.DirectionsWaypoint[] = chunk.slice(1, -1).map(p => ({
                    location: new google.maps.LatLng(p.latitud, p.longitud),
                    stopover: true
                }));

                const request: google.maps.DirectionsRequest = {
                    origin: origen,
                    destination: destino,
                    waypoints: waypoints,
                    travelMode: google.maps.TravelMode.DRIVING,
                    optimizeWaypoints: false
                };

                try {
                    const response = await directionsService.route(request);

                    const renderer = new google.maps.DirectionsRenderer({
                        map: map,
                        suppressMarkers: true, // SIBU maneja los suyos propios
                        preserveViewport: true, // No auto centrar en cada tramo para evitar parpadeos visuales
                        polylineOptions: {
                            strokeColor: '#1E40AF', // Azul (Tailwind blue-800)
                            strokeWeight: 5,
                            strokeOpacity: 0.8
                        }
                    });

                    renderer.setDirections(response);
                    renderizadoresActivos.value.push(renderer);

                } catch (err: any) {
                    console.warn(`SIBU | Tramo ${i} falló: `, err);
                    // La ruta continúa renderizando los siguientes tramos disponibles, no paramos todo.
                }

                // Retardo para evitar sobrecargar a la API y el error "OVER_QUERY_LIMIT"
                await delay(300);
            }
        } catch (err: any) {
            errorRuta.value = `Error crítico al trazar la ruta: ${err.message || String(err)}`;
            console.error(errorRuta.value);
        } finally {
            estasCargando.value = false;
        }
    };

    return {
        trazarRuta,
        limpiarRuta,
        estasCargando,
        errorRuta
    };
}
