import React, { useState, useEffect, useRef } from 'react';
import { cn } from '../../shared/utils';
import { useGoogleMapsLoader } from '../google-maps-loader';

export interface RouteMapProps extends React.HTMLAttributes<HTMLDivElement> {
  origin: { lat: number; lng: number };
  destination: { lat: number; lng: number };
  waypoints?: Array<{ lat: number; lng: number }>;
  travelMode?: 'DRIVING' | 'WALKING' | 'BICYCLING' | 'TRANSIT';
  height?: string;
  mapId?: string;
  apiKey?: string;
  mapContainerClassName?: string;
  disableDefaultUI?: boolean;
  zoomControl?: boolean;
  streetViewControl?: boolean;
  mapTypeControl?: boolean;
  fullscreenControl?: boolean;
  onRouteCalculated?: (distance: string, duration: string) => void;
}

const RouteMapContent = React.forwardRef<HTMLDivElement, RouteMapProps & { apiKey: string }>(
  ({ apiKey, ...props }, ref) => {
    const { isLoaded, loadError, load } = useGoogleMapsLoader();

    const {
      origin,
      destination,
      waypoints = [],
      travelMode = 'DRIVING',
      height = '450px',
      mapContainerClassName,
      disableDefaultUI = false,
      zoomControl = true,
      streetViewControl = false,
      mapTypeControl = false,
      fullscreenControl = true,
      onRouteCalculated,
      className,
      ...divProps
    } = props;

    const mapRef = useRef<google.maps.Map | null>(null);
    const gmpMapRef = useRef<any>(null); // Ref for custom element
    const directionsRendererRef = useRef<google.maps.DirectionsRenderer | null>(null);
    const iInitializedRef = useRef(false);
    const isCalculatingRef = useRef(false);

    // Initialize map
    useEffect(() => {
      // Load API if needed
      if (!isLoaded && apiKey && !loadError && load) {
        load(apiKey).catch(console.error);
      }
    }, [isLoaded, apiKey, loadError, load]);

    // Handle gmp-map initialization and DirectionsRenderer
    useEffect(() => {
      if (!isLoaded || !gmpMapRef.current) return;

      const setupMap = (map: google.maps.Map) => {
        mapRef.current = map;
        // Create directions renderer
        const computedStyle = getComputedStyle(document.documentElement);
        const primaryColor = computedStyle.getPropertyValue('--primary').trim() || '#4F46E5';

        if (!directionsRendererRef.current) {
          directionsRendererRef.current = new google.maps.DirectionsRenderer({
            map: map,
            suppressMarkers: false,
            polylineOptions: {
              strokeColor: primaryColor,
              strokeWeight: 5,
              strokeOpacity: 0.8,
            },
          });
        } else {
          directionsRendererRef.current.setMap(map);
        }
      };

      const gmpMap = gmpMapRef.current;
      if (gmpMap.innerMap) {
        setupMap(gmpMap.innerMap);
      } else {
        const interval = setInterval(() => {
          if (gmpMap.innerMap) {
            setupMap(gmpMap.innerMap);
            clearInterval(interval);
          }
        }, 100);
        return () => clearInterval(interval);
      }

      return () => {
        if (directionsRendererRef.current) {
          directionsRendererRef.current.setMap(null);
          // Don't nullify renderer here to allow reuse, or recreate
        }
        mapRef.current = null;
      };
    }, [isLoaded]);

    // Sync properties with gmp-map custom element
    useEffect(() => {
      if (gmpMapRef.current && origin) {
        gmpMapRef.current.center = origin;
      }
    }, [origin.lat, origin.lng]);

    useEffect(() => {
      if (gmpMapRef.current) {
        gmpMapRef.current.zoom = 13;
      }
    }, []);

    // mapId is now set declaratively on the gmp-map element

    // Calculate route
    useEffect(() => {
      const map = mapRef.current;
      const renderer = directionsRendererRef.current;

      if (!map || !renderer || !isLoaded || isCalculatingRef.current) return;
      if (!origin || !destination) return;

      isCalculatingRef.current = true;

      const directionsService = new google.maps.DirectionsService();

      const request: google.maps.DirectionsRequest = {
        origin: origin,
        destination: destination,
        waypoints: waypoints.map(wp => ({
          location: wp,
          stopover: true,
        })),
        travelMode: google.maps.TravelMode[travelMode],
      };

      directionsService.route(request, (result, status) => {
        isCalculatingRef.current = false;

        if (status === 'OK' && result) {
          renderer.setDirections(result);

          // Calculate total distance and duration
          const route = result.routes[0];
          if (route?.legs?.length > 0 && onRouteCalculated) {
            let totalDistance = 0;
            let totalDuration = 0;

            route.legs.forEach(leg => {
              if (leg.distance) totalDistance += leg.distance.value;
              if (leg.duration) totalDuration += leg.duration.value;
            });

            const distanceKm = (totalDistance / 1000).toFixed(1);
            const distanceText = `${distanceKm} km`;

            const hours = Math.floor(totalDuration / 3600);
            const minutes = Math.floor((totalDuration % 3600) / 60);
            const durationText = hours > 0 ? `${hours}h ${minutes}min` : `${minutes} min`;

            onRouteCalculated(distanceText, durationText);
          }
        }
      });
    }, [
      isLoaded,
      origin.lat,
      origin.lng,
      destination.lat,
      destination.lng,
      travelMode,
      mapRef.current,
    ]); // Added mapRef.current dep

    if (loadError) {
      // ... (Error state same as before)
      return (
        <div
          ref={ref}
          className={cn(
            'relative rounded-[var(--radius-card)] border border-destructive/50 overflow-hidden bg-destructive/5',
            className
          )}
          style={{ height }}
          {...divProps}
        >
          <div className="absolute inset-0 flex items-center justify-center">
            <div className="text-center space-y-2 p-6">
              <div className="text-destructive">
                <svg
                  className="w-12 h-12 mx-auto"
                  fill="none"
                  stroke="currentColor"
                  viewBox="0 0 24 24"
                >
                  <path
                    strokeLinecap="round"
                    strokeLinejoin="round"
                    strokeWidth={2}
                    d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
                  />
                </svg>
              </div>
              <p className="text-sm font-medium text-foreground">Failed to load Google Maps</p>
              <p className="text-xs text-muted-foreground">Check API key in Settings</p>
            </div>
          </div>
        </div>
      );
    }

    if (!isLoaded) {
      return (
        <div
          ref={ref}
          className={cn(
            'relative rounded-[var(--radius-card)] border border-border overflow-hidden bg-muted animate-pulse',
            className
          )}
          style={{ height }}
          {...divProps}
        />
      );
    }

    return (
      <div
        ref={ref}
        className={cn(
          'relative rounded-[var(--radius-card)] border border-border overflow-hidden',
          className
        )}
        style={{ height }}
        {...divProps}
      >
        {/* @ts-ignore */}
        <gmp-map
          ref={gmpMapRef}
          style={{ height: '100%', width: '100%', display: 'block' }}
          map-id={props.mapId || 'xertica-route-map'}
        />
      </div>
    );
  }
);
RouteMapContent.displayName = 'RouteMapContent';

/**
 * Specialized route display and calculation component for Google Maps.
 *
 * @description
 * Calculates and renders a route between an `origin` and `destination` point
 * using the Google Directions Service. Supports intermediate `waypoints` and
 * multiple `travelMode` options (DRIVING, WALKING, BICYCLING, TRANSIT).
 *
 * @ai-rules
 * 1. Provide `origin` and `destination` as LatLng objects `{ lat, lng }`.
 * 2. Use `onRouteCalculated` to receive the pre-formatted distance and duration strings.
 * 3. `travelMode` accepts 'DRIVING', 'WALKING', 'BICYCLING', or 'TRANSIT'.
 * 4. The Directions API must be enabled on your Google Maps API key.
 */
export const RouteMap = React.forwardRef<HTMLDivElement, RouteMapProps>((props, ref) => {
  const { isLoaded, loadError } = useGoogleMapsLoader();
  const effectiveApiKey =
    props.apiKey ||
    (typeof import.meta !== 'undefined' &&
      import.meta.env &&
      import.meta.env.VITE_GOOGLE_MAPS_API_KEY) ||
    '';

  const isValidKey =
    effectiveApiKey &&
    effectiveApiKey !== 'YOUR_GOOGLE_MAPS_API_KEY_HERE' &&
    effectiveApiKey.startsWith('AIza');

  if (isLoaded || isValidKey || loadError) {
    return <RouteMapContent ref={ref} {...props} apiKey={effectiveApiKey} />;
  }

  // Check if the script is injected in the DOM (loading via provider)
  const isScriptInjected =
    typeof document !== 'undefined' &&
    !!document.querySelector('script[src*="maps.googleapis.com/maps/api/js"]');

  if (isScriptInjected) {
    return <RouteMapContent ref={ref} {...props} apiKey={effectiveApiKey} />;
  }

  const {
    origin,
    destination,
    waypoints,
    travelMode,
    height,
    apiKey,
    mapContainerClassName,
    disableDefaultUI,
    zoomControl,
    streetViewControl,
    mapTypeControl,
    fullscreenControl,
    onRouteCalculated,
    ...divProps
  } = props;

  return (
    <div
      ref={ref}
      className={cn(
        'relative rounded-[var(--radius-card)] border border-border overflow-hidden bg-muted',
        props.className
      )}
      style={{ height: props.height || '450px' }}
      {...divProps}
    >
      <div className="absolute inset-0 flex items-center justify-center bg-gradient-to-br from-muted/50 to-muted">
        <div className="text-center space-y-3 p-6">
          <div className="w-16 h-16 mx-auto bg-primary/10 rounded-full flex items-center justify-center">
            <svg
              className="w-8 h-8 text-primary"
              fill="none"
              stroke="currentColor"
              viewBox="0 0 24 24"
            >
              <path
                strokeLinecap="round"
                strokeLinejoin="round"
                strokeWidth={2}
                d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z"
              />
              <path
                strokeLinecap="round"
                strokeLinejoin="round"
                strokeWidth={2}
                d="M15 11a3 3 0 11-6 0 3 3 0 016 0z"
              />
            </svg>
          </div>
          <p className="text-sm text-muted-foreground">Configure Google Maps API Key in Settings</p>
        </div>
      </div>
    </div>
  );
});
RouteMap.displayName = 'RouteMap';
