import { ref } from 'vue';

import { useMapState } from './useMapState';

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 { registrarPolyline, polylines } = useMapState();

    // Limpia los tramos anteriores dibujados en el mapa
    const limpiarRuta = () => {
        if (polylines.value.length > 0) {
            polylines.value.forEach((polyline) => {
                polyline.setMap(null);
            });
            polylines.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, 
        isPast: boolean = false,
        cancelToken?: { cancelled: boolean }
    ) => {
        if (!paradas || paradas.length < 2) {
            errorRuta.value = 'Se requieren al menos 2 paradas para trazar una ruta.';
            return;
        }

        // NOTA: No llamamos a limpiarRuta() aquí para poder encadenar llamadas (dibujar fondo + trazado activo)
        estasCargando.value = true;
        errorRuta.value = null;

        try {
            const { DirectionsService } = await google.maps.importLibrary("routes") as any;
            const directionsService = new DirectionsService();

            const maxWaypoints = 23; // Google Directions limit is typically 25 including origin/dest

            for (let i = 0; i < paradas.length - 1; i += maxWaypoints) {
                // GUARD: Abortar si la operación fue cancelada durante el delay
                if (cancelToken?.cancelled) break;

                const chunk = paradas.slice(i, i + maxWaypoints + 1);
                if (chunk.length < 2) break;

                const origin = { lat: chunk[0]!.latitud, lng: chunk[0]!.longitud };
                const destination = { lat: chunk[chunk.length - 1]!.latitud, lng: chunk[chunk.length - 1]!.longitud };

                const waypoints = chunk.slice(1, -1).map(p => ({
                    location: new google.maps.LatLng(p.latitud, p.longitud),
                    stopover: true
                }));

                try {
                    const result = await new Promise<google.maps.DirectionsResult>((resolve, reject) => {
                        directionsService.route({
                            origin,
                            destination,
                            waypoints,
                            travelMode: google.maps.TravelMode.DRIVING
                        }, (response: google.maps.DirectionsResult | null, status: google.maps.DirectionsStatus) => {
                            if (status === google.maps.DirectionsStatus.OK && response) {
                                resolve(response);
                            } else {
                                reject(new Error(`Directions API failed: ${status}`));
                            }
                        });
                    });

                    if (result.routes && result.routes.length > 0 && !cancelToken?.cancelled) {
                        const route = result.routes[0];
                        if (route?.overview_path) {
                            const polyline = new google.maps.Polyline({
                                path: route.overview_path,
                                map: map,
                                strokeColor: isPast ? '#9CA3AF' : '#FBBF24',
                                strokeWeight: isPast ? 4 : 6,
                                strokeOpacity: isPast ? 0.6 : 1.0,
                                icons: isPast ? [{
                                    icon: { path: 'M 0,-1 0,1', strokeOpacity: 1, scale: 2 },
                                    offset: '0',
                                    repeat: '10px'
                                }] : []
                            });
                            registrarPolyline(polyline);
                        }
                    }
                } catch (err: any) {
                    console.warn(`SIBU | Tramo ${i} falló con Directions API: `, err);
                }

                if (i + maxWaypoints < paradas.length - 1 && !cancelToken?.cancelled) {
                    await delay(300);
                }
            }
        } catch (err: any) {
            if (!cancelToken?.cancelled) {
                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
    };
}
