
'use client';

import { useState, useEffect, useRef, useCallback } from 'react';
import { Search, MapPin, Ruler, Trash2, Pentagon, Minus, Square, ZoomIn, ZoomOut, Move, Hand } from 'lucide-react';
import { Input } from '@/components/ui/input';
import { Button } from '@/components/ui/button';
import { Card } from '@/components/ui/card';
import { Label } from '@/components/ui/label';
import { toast } from 'sonner';
import { Badge } from '@/components/ui/badge';
import { Slider } from '@/components/ui/slider';
import { Switch } from '@/components/ui/switch';

interface GoogleMapsSearchProps {
  initialAddress?: string;
  onLocationSelect?: (location: { address: string; lat: number; lng: number }) => void;
  onAreaMeasured?: (area: number) => void;
  onLineMeasured?: (length: number) => void;
  onAddressUsed?: () => void;
  contingency?: number;
  onContingencyChange?: (value: number) => void;
  measurementUnit?: 'metric' | 'imperial';
  onMeasurementUnitChange?: (unit: 'metric' | 'imperial') => void;
}

type DrawingMode = 'polygon' | 'polyline' | 'rectangle' | null;

export function GoogleMapsSearch({ 
  initialAddress, 
  onLocationSelect, 
  onAreaMeasured, 
  onLineMeasured,
  onAddressUsed,
  contingency = 5,
  onContingencyChange,
  measurementUnit = 'metric',
  onMeasurementUnitChange
}: GoogleMapsSearchProps) {
  const [searchQuery, setSearchQuery] = useState(initialAddress || '');
  const [isMapReady, setIsMapReady] = useState(false);
  const [drawingMode, setDrawingMode] = useState<DrawingMode>(null);
  const [isPanMode, setIsPanMode] = useState(true); // Default to pan mode
  const [localContingency, setLocalContingency] = useState(contingency);
  const [localMeasurementUnit, setLocalMeasurementUnit] = useState(measurementUnit);
  const mapRef = useRef<HTMLDivElement>(null);
  const mapInstanceRef = useRef<any>(null);
  const drawingManagerRef = useRef<any>(null);
  const overlaysRef = useRef<any[]>([]);
  const hasAutoSearched = useRef(false);

  // Unit conversion functions
  const metersToFeet = (meters: number) => meters * 3.28084;
  const sqMetersToSqFeet = (sqMeters: number) => sqMeters * 10.7639;

  const convertMeasurement = useCallback((value: number, isArea: boolean = true) => {
    if (localMeasurementUnit === 'imperial') {
      return isArea ? sqMetersToSqFeet(value) : metersToFeet(value);
    }
    return value;
  }, [localMeasurementUnit]);

  const getUnitLabel = useCallback((isArea: boolean = true) => {
    if (localMeasurementUnit === 'imperial') {
      return isArea ? 'sq ft' : 'ft';
    }
    return isArea ? 'sq m' : 'm';
  }, [localMeasurementUnit]);

  // Load Google Maps Script with geometry library
  useEffect(() => {
    if (typeof window !== 'undefined' && !(window as any).google) {
      const script = document.createElement('script');
      script.src = `https://maps.googleapis.com/maps/api/js?key=${process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY || ''}&libraries=drawing,places,geometry`;
      script.async = true;
      script.defer = true;
      script.onload = () => initializeMap();
      document.head.appendChild(script);
    } else if ((window as any).google) {
      initializeMap();
    }
  }, []);

  const applyContingency = useCallback((value: number) => {
    return value * (1 + localContingency / 100);
  }, [localContingency]);

  const handleContingencyChange = (value: number[]) => {
    setLocalContingency(value[0]);
    if (onContingencyChange) {
      onContingencyChange(value[0]);
    }
  };

  const handleMeasurementUnitChange = (checked: boolean) => {
    const newUnit = checked ? 'imperial' : 'metric';
    setLocalMeasurementUnit(newUnit);
    if (onMeasurementUnitChange) {
      onMeasurementUnitChange(newUnit);
    }
    toast.success(`Switched to ${newUnit === 'metric' ? 'Metric (meters)' : 'Imperial (feet)'}`);
  };

  const initializeMap = useCallback(() => {
    if (!mapRef.current || mapInstanceRef.current) return;

    try {
      const g = (window as any).google;
      if (!g) return;

      // Initialize map with enhanced controls
      const map = new g.maps.Map(mapRef.current, {
        center: { lat: -33.8688, lng: 151.2093 }, // Sydney default
        zoom: 19,
        mapTypeId: g.maps.MapTypeId.SATELLITE,
        tilt: 0,
        draggable: true, // Allow panning by default
        // Enable all controls for better navigation
        zoomControl: true,
        zoomControlOptions: {
          position: g.maps.ControlPosition.RIGHT_CENTER
        },
        streetViewControl: false,
        mapTypeControl: true,
        mapTypeControlOptions: {
          position: g.maps.ControlPosition.TOP_RIGHT,
          style: g.maps.MapTypeControlStyle.DROPDOWN_MENU,
          mapTypeIds: [
            g.maps.MapTypeId.SATELLITE,
            g.maps.MapTypeId.HYBRID,
            g.maps.MapTypeId.ROADMAP
          ]
        },
        fullscreenControl: true,
        fullscreenControlOptions: {
          position: g.maps.ControlPosition.RIGHT_TOP
        },
        // Improve precision
        gestureHandling: 'greedy',
        // Enable rotation and tilt for better perspective
        rotateControl: true,
        scaleControl: true
      });

      mapInstanceRef.current = map;

      // Initialize drawing manager with precise options
      const drawingManager = new g.maps.drawing.DrawingManager({
        drawingMode: null,
        drawingControl: false,
        polygonOptions: {
          fillColor: '#2196F3',
          fillOpacity: 0.4,
          strokeWeight: 3,
          strokeColor: '#1976D2',
          clickable: true,
          editable: true,
          draggable: false,
          geodesic: true, // More accurate for large areas
        },
        polylineOptions: {
          strokeColor: '#FF6B6B',
          strokeWeight: 4,
          clickable: true,
          editable: true,
          draggable: false,
          geodesic: true,
        },
        rectangleOptions: {
          fillColor: '#4CAF50',
          fillOpacity: 0.4,
          strokeWeight: 3,
          strokeColor: '#2E7D32',
          clickable: true,
          editable: true,
          draggable: false,
        },
      });

      drawingManager.setMap(map);
      drawingManagerRef.current = drawingManager;

      // Listen for polygon complete
      g.maps.event.addListener(drawingManager, 'polygoncomplete', (polygon: any) => {
        overlaysRef.current.push(polygon);
        const rawAreaMeters = g.maps.geometry.spherical.computeArea(polygon.getPath());
        const areaWithContingencyMeters = applyContingency(rawAreaMeters);
        
        // Convert based on unit preference
        const rawArea = convertMeasurement(rawAreaMeters, true);
        const areaWithContingency = convertMeasurement(areaWithContingencyMeters, true);
        const unitLabel = getUnitLabel(true);
        
        if (onAreaMeasured) {
          onAreaMeasured(areaWithContingencyMeters); // Always send meters to parent
        }

        // Stop drawing mode after completing and enable pan mode
        drawingManager.setDrawingMode(null);
        setDrawingMode(null);
        setIsPanMode(true);
        if (mapInstanceRef.current) {
          mapInstanceRef.current.setOptions({ draggable: true, gestureHandling: 'greedy' });
        }

        toast.success(
          `Area measured: ${rawArea.toFixed(2)} ${unitLabel} (Raw)\n` +
          `With ${localContingency}% contingency: ${areaWithContingency.toFixed(2)} ${unitLabel}`
        );
      });

      // Listen for polyline complete (for linear measurements like gutters)
      g.maps.event.addListener(drawingManager, 'polylinecomplete', (polyline: any) => {
        overlaysRef.current.push(polyline);
        const rawLengthMeters = g.maps.geometry.spherical.computeLength(polyline.getPath());
        const lengthWithContingencyMeters = applyContingency(rawLengthMeters);
        
        // Convert based on unit preference
        const rawLength = convertMeasurement(rawLengthMeters, false);
        const lengthWithContingency = convertMeasurement(lengthWithContingencyMeters, false);
        const unitLabel = getUnitLabel(false);
        
        if (onLineMeasured) {
          onLineMeasured(lengthWithContingencyMeters); // Always send meters to parent
        }

        // Stop drawing mode after completing and enable pan mode
        drawingManager.setDrawingMode(null);
        setDrawingMode(null);
        setIsPanMode(true);
        if (mapInstanceRef.current) {
          mapInstanceRef.current.setOptions({ draggable: true, gestureHandling: 'greedy' });
        }

        toast.success(
          `Length measured: ${rawLength.toFixed(2)} ${unitLabel} (Raw)\n` +
          `With ${localContingency}% contingency: ${lengthWithContingency.toFixed(2)} ${unitLabel}`
        );
      });

      // Listen for rectangle complete
      g.maps.event.addListener(drawingManager, 'rectanglecomplete', (rectangle: any) => {
        overlaysRef.current.push(rectangle);
        const bounds = rectangle.getBounds();
        const ne = bounds.getNorthEast();
        const sw = bounds.getSouthWest();
        
        // Calculate area of rectangle
        const rawAreaMeters = g.maps.geometry.spherical.computeArea([
          ne,
          { lat: ne.lat(), lng: sw.lng() },
          sw,
          { lat: sw.lat(), lng: ne.lng() },
        ]);
        const areaWithContingencyMeters = applyContingency(rawAreaMeters);
        
        // Convert based on unit preference
        const rawArea = convertMeasurement(rawAreaMeters, true);
        const areaWithContingency = convertMeasurement(areaWithContingencyMeters, true);
        const unitLabel = getUnitLabel(true);
        
        if (onAreaMeasured) {
          onAreaMeasured(areaWithContingencyMeters); // Always send meters to parent
        }

        // Stop drawing mode after completing and enable pan mode
        drawingManager.setDrawingMode(null);
        setDrawingMode(null);
        setIsPanMode(true);
        if (mapInstanceRef.current) {
          mapInstanceRef.current.setOptions({ draggable: true, gestureHandling: 'greedy' });
        }

        toast.success(
          `Area measured: ${rawArea.toFixed(2)} ${unitLabel} (Raw)\n` +
          `With ${localContingency}% contingency: ${areaWithContingency.toFixed(2)} ${unitLabel}`
        );
      });

      setIsMapReady(true);
    } catch (error) {
      console.error('Error initializing map:', error);
      toast.error('Failed to initialize Google Maps');
    }
  }, [onAreaMeasured, onLineMeasured, localContingency, applyContingency]);

  const handleSearch = useCallback(async () => {
    if (!searchQuery.trim() || !mapInstanceRef.current) return;

    try {
      const g = (window as any).google;
      if (!g) return;

      const geocoder = new g.maps.Geocoder();
      const result = await geocoder.geocode({ address: searchQuery });

      if (result.results && result.results.length > 0) {
        const location = result.results[0].geometry.location;
        const address = result.results[0].formatted_address;

        mapInstanceRef.current.setCenter(location);
        mapInstanceRef.current.setZoom(20);

        // Add marker
        new g.maps.Marker({
          position: location,
          map: mapInstanceRef.current,
          title: address,
        });

        if (onLocationSelect) {
          onLocationSelect({
            address,
            lat: location.lat(),
            lng: location.lng(),
          });
        }

        toast.success('Location found!');
        
        // Notify that the address has been used
        if (onAddressUsed) {
          onAddressUsed();
        }
      } else {
        toast.error('Location not found');
      }
    } catch (error) {
      console.error('Geocoding error:', error);
      toast.error('Failed to search location');
    }
  }, [searchQuery, onLocationSelect, onAddressUsed]);

  // Auto-search when initialAddress is provided and map is ready
  useEffect(() => {
    if (isMapReady && initialAddress && !hasAutoSearched.current) {
      hasAutoSearched.current = true;
      setSearchQuery(initialAddress);
      
      // Small delay to ensure map is fully ready
      setTimeout(() => {
        if (mapInstanceRef.current) {
          const g = (window as any).google;
          if (!g) return;

          const geocoder = new g.maps.Geocoder();
          geocoder.geocode({ address: initialAddress }, (results: any, status: any) => {
            if (status === 'OK' && results && results.length > 0) {
              const location = results[0].geometry.location;
              const address = results[0].formatted_address;

              mapInstanceRef.current.setCenter(location);
              mapInstanceRef.current.setZoom(20);

              // Add marker
              new g.maps.Marker({
                position: location,
                map: mapInstanceRef.current,
                title: address,
              });

              if (onLocationSelect) {
                onLocationSelect({
                  address,
                  lat: location.lat(),
                  lng: location.lng(),
                });
              }

              toast.success('Customer address loaded on map!');
              
              if (onAddressUsed) {
                onAddressUsed();
              }
            }
          });
        }
      }, 500);
    }
  }, [isMapReady, initialAddress, onLocationSelect, onAddressUsed]);

  const activateDrawingMode = useCallback((mode: DrawingMode) => {
    if (!drawingManagerRef.current || !mapInstanceRef.current) {
      console.error('Drawing manager or map not initialized');
      toast.error('Map not ready. Please wait a moment and try again.');
      return;
    }

    const g = (window as any).google;
    if (!g || !g.maps || !g.maps.drawing) {
      console.error('Google Maps drawing library not loaded');
      toast.error('Drawing tools not loaded. Please refresh the page.');
      return;
    }

    if (drawingMode === mode) {
      // Deactivate if clicking the same mode - return to pan mode
      drawingManagerRef.current.setDrawingMode(null);
      setDrawingMode(null);
      setIsPanMode(true);
      mapInstanceRef.current.setOptions({ 
        draggable: true,
        gestureHandling: 'greedy'
      });
      toast.info('Drawing mode disabled - Pan mode active');
    } else {
      // Activate the selected mode and disable pan
      let googleMode = null;
      let message = '';
      
      switch (mode) {
        case 'polygon':
          googleMode = g.maps.drawing.OverlayType.POLYGON;
          message = 'Polygon tool active! Click on the map to add points. Double-click to finish.';
          break;
        case 'polyline':
          googleMode = g.maps.drawing.OverlayType.POLYLINE;
          message = 'Line tool active! Click on the map to add points. Double-click to finish.';
          break;
        case 'rectangle':
          googleMode = g.maps.drawing.OverlayType.RECTANGLE;
          message = 'Rectangle tool active! Click and drag to draw a rectangle.';
          break;
      }
      
      if (googleMode) {
        // First disable pan mode completely
        setIsPanMode(false);
        mapInstanceRef.current.setOptions({ 
          draggable: false,
          gestureHandling: 'none'  // This prevents all touch/drag gestures
        });
        
        // Then activate drawing mode
        drawingManagerRef.current.setDrawingMode(googleMode);
        setDrawingMode(mode);
        
        toast.info(message);
        console.log(`Drawing mode activated: ${mode}`, googleMode);
      }
    }
  }, [drawingMode]);

  const togglePanMode = useCallback(() => {
    if (!mapInstanceRef.current || !drawingManagerRef.current) return;

    if (drawingMode) {
      // If in drawing mode, deactivate it first
      drawingManagerRef.current.setDrawingMode(null);
      setDrawingMode(null);
    }

    // Toggle pan mode
    const newPanMode = !isPanMode;
    setIsPanMode(newPanMode);
    mapInstanceRef.current.setOptions({ 
      draggable: newPanMode,
      gestureHandling: newPanMode ? 'greedy' : 'none'
    });
    
    toast.info(newPanMode ? 'Pan mode enabled - Click and drag to move map' : 'Pan mode disabled');
  }, [isPanMode, drawingMode]);

  const clearMeasurements = useCallback(() => {
    overlaysRef.current.forEach(overlay => overlay.setMap(null));
    overlaysRef.current = [];
    toast.success('All measurements cleared');
  }, []);

  const handleZoomIn = () => {
    if (mapInstanceRef.current) {
      const currentZoom = mapInstanceRef.current.getZoom();
      mapInstanceRef.current.setZoom(currentZoom + 1);
    }
  };

  const handleZoomOut = () => {
    if (mapInstanceRef.current) {
      const currentZoom = mapInstanceRef.current.getZoom();
      mapInstanceRef.current.setZoom(currentZoom - 1);
    }
  };

  return (
    <Card className="p-4 space-y-4">
      {/* Search Bar */}
      <div className="flex gap-2">
        <div className="flex-1 relative">
          <Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-muted-foreground w-4 h-4" />
          <Input
            value={searchQuery}
            onChange={(e) => setSearchQuery(e.target.value)}
            onKeyDown={(e) => e.key === 'Enter' && handleSearch()}
            placeholder="Search for an address..."
            className="pl-10"
          />
        </div>
        <Button onClick={handleSearch} variant="secondary">
          <MapPin className="w-4 h-4 mr-2" />
          Search
        </Button>
      </div>

      {/* Settings Section */}
      <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
        {/* Contingency Slider */}
        <div className="space-y-3 p-4 bg-blue-50 dark:bg-blue-950/20 rounded-lg border-2 border-blue-200 dark:border-blue-800">
          <div className="flex items-center justify-between">
            <Label className="text-sm font-semibold text-blue-900 dark:text-blue-100">
              Measurement Contingency
            </Label>
            <Badge variant="default" className="bg-blue-600">
              {localContingency}%
            </Badge>
          </div>
          <Slider
            value={[localContingency]}
            onValueChange={handleContingencyChange}
            min={1}
            max={15}
            step={0.5}
            className="w-full"
          />
          <p className="text-xs text-blue-700 dark:text-blue-300">
            Adds {localContingency}% to all measurements for better accuracy
          </p>
        </div>

        {/* Unit Switcher */}
        <div className="space-y-3 p-4 bg-purple-50 dark:bg-purple-950/20 rounded-lg border-2 border-purple-200 dark:border-purple-800">
          <div className="flex items-center justify-between">
            <Label className="text-sm font-semibold text-purple-900 dark:text-purple-100">
              Measurement Units
            </Label>
            <Badge variant="default" className="bg-purple-600">
              {localMeasurementUnit === 'metric' ? 'Metric' : 'Imperial'}
            </Badge>
          </div>
          <div className="flex items-center justify-between">
            <div className="space-y-0.5">
              <p className="text-sm font-medium text-purple-900 dark:text-purple-100">
                {localMeasurementUnit === 'metric' ? 'Meters (m)' : 'Feet (ft)'}
              </p>
              <p className="text-xs text-purple-700 dark:text-purple-300">
                {localMeasurementUnit === 'metric' ? 'Square meters / Linear meters' : 'Square feet / Linear feet'}
              </p>
            </div>
            <Switch
              checked={localMeasurementUnit === 'imperial'}
              onCheckedChange={handleMeasurementUnitChange}
            />
          </div>
          <p className="text-xs text-purple-700 dark:text-purple-300">
            Toggle to switch between metric and imperial units
          </p>
        </div>
      </div>

      {/* Map Container with Custom Controls */}
      <div className="relative">
        <div ref={mapRef} className="w-full h-[500px] rounded-lg border-2 border-gray-300 dark:border-gray-700" />
        
        {/* Custom Zoom Controls Overlay */}
        <div className="absolute top-4 left-4 flex flex-col gap-2 bg-white dark:bg-gray-800 rounded-lg shadow-lg p-1">
          <Button
            size="sm"
            variant="outline"
            onClick={handleZoomIn}
            disabled={!isMapReady}
            className="w-10 h-10 p-0"
            title="Zoom In"
          >
            <ZoomIn className="w-4 h-4" />
          </Button>
          <Button
            size="sm"
            variant="outline"
            onClick={handleZoomOut}
            disabled={!isMapReady}
            className="w-10 h-10 p-0"
            title="Zoom Out"
          >
            <ZoomOut className="w-4 h-4" />
          </Button>
          <div className="border-t my-1"></div>
          <Button
            size="sm"
            variant={isPanMode ? 'default' : 'outline'}
            onClick={togglePanMode}
            disabled={!isMapReady}
            className="w-10 h-10 p-0"
            title={isPanMode ? 'Pan Mode Active' : 'Enable Pan Mode'}
          >
            <Hand className="w-4 h-4" />
          </Button>
        </div>

        {/* Drawing Mode Indicator */}
        {drawingMode && (
          <div className="absolute top-4 right-4 animate-pulse">
            <Badge variant="default" className="text-sm py-2 px-4 bg-green-600">
              ✏️ Drawing Mode Active - {drawingMode === 'polygon' ? 'Polygon' : drawingMode === 'polyline' ? 'Line' : 'Rectangle'}
            </Badge>
          </div>
        )}
      </div>

      {/* Drawing Tools */}
      <div className="space-y-3">
        <div className="flex items-center justify-between">
          <Label className="text-sm font-medium">Professional Measuring Tools</Label>
          <Badge variant="secondary" className="text-xs">
            {overlaysRef.current.length} measurements
          </Badge>
        </div>
        
        <div className="grid grid-cols-3 gap-2">
          <Button
            onClick={() => activateDrawingMode('polygon')}
            variant={drawingMode === 'polygon' ? 'default' : 'outline'}
            disabled={!isMapReady}
            className="flex-col h-auto py-3 hover:bg-blue-100 dark:hover:bg-blue-900"
          >
            <Pentagon className="w-5 h-5 mb-1" />
            <span className="text-xs font-semibold">Polygon Tool</span>
            <span className="text-[10px] text-muted-foreground">Roofs/Areas</span>
          </Button>
          
          <Button
            onClick={() => activateDrawingMode('polyline')}
            variant={drawingMode === 'polyline' ? 'default' : 'outline'}
            disabled={!isMapReady}
            className="flex-col h-auto py-3 hover:bg-red-100 dark:hover:bg-red-900"
          >
            <Minus className="w-5 h-5 mb-1" />
            <span className="text-xs font-semibold">Line Tool</span>
            <span className="text-[10px] text-muted-foreground">Gutters/Perimeter</span>
          </Button>
          
          <Button
            onClick={() => activateDrawingMode('rectangle')}
            variant={drawingMode === 'rectangle' ? 'default' : 'outline'}
            disabled={!isMapReady}
            className="flex-col h-auto py-3 hover:bg-green-100 dark:hover:bg-green-900"
          >
            <Square className="w-5 h-5 mb-1" />
            <span className="text-xs font-semibold">Rectangle Tool</span>
            <span className="text-[10px] text-muted-foreground">Quick Select</span>
          </Button>
        </div>

        {/* Instructions */}
        <div className="bg-gray-50 dark:bg-gray-900 p-3 rounded-lg text-xs space-y-1">
          <p className="font-semibold text-gray-900 dark:text-gray-100">📏 How to Measure:</p>
          <ul className="list-disc list-inside space-y-1 text-gray-700 dark:text-gray-300">
            <li><strong>Polygon:</strong> Click points on the map, double-click to finish</li>
            <li><strong>Line:</strong> Click to draw lines, double-click to complete</li>
            <li><strong>Rectangle:</strong> Click and drag to draw a rectangle</li>
            <li><strong>Pan:</strong> Click and drag the map to move around</li>
            <li>All shapes are <strong>editable</strong> after drawing - drag vertices to adjust</li>
          </ul>
        </div>

        <Button
          onClick={clearMeasurements}
          variant="outline"
          disabled={overlaysRef.current.length === 0}
          className="w-full"
        >
          <Trash2 className="w-4 h-4 mr-2" />
          Clear All Measurements ({overlaysRef.current.length})
        </Button>
      </div>

      {!process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY && (
        <div className="bg-yellow-50 border border-yellow-200 rounded-lg p-3">
          <p className="text-sm text-yellow-800">
            ⚠️ Google Maps API key not configured. Please add NEXT_PUBLIC_GOOGLE_MAPS_API_KEY to your environment variables.
          </p>
        </div>
      )}
    </Card>
  );
}
