/**
 * @ai-summary Google Maps component for station visualization
 */

import React, { useEffect, useRef, useState } from 'react';
import { Box, CircularProgress, Alert } from '@mui/material';
import { Station } from '../types/stations.types';
import { loadGoogleMaps, getGoogleMapsApi } from '../utils/maps-loader';
import {
  createStationMarker,
  createCurrentLocationMarker,
  createInfoWindow,
  fitBoundsToMarkers
} from '../utils/map-utils';
import { getGoogleMapsMapId } from '@/core/config/config.types';

interface StationMapProps {
  stations: Station[];
  savedPlaceIds?: Set<string>;
  center?: { lat: number; lng: number };
  currentLocation?: { latitude: number; longitude: number };
  zoom?: number;
  onMarkerClick?: (station: Station) => void;
  height?: string;
  readyToRender?: boolean;
}

/**
 * Google Maps component showing station markers
 * Responsive height: 300px mobile, 500px desktop
 * Blue markers for normal stations, gold for saved
 */
export const StationMap: React.FC<StationMapProps> = ({
  stations,
  savedPlaceIds = new Set(),
  center,
  currentLocation,
  zoom = 12,
  onMarkerClick,
  height = '500px',
  readyToRender = true
}) => {
  const mapContainer = useRef<HTMLDivElement>(null);
  const map = useRef<google.maps.Map | null>(null);
  const markers = useRef<google.maps.marker.AdvancedMarkerElement[]>([]);
  const infoWindows = useRef<google.maps.InfoWindow[]>([]);
  const currentLocationMarker = useRef<google.maps.marker.AdvancedMarkerElement | null>(null);
  const isInitializing = useRef<boolean>(false);
  const mapIdRef = useRef<string | null>(null);

  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  // Initialize map
  useEffect(() => {
    // Don't initialize if parent says we're not ready
    if (!readyToRender) {
      console.debug('[StationMap] Not ready to render, skipping initialization');
      return;
    }

    const initMap = async () => {
      // Prevent multiple concurrent initializations
      if (isInitializing.current || map.current) {
        console.debug('[StationMap] Already initializing or initialized, skipping');
        return;
      }

      // Wait for container to be fully mounted in DOM
      if (!mapContainer.current || !document.body.contains(mapContainer.current)) {
        console.debug('[StationMap] Container not ready, delaying initialization');
        setTimeout(initMap, 100);
        return;
      }

      isInitializing.current = true;

      try {
        setIsLoading(true);

        // Load Google Maps API
        await loadGoogleMaps();
        const maps = getGoogleMapsApi();

        if (!mapContainer.current || !document.body.contains(mapContainer.current)) {
          console.debug('[StationMap] Container removed during initialization');
          isInitializing.current = false;
          setIsLoading(false);
          return;
        }

        // Create map
        const defaultCenter = center || {
          lat: currentLocation?.latitude || 43.074734,
          lng: currentLocation?.longitude || -89.384271
        };

        if (mapIdRef.current === null) {
          const mapId = getGoogleMapsMapId();
          if (!mapId) {
            console.error(
              '[StationMap] Google Maps Map ID is not configured. Add google-maps-map-id secret to enable advanced markers.'
            );
            setError('Google Maps Map ID is not configured. Please contact support.');
            isInitializing.current = false;
            setIsLoading(false);
            return;
          }
          mapIdRef.current = mapId;
        }

        map.current = new maps.Map(mapContainer.current, {
          zoom,
          center: defaultCenter,
          mapId: mapIdRef.current || undefined,
          mapTypeControl: true,
          streetViewControl: false,
          fullscreenControl: true
        });

        setError(null);
        isInitializing.current = false;
      } catch (err) {
        setError(err instanceof Error ? err.message : 'Failed to load map');
        console.error('Map initialization failed:', err);
        isInitializing.current = false;
      } finally {
        setIsLoading(false);
      }
    };

    // Suppress DOM errors from Google Maps/React conflicts
    const handleError = (event: ErrorEvent) => {
      const errorMsg = event.error?.message || event.message || '';
      const isDomError =
        errorMsg.includes('removeChild') ||
        errorMsg.includes('insertBefore') ||
        errorMsg.includes('replaceChild') ||
        event.error?.name === 'NotFoundError' ||
        (event.error instanceof DOMException);

      if (isDomError) {
        // This is a known issue when Google Maps manipulates DOM nodes React is managing
        // Suppress the error as it doesn't affect functionality
        event.preventDefault();
        event.stopPropagation();
        event.stopImmediatePropagation();
        console.debug('[StationMap] Suppressed harmless Google Maps DOM error:', errorMsg);
      }
    };

    // Suppress unhandled promise rejections from Google Maps DOM conflicts
    const handleRejection = (event: PromiseRejectionEvent) => {
      const errorMsg = event.reason?.message || String(event.reason) || '';
      const isDomError =
        errorMsg.includes('removeChild') ||
        errorMsg.includes('insertBefore') ||
        errorMsg.includes('replaceChild') ||
        event.reason?.name === 'NotFoundError' ||
        (event.reason instanceof DOMException);

      if (isDomError) {
        event.preventDefault();
        console.debug('[StationMap] Suppressed harmless Google Maps promise rejection:', errorMsg);
      }
    };

    window.addEventListener('error', handleError, true);
    window.addEventListener('unhandledrejection', handleRejection, true);

    // Delay initialization to ensure React finishes initial render
    // This prevents race conditions with DOM manipulation
    const initTimer = setTimeout(() => {
      if (readyToRender) {
        initMap();
      }
    }, 50);

    // Cleanup: clear markers when component unmounts
    return () => {
      clearTimeout(initTimer);
      window.removeEventListener('error', handleError, true);
      window.removeEventListener('unhandledrejection', handleRejection, true);
      isInitializing.current = false;

      // Defensive cleanup - Google Maps may have already removed these elements
      try {
        if (map.current && (window as any).google?.maps?.event) {
          // Stop any pending operations
          (window as any).google.maps.event.clearInstanceListeners(map.current);
          map.current = null;
        }
      } catch (err) {
        // Ignore - map may already be destroyed
      }

      try {
        markers.current.forEach((marker) => {
          try {
            marker.map = null;
          } catch (e) {
            // Ignore individual marker cleanup errors
          }
        });
        markers.current = [];
      } catch (err) {
        console.debug('[StationMap] Marker cleanup error (ignored):', err);
      }

      try {
        infoWindows.current.forEach((iw) => {
          try {
            iw.close();
          } catch (e) {
            // Ignore individual info window cleanup errors
          }
        });
        infoWindows.current = [];
      } catch (err) {
        console.debug('[StationMap] InfoWindow cleanup error (ignored):', err);
      }

      try {
        if (currentLocationMarker.current) {
          currentLocationMarker.current.map = null;
          currentLocationMarker.current = null;
        }
      } catch (err) {
        // Ignore current location marker cleanup errors
      }
    };
  }, [readyToRender]);

  // Update markers when stations or saved status changes
  useEffect(() => {
    if (!map.current) return;

    // Don't update markers during initialization
    if (isInitializing.current) {
      console.debug('[StationMap] Skipping marker update during initialization');
      return;
    }

    try {
      // Verify Google Maps API is available
      if (!(window as any).google?.maps) {
        console.warn('[StationMap] Google Maps API not available, skipping marker update');
        return;
      }

      // Clear old markers and info windows
      markers.current.forEach((marker) => {
        marker.map = null;
      });
      infoWindows.current.forEach((iw) => iw.close());
      markers.current = [];
      infoWindows.current = [];

      getGoogleMapsApi();
      const allMarkers: google.maps.marker.AdvancedMarkerElement[] = [];

    // Add station markers
    stations.forEach((station) => {
      const isSaved = savedPlaceIds.has(station.placeId);
      const marker = createStationMarker(station, map.current!, isSaved);
      const infoWindow = createInfoWindow(station, isSaved);

      markers.current.push(marker);
      infoWindows.current.push(infoWindow);
      allMarkers.push(marker);

      // Add click listener
      marker.addListener('click', () => {
        // Close all other info windows
        infoWindows.current.forEach((iw) => iw.close());

        // Open this one
        infoWindow.open({
          anchor: marker,
          map: map.current!,
          shouldFocus: false
        });
        onMarkerClick?.(station);
      });
    });

    // Add current location marker
    if (currentLocation) {
      if (currentLocationMarker.current) {
        currentLocationMarker.current.map = null;
      }

      currentLocationMarker.current = createCurrentLocationMarker(
        currentLocation.latitude,
        currentLocation.longitude,
        map.current
      );
      allMarkers.push(currentLocationMarker.current);
    }

      // Fit bounds to show all markers
      if (allMarkers.length > 0) {
        fitBoundsToMarkers(map.current, allMarkers);
      }
    } catch (error) {
      // Ignore DOM errors from Google Maps conflicting with React reconciliation
      // This is a known issue when Google Maps removes DOM nodes that React still has references to
      if (error instanceof Error && error.message.includes('removeChild')) {
        console.warn('[StationMap] Ignoring Google Maps DOM conflict:', error.message);
        return;
      }
      // Re-throw other errors
      throw error;
    }
  }, [stations, savedPlaceIds, currentLocation, onMarkerClick]);

  if (error) {
    return (
      <Box
        sx={{
          height,
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
          padding: 2
        }}
      >
        <Alert severity="error">{error}</Alert>
      </Box>
    );
  }

  return (
    <Box
      sx={{
        position: 'relative',
        height,
        width: '100%',
        borderRadius: 1,
        overflow: 'hidden',
        backgroundColor: 'grey.300'
      }}
    >
      <Box
        ref={mapContainer}
        sx={{
          position: 'absolute',
          inset: 0,
          width: '100%',
          height: '100%'
        }}
      />

      {isLoading && (
        <Box
          sx={{
            position: 'absolute',
            top: '50%',
            left: '50%',
            transform: 'translate(-50%, -50%)',
            zIndex: 1
          }}
        >
          <CircularProgress />
        </Box>
      )}
    </Box>
  );
};

export default StationMap;
